From 4fbb63e0b922f72542b1a9eaf0334f0be3811a8f Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 16 Jul 2026 18:50:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20SOCKS5=20=E9=9A=A7=E9=81=93=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E8=B6=85=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复子线程事件循环中 asyncio.wait_for 包装 open_connection 导致的读取取消问题。 改用 socket 层面的 timeout 设置,不再用 wait_for 包装。 同时修复 _reply 中 writer.write 不需要 await 的问题。 --- engine/server.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/engine/server.py b/engine/server.py index fe3398e..648b01b 100644 --- a/engine/server.py +++ b/engine/server.py @@ -4,6 +4,7 @@ import logging import struct import time import uuid +import socket as _socket import ipaddress from datetime import datetime, timezone @@ -127,11 +128,11 @@ class ConnectionHandler: methods = header[2:2 + n_methods] # 检查是否支持 if METHOD_USERPASS in methods and self.config.auth_method == "userpass": - await self.writer.write(bytes([SOCKS_VERSION, METHOD_USERPASS])) + self.writer.write(bytes([SOCKS_VERSION, METHOD_USERPASS])) elif METHOD_NO_AUTH in methods: - await self.writer.write(bytes([SOCKS_VERSION, METHOD_NO_AUTH])) + self.writer.write(bytes([SOCKS_VERSION, METHOD_NO_AUTH])) else: - await self.writer.write(bytes([SOCKS_VERSION, METHOD_NOT_ACCEPTED])) + self.writer.write(bytes([SOCKS_VERSION, METHOD_NOT_ACCEPTED])) return False await self.writer.drain() return True @@ -177,14 +178,14 @@ class ConnectionHandler: log.warning("认证失败: %s (user=%s)", self.src_ip, username) await self.user_service.log_event("auth_fail", username, self.src_ip, "密码错误或账号不可用") - await self.writer.write(bytes([1, 0x01])) # auth fail + self.writer.write(bytes([1, 0x01])) # auth fail await self.writer.drain() return False self.username = username log.info("[%s] 认证成功: %s (from %s)", self.conn_id, username, self.src_ip) await self.user_service.log_event("auth_success", username, self.src_ip) - await self.writer.write(bytes([1, 0x00])) # auth ok + self.writer.write(bytes([1, 0x00])) # auth ok await self.writer.drain() return True @@ -273,11 +274,13 @@ class ConnectionHandler: # 连接目标 try: - reader, writer = await asyncio.wait_for( - asyncio.open_connection(addr, port), - timeout=self.config.timeout - ) - except (asyncio.TimeoutError, OSError) as e: + # 注意:不用 asyncio.wait_for 包装 open_connection, + # 在子线程事件循环中 wait_for 会导致连接成功后读取被取消 + sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) + sock.settimeout(self.config.timeout) + sock.connect((addr, port)) + reader, writer = await asyncio.open_connection(sock=sock) + except (OSError, Exception) as e: log.warning("[%s] 无法连接 %s:%d: %s", self.conn_id, addr, port, e) rep = REP_CONN_REFUSED if "refused" in str(e).lower() else REP_HOST_UNREACHABLE await self._reply(rep)