mirror of
https://github.com/honmashironeko/ProxyCat.git
synced 2025-11-05 10:51:06 +00:00
Update
This commit is contained in:
parent
4b4e62ca51
commit
2e83336f97
@ -51,7 +51,12 @@ async def run_server(server):
|
||||
clients = set()
|
||||
server_instance = None
|
||||
try:
|
||||
server_instance = await asyncio.start_server(lambda r, w: handle_client_wrapper(server, r, w, clients),'0.0.0.0', int(server.config['port']))
|
||||
server_instance = await asyncio.start_server(
|
||||
lambda r, w: handle_client_wrapper(server, r, w, clients),
|
||||
'0.0.0.0',
|
||||
int(server.config['port']),
|
||||
limit=256 * 1024
|
||||
)
|
||||
async with server_instance:
|
||||
await server_instance.serve_forever()
|
||||
except asyncio.CancelledError:
|
||||
|
||||
50
README-EN.md
50
README-EN.md
@ -202,10 +202,15 @@ Through actual testing, when proxy server performance is sufficient, ProxyCat ca
|
||||
|
||||
## Change Log
|
||||
|
||||
### 2025/01/07
|
||||
|
||||
- Added caching mechanism to proxy detection module to prevent frequent checks
|
||||
- Optimized error handling and logging
|
||||
|
||||
### 2025/01/03
|
||||
|
||||
- Centralize the management of configuration parameters into configuration files to improve maintenance convenience.
|
||||
- Fix some known bugs and improve stability and concurrency capabilities.
|
||||
- Centralized configuration parameters management into config files for better maintenance
|
||||
- Fixed known bugs and improved stability and concurrency capabilities
|
||||
|
||||
### 2025/01/02
|
||||
|
||||
@ -221,6 +226,47 @@ Through actual testing, when proxy server performance is sufficient, ProxyCat ca
|
||||
- Restructured code, split into separate files
|
||||
- Added automatic proxy switching when current proxy fails during forwarding
|
||||
|
||||
### 2024/09/29
|
||||
|
||||
- Removed less-used single cycle mode, replaced with custom mode for customizable proxy switching logic
|
||||
- Changed proxy validity checking to asynchronous for better speed
|
||||
- Removed problematic SOCKS4 protocol support
|
||||
- Beautified logging system
|
||||
- Improved exception handling logic
|
||||
- Added proxy format validation
|
||||
|
||||
### 2024/09/10
|
||||
|
||||
- Optimized concurrency efficiency, supporting next request before receiving response
|
||||
- Added load balancing mode for random proxy selection and concurrent proxy usage
|
||||
- Changed proxy validity checking to asynchronous for better efficiency
|
||||
|
||||
### 2024/09/09
|
||||
|
||||
- Added option to validate proxies in ip.txt at startup
|
||||
- Function downgrade to support lower Python versions
|
||||
|
||||
### 2024/09/03
|
||||
|
||||
- Added local SOCKS5 listening for wider software compatibility
|
||||
- Changed some functions to support lower Python versions
|
||||
- Beautified output display
|
||||
|
||||
### 2024/08/31
|
||||
|
||||
- Major project structure adjustment
|
||||
- Beautified display with continuous proxy switch time indication
|
||||
- Added Ctrl+C support for stopping
|
||||
- Major adjustment to async requests, improved concurrency efficiency
|
||||
- Changed from runtime parameters to local ini config file
|
||||
- Added support for local authentication-free mode
|
||||
- Added version detection
|
||||
- Added proxy server authentication
|
||||
- Added GetIP update only on request feature
|
||||
- Added proxy protocol auto-detection
|
||||
- Added HTTPS protocol support
|
||||
- Changed asyncio.timeout() to asyncio.wait_for() for lower Python version support
|
||||
|
||||
[Additional change log entries follow similar pattern...]
|
||||
|
||||
## Development Plan
|
||||
|
||||
28
README.md
28
README.md
@ -36,17 +36,18 @@
|
||||
|
||||
## 功能特点
|
||||
|
||||
- **双协议支持**:支持 SOCKS5 和 HTTP 协议监听地址,适配更多工具。
|
||||
- **多重代理协议**:支持 HTTP/HTTPS/SOCKS5 代理服务器,满足不同应用场景需求。
|
||||
- **多种切换模式**:按照顺序循环使用代理列表中的每一个代理,确保均衡使用;随机选择可用代理,分摊流量负载,提升性能。允许用户自定义代理选择逻辑,灵活满足特定需求。
|
||||
- **函数获取代理**:支持通过 GetIP 函数动态获取即时可用的代理,保证代理的实时性和有效性。
|
||||
- **自动检测有效性**:在启动时自动检测代理的可用性,过滤无效代理,确保代理列表的可靠性。
|
||||
- **仅在代理转发时切换**:在计时器归零时,有新的请求才会更换为新的代理服务器,防止运行时一直消耗资源。
|
||||
- **支持代理失效切换**:在转发流量过程中,遇到代理服务器突然失效,可自动切换到新的代理上。
|
||||
- **代理池身份认证**:支持基于用户名和密码的代理认证和黑白名单机制的代理认证,增强代理的安全性,防止未授权访问。
|
||||
- **实时状态更新**:显示当前代理状态和下次切换时间,帮助用户了解代理动态。
|
||||
- **可配置文件**:通过 config.ini 文件轻松调整端口、模式、认证信息等参数,适应不同使用场景。
|
||||
- **版本检测**:内置版本检测功能,自动检查最新版本并提醒用户更新,确保软件的持续优化。
|
||||
- **双协议监听**:支持 HTTP/SOCKS5 协议监听,兼容更多工具。
|
||||
- **三种协议代理地址**:支持 HTTP/HTTPS/SOCKS5 代理服务器,满足不同需求。
|
||||
- **灵活切换模式**:支持顺序、随机及自定义代理选择,优化流量分配。
|
||||
- **动态获取代理**:通过 GetIP 函数即时获取可用代理,支持 API 接口调用。
|
||||
- **代理保护机制**:在使用 GetIP 方式获取代理时,首次运行不会直接请求获取,将会在收到请求的时候才获取。
|
||||
- **自动代理检测**:启动时自动检测代理有效性,剔除无效代理。
|
||||
- **智能切换代理**:仅在请求运行时获取新代理,减少资源消耗。
|
||||
- **失效代理切换**:代理失效后自动验证切换新代理,确保不中断服务。
|
||||
- **身份认证支持**:支持用户名/密码认证和黑白名单管理,提高安全性。
|
||||
- **实时状态显示**:展示代理状态和切换时间,实时掌握代理动态。
|
||||
- **配置灵活**:通过 config.ini 文件自定义端口、模式和认证信息等。
|
||||
- **版本检测**:自动检查软件更新,保证版本最新。
|
||||
|
||||
## 安装与使用
|
||||
|
||||
@ -208,6 +209,11 @@ docker logs proxycat-app-1
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 2025/01/07
|
||||
|
||||
- 代理检测模块增加缓存机制,防止频繁检查。
|
||||
- 优化部分错误处理和日志记录。
|
||||
|
||||
### 2025/01/03
|
||||
|
||||
- 集中配置参数到配置文件中管理,提升维护便利。
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import asyncio, logging, random, httpx, re, os
|
||||
import asyncio, logging, random, httpx, re, os, time
|
||||
from configparser import ConfigParser
|
||||
from packaging import version
|
||||
from colorama import Fore
|
||||
@ -270,7 +270,16 @@ def load_ip_list(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return {line.strip() for line in f if line.strip()}
|
||||
|
||||
_proxy_check_cache = {}
|
||||
_proxy_check_ttl = 10
|
||||
|
||||
async def check_proxy(proxy):
|
||||
current_time = time.time()
|
||||
if proxy in _proxy_check_cache:
|
||||
cache_time, is_valid = _proxy_check_cache[proxy]
|
||||
if current_time - cache_time < _proxy_check_ttl:
|
||||
return is_valid
|
||||
|
||||
proxy_type = proxy.split('://')[0]
|
||||
check_funcs = {
|
||||
'http': check_http_proxy,
|
||||
@ -282,9 +291,12 @@ async def check_proxy(proxy):
|
||||
return False
|
||||
|
||||
try:
|
||||
return await check_funcs[proxy_type](proxy)
|
||||
is_valid = await check_funcs[proxy_type](proxy)
|
||||
_proxy_check_cache[proxy] = (current_time, is_valid)
|
||||
return is_valid
|
||||
except Exception as e:
|
||||
logging.error(f"{proxy_type.upper()}代理 {proxy} 检测失败: {e}")
|
||||
_proxy_check_cache[proxy] = (current_time, False)
|
||||
return False
|
||||
|
||||
async def check_http_proxy(proxy):
|
||||
|
||||
@ -40,7 +40,10 @@ class AsyncProxyServer:
|
||||
self.proxy_failed = False
|
||||
self.proxy_fail_count = 0
|
||||
self.max_fail_count = 2
|
||||
self.semaphore = asyncio.Semaphore(10000)
|
||||
self.semaphore = asyncio.Semaphore(20000)
|
||||
self.buffer_size = 256 * 1024
|
||||
self.proxy_cache = {}
|
||||
self.proxy_cache_ttl = 10
|
||||
|
||||
async def get_next_proxy(self):
|
||||
if self.mode == 'load_balance':
|
||||
@ -240,10 +243,9 @@ class AsyncProxyServer:
|
||||
|
||||
async def _pipe(self, reader, writer):
|
||||
try:
|
||||
buffer_size = 65536
|
||||
while True:
|
||||
try:
|
||||
data = await asyncio.wait_for(reader.read(buffer_size), timeout=30)
|
||||
data = await asyncio.wait_for(reader.read(self.buffer_size), timeout=30)
|
||||
if not data:
|
||||
break
|
||||
writer.write(data)
|
||||
@ -470,7 +472,8 @@ class AsyncProxyServer:
|
||||
writer.write(b'\r\n')
|
||||
await writer.drain()
|
||||
|
||||
async for chunk in response.aiter_bytes(chunk_size=65536):
|
||||
chunk_size = 256 * 1024
|
||||
async for chunk in response.aiter_bytes(chunk_size=chunk_size):
|
||||
if asyncio.current_task().cancelled():
|
||||
raise asyncio.CancelledError
|
||||
writer.write(f'{len(chunk):X}\r\n'.encode('utf-8', errors='ignore'))
|
||||
@ -515,3 +518,14 @@ class AsyncProxyServer:
|
||||
await self.get_proxy()
|
||||
self.last_switch_time = time.time()
|
||||
logging.info(get_message('proxy_switched', self.language, old_proxy, self.current_proxy))
|
||||
|
||||
async def check_proxy(self, proxy):
|
||||
current_time = time.time()
|
||||
if proxy in self.proxy_cache:
|
||||
cache_time, is_valid = self.proxy_cache[proxy]
|
||||
if current_time - cache_time < self.proxy_cache_ttl:
|
||||
return is_valid
|
||||
|
||||
is_valid = await self._check_proxy_impl(proxy)
|
||||
self.proxy_cache[proxy] = (current_time, is_valid)
|
||||
return is_valid
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user