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)