fix(lite): bundle tun runtime and quiet connection logs
This commit is contained in:
@@ -26,6 +26,8 @@ call ..\.venv\Scripts\python.exe -m nuitka ^
|
|||||||
--include-data-files=runtime/LICENSE.tun2socks.txt=LICENSE.tun2socks.txt ^
|
--include-data-files=runtime/LICENSE.tun2socks.txt=LICENSE.tun2socks.txt ^
|
||||||
--include-data-files=runtime/LICENSE.wintun.txt=LICENSE.wintun.txt ^
|
--include-data-files=runtime/LICENSE.wintun.txt=LICENSE.wintun.txt ^
|
||||||
--include-data-files=runtime/README.txt=README.txt ^
|
--include-data-files=runtime/README.txt=README.txt ^
|
||||||
|
--include-data-files=runtime/tun2socks.exe=tun2socks.exe ^
|
||||||
|
--include-data-files=runtime/wintun.dll=wintun.dll ^
|
||||||
--windows-icon-from-ico=ico.ico ^
|
--windows-icon-from-ico=ico.ico ^
|
||||||
--windows-console-mode=disable ^
|
--windows-console-mode=disable ^
|
||||||
--company-name="Global Rosmanka Cloud Nexus Inc" ^
|
--company-name="Global Rosmanka Cloud Nexus Inc" ^
|
||||||
|
|||||||
+15
-14
@@ -1056,7 +1056,7 @@ def _verify_proxy_connectivity(timeout=10, opener=None, cancel_event=None):
|
|||||||
response.read(1)
|
response.read(1)
|
||||||
_raise_if_start_cancelled(cancel_event)
|
_raise_if_start_cancelled(cancel_event)
|
||||||
results[name] = True
|
results[name] = True
|
||||||
log(f" {name} 可达")
|
log_detail(f" {name} 可达")
|
||||||
except _StartCancelled:
|
except _StartCancelled:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -1064,7 +1064,7 @@ def _verify_proxy_connectivity(timeout=10, opener=None, cancel_event=None):
|
|||||||
# 这不是“开启失败”,也不能在稍后把界面重新切成已开启。
|
# 这不是“开启失败”,也不能在稍后把界面重新切成已开启。
|
||||||
_raise_if_start_cancelled(cancel_event)
|
_raise_if_start_cancelled(cancel_event)
|
||||||
results[name] = False
|
results[name] = False
|
||||||
log(f" {name} 不可达: {e}")
|
log_detail(f" {name} 不可达: {e}")
|
||||||
if required:
|
if required:
|
||||||
raise RuntimeError(f"境外隧道验证失败({name}):{e}") from e
|
raise RuntimeError(f"境外隧道验证失败({name}):{e}") from e
|
||||||
return results
|
return results
|
||||||
@@ -1116,7 +1116,7 @@ def _tls_start(remote_host, remote_port=443, use_tls=True, bypass_lan=False, sma
|
|||||||
svr.close()
|
svr.close()
|
||||||
svr = None
|
svr = None
|
||||||
if attempt < 2:
|
if attempt < 2:
|
||||||
log(f"端口 {_TLS_LOCAL_PORT} 绑定失败: {e},1 秒后重试 ({attempt + 1}/3)")
|
log_detail(f"端口 {_TLS_LOCAL_PORT} 绑定失败: {e},1 秒后重试 ({attempt + 1}/3)")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
if svr is None:
|
if svr is None:
|
||||||
raise last_err
|
raise last_err
|
||||||
@@ -2259,7 +2259,7 @@ def _connect_route(direct_target, allow_direct_fallback, remote_host, remote_por
|
|||||||
except OSError as e:
|
except OSError as e:
|
||||||
if not allow_direct_fallback:
|
if not allow_direct_fallback:
|
||||||
raise
|
raise
|
||||||
log(f"[转发器] 国内直连 {direct_target[0]} 失败,回退上游隧道: {e}")
|
log_detail(f"[转发器] 国内直连 {direct_target[0]} 失败,回退上游隧道: {e}")
|
||||||
if jump_chain:
|
if jump_chain:
|
||||||
if not use_tls:
|
if not use_tls:
|
||||||
raise RuntimeError("跳板模式仅支持 TLS 上游")
|
raise RuntimeError("跳板模式仅支持 TLS 上游")
|
||||||
@@ -2381,7 +2381,7 @@ def _tls_relay(client, remote_host, remote_port, ctx, use_tls, bypass_lan=False,
|
|||||||
else:
|
else:
|
||||||
log_detail(f"[连接 #{connection_id}] 无法解析目标: {first_line or '空请求'},客户端={peer_text}")
|
log_detail(f"[连接 #{connection_id}] 无法解析目标: {first_line or '空请求'},客户端={peer_text}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"[转发器] 读取首包失败: {e}")
|
log_detail(f"[转发器] 读取首包失败: {e}")
|
||||||
log_detail(f"[连接 #{connection_id}] 失败: 读取首包,目标={target_text},规则匹配={rule_match},错误={e}")
|
log_detail(f"[连接 #{connection_id}] 失败: 读取首包,目标={target_text},规则匹配={rule_match},错误={e}")
|
||||||
client.close()
|
client.close()
|
||||||
return
|
return
|
||||||
@@ -2414,7 +2414,7 @@ def _tls_relay(client, remote_host, remote_port, ctx, use_tls, bypass_lan=False,
|
|||||||
if via_tunnel:
|
if via_tunnel:
|
||||||
_traffic_add(up=len(buf))
|
_traffic_add(up=len(buf))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"[转发器] 连接目标失败: {e}")
|
log_detail(f"[转发器] 连接目标失败: {e}")
|
||||||
log_detail(f"[连接 #{connection_id}] 连接失败: 目标={target_text},规则匹配={rule_match},路径={route_summary},错误={e}")
|
log_detail(f"[连接 #{connection_id}] 连接失败: 目标={target_text},规则匹配={rule_match},路径={route_summary},错误={e}")
|
||||||
try:
|
try:
|
||||||
client.close()
|
client.close()
|
||||||
@@ -2691,7 +2691,8 @@ def _make_tun_backend(emit):
|
|||||||
engine = Path(BASE_DIR) / "runtime" / "tun2socks.exe"
|
engine = Path(BASE_DIR) / "runtime" / "tun2socks.exe"
|
||||||
if not engine.is_file() or not (engine.parent / "wintun.dll").is_file():
|
if not engine.is_file() or not (engine.parent / "wintun.dll").is_file():
|
||||||
raise RuntimeError("单文件包中的 tun2socks.exe 或 wintun.dll 缺失")
|
raise RuntimeError("单文件包中的 tun2socks.exe 或 wintun.dll 缺失")
|
||||||
return TunBackend(_USER_DIR, engine_path=engine, log=emit, detail_log=emit)
|
detail_emit = getattr(emit, "detail", emit)
|
||||||
|
return TunBackend(_USER_DIR, engine_path=engine, log=emit, detail_log=detail_emit)
|
||||||
|
|
||||||
|
|
||||||
def _start_tun_backend(backend, payload):
|
def _start_tun_backend(backend, payload):
|
||||||
@@ -2783,7 +2784,7 @@ class MainWindow(QWidget):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self._proxy_set_by_us = False # 系统代理是否由本程序开启(退出时只清理自己设置的)
|
self._proxy_set_by_us = False # 系统代理是否由本程序开启(退出时只清理自己设置的)
|
||||||
self._mode = _proxy_mode()
|
self._mode = _proxy_mode()
|
||||||
self._tun_controller = TunModeController(_tun_worker_command(), log)
|
self._tun_controller = TunModeController(_tun_worker_command(), log, log_detail)
|
||||||
self._quitting = False
|
self._quitting = False
|
||||||
self._tray = None
|
self._tray = None
|
||||||
self._tray_menu = None
|
self._tray_menu = None
|
||||||
@@ -3224,11 +3225,11 @@ class MainWindow(QWidget):
|
|||||||
_traffic_reset()
|
_traffic_reset()
|
||||||
current_node = _current_node()
|
current_node = _current_node()
|
||||||
jump_chain = _jump_chain(current_node)
|
jump_chain = _jump_chain(current_node)
|
||||||
log("TLS 多跳模式" if jump_chain else "TLS 直连模式")
|
log_detail("TLS 多跳模式" if jump_chain else "TLS 直连模式")
|
||||||
ep = _endpoint_domain()
|
ep = _endpoint_domain()
|
||||||
log(f" 目标域名: {ep}")
|
log_detail(f" 目标域名: {ep}")
|
||||||
if jump_chain:
|
if jump_chain:
|
||||||
log(f" 跳板路径: {_jump_route_text(current_node)}")
|
log_detail(f" 跳板路径: {_jump_route_text(current_node)}")
|
||||||
# PAC 模式:全部流量进转发器,按域名表/解析 IP 智能分流
|
# PAC 模式:全部流量进转发器,按域名表/解析 IP 智能分流
|
||||||
use_internal_pac = _should_use_internal_pac(use_pac)
|
use_internal_pac = _should_use_internal_pac(use_pac)
|
||||||
if use_internal_pac:
|
if use_internal_pac:
|
||||||
@@ -3249,7 +3250,7 @@ class MainWindow(QWidget):
|
|||||||
# 在内存中启动本地 PAC HTTP 服务,不往 EXE 目录写任何文件
|
# 在内存中启动本地 PAC HTTP 服务,不往 EXE 目录写任何文件
|
||||||
pac_port = _start_pac_server(pac_content)
|
pac_port = _start_pac_server(pac_content)
|
||||||
pac_url = f"http://127.0.0.1:{pac_port}/proxy.pac"
|
pac_url = f"http://127.0.0.1:{pac_port}/proxy.pac"
|
||||||
log(f"使用 PAC: {pac_url}")
|
log_detail(f"使用 PAC: {pac_url}")
|
||||||
with self._proxy_state_lock:
|
with self._proxy_state_lock:
|
||||||
_raise_if_start_cancelled(cancel_event)
|
_raise_if_start_cancelled(cancel_event)
|
||||||
proxy_on(pac_url=pac_url)
|
proxy_on(pac_url=pac_url)
|
||||||
@@ -3260,10 +3261,10 @@ class MainWindow(QWidget):
|
|||||||
proxy_on(bypass_lan=use_bypass_lan)
|
proxy_on(bypass_lan=use_bypass_lan)
|
||||||
self._proxy_set_by_us = True
|
self._proxy_set_by_us = True
|
||||||
if use_internal_pac:
|
if use_internal_pac:
|
||||||
log(f"使用内置 PAC:系统固定代理 127.0.0.1:{PROXY_PORT},转发器内部智能分流")
|
log_detail(f"使用内置 PAC:系统固定代理 127.0.0.1:{PROXY_PORT},转发器内部智能分流")
|
||||||
_raise_if_start_cancelled(cancel_event)
|
_raise_if_start_cancelled(cancel_event)
|
||||||
if use_bypass_lan:
|
if use_bypass_lan:
|
||||||
log("不代理内网 IP:内网地址将直连")
|
log_detail("不代理内网 IP:内网地址将直连")
|
||||||
log("验证代理连通性...")
|
log("验证代理连通性...")
|
||||||
_verify_proxy_connectivity(cancel_event=cancel_event)
|
_verify_proxy_connectivity(cancel_event=cancel_event)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -46,9 +46,11 @@ def _receive(reader) -> dict[str, Any]:
|
|||||||
class TunModeController:
|
class TunModeController:
|
||||||
"""普通权限 GUI 仅在首次开启 TUN 时启动管理员工作进程。"""
|
"""普通权限 GUI 仅在首次开启 TUN 时启动管理员工作进程。"""
|
||||||
|
|
||||||
def __init__(self, command: list[str], log: Callable[[str], None]):
|
def __init__(self, command: list[str], log: Callable[[str], None],
|
||||||
|
detail_log: Callable[[str], None] | None = None):
|
||||||
self.command = command
|
self.command = command
|
||||||
self.log = log
|
self.log = log
|
||||||
|
self.detail_log = detail_log or log
|
||||||
self._lock = threading.RLock()
|
self._lock = threading.RLock()
|
||||||
self._socket: socket.socket | None = None
|
self._socket: socket.socket | None = None
|
||||||
self._reader = None
|
self._reader = None
|
||||||
@@ -129,7 +131,8 @@ class TunModeController:
|
|||||||
while True:
|
while True:
|
||||||
message = _receive(self._reader)
|
message = _receive(self._reader)
|
||||||
if message.get("type") == "log":
|
if message.get("type") == "log":
|
||||||
self.log(str(message.get("message") or ""))
|
callback = self.detail_log if message.get("detail") else self.log
|
||||||
|
callback(str(message.get("message") or ""))
|
||||||
continue
|
continue
|
||||||
if message.get("type") != "result":
|
if message.get("type") != "result":
|
||||||
raise TunModeError("TUN 工作进程响应无效")
|
raise TunModeError("TUN 工作进程响应无效")
|
||||||
@@ -192,12 +195,22 @@ def run_tun_worker(port: int, token: str, backend_factory,
|
|||||||
send_lock = threading.Lock()
|
send_lock = threading.Lock()
|
||||||
_send(connection, {"type": "hello", "token": token}, send_lock)
|
_send(connection, {"type": "hello", "token": token}, send_lock)
|
||||||
|
|
||||||
def emit(message: str) -> None:
|
def emit(message: str, detail: bool = False) -> None:
|
||||||
try:
|
try:
|
||||||
_send(connection, {"type": "log", "message": str(message)}, send_lock)
|
_send(connection, {"type": "log", "message": str(message),
|
||||||
|
"detail": bool(detail)}, send_lock)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class _WorkerLogger:
|
||||||
|
def __call__(self, message: str) -> None:
|
||||||
|
emit(message)
|
||||||
|
|
||||||
|
def detail(self, message: str) -> None:
|
||||||
|
emit(message, detail=True)
|
||||||
|
|
||||||
|
logger = _WorkerLogger()
|
||||||
|
|
||||||
backend = None
|
backend = None
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
@@ -213,7 +226,7 @@ def run_tun_worker(port: int, token: str, backend_factory,
|
|||||||
# 延迟创建后端,使初始化失败也能通过控制协议返回具体原因,
|
# 延迟创建后端,使初始化失败也能通过控制协议返回具体原因,
|
||||||
# 避免 GUI 只看到 Windows 的 10053 连接中止错误。
|
# 避免 GUI 只看到 Windows 的 10053 连接中止错误。
|
||||||
if backend is None:
|
if backend is None:
|
||||||
backend = backend_factory(emit)
|
backend = backend_factory(logger)
|
||||||
start_backend(backend, request["payload"])
|
start_backend(backend, request["payload"])
|
||||||
value = None
|
value = None
|
||||||
elif command == "stop":
|
elif command == "stop":
|
||||||
|
|||||||
Reference in New Issue
Block a user