ykxmz 1.5.0:修复手表端 TLS 证书校验 + MTU 修复网络稳定性

被控端
- 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%)
- 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败)
- 每分钟回头找局域网,自动切回快 400 倍的路径
- 画面心跳帧:静止时省流量,客户端仍知道流是活的
- 锁屏时给出可操作的提示

手表端
- 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException
- 连接错误翻译成人话(证书/时间/解析/超时分别提示)
- 经中转连上后用服务器报的地址刷新已配对记录
- 新增局域网连接页面、服务器延迟检测

服务器端
- 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502)
- 网络调优脚本 net-tune.sh(开机自动应用)
- 管理页:批量删除、网络体检、下载区
- 隧道改 HTTP/2 + 双连接

文档
- 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
This commit is contained in:
xmz7891
2026-10-06 19:01:05 +08:00
commit b62ac865ea
3195 changed files with 203292 additions and 0 deletions
+260
View File
@@ -0,0 +1,260 @@
# -*- coding: utf-8 -*-
"""防火墙检测与修复脚本测试。
背景(真机踩到的坑):
Windows 防火墙的「阻止」规则**优先级高于「放行」规则**。
当系统弹「是否允许此应用通过防火墙」而用户点了取消时,
系统会自动建一条 Block 规则,之后加多少 Allow 都不管用。
而且规则是按**程序完整路径**建的,换个目录解压就多一条。
又因为防火墙不过滤回环(127.0.0.1),本地自测全绿、真机永远超时。
这里验证:
1. netsh 输出解析(中英文两种语言都要认)
2. 阻止规则识别
3. 修复脚本内容正确(先删阻止、再建放行)
不需要管理员权限:不实际执行提权,只验证解析与脚本生成。
"""
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "windows"))
from lanremote import firewall # noqa: E402
PASSED = 0
FAILED = 0
def check(name: str, ok: bool, detail: str = "") -> None:
global PASSED, FAILED
if ok:
PASSED += 1
print(f" [PASS] {name}")
else:
FAILED += 1
print(f" [FAIL] {name} {detail}")
# 中文系统的 netsh 输出样例(字段名是中文的)
ZH_RULE = """规则名称: ykxmz.exe
----------------------------------------------------------------------
已启用: 是
方向: 入
配置文件: 公用
分组:
本地 IP: 任何
远程 IP: 任何
协议: TCP
本地端口: 任何
远程端口: 任何
边缘遍历: 否
程序: C:\\Users\\shu\\Desktop\\LanRemote\\dist_exe\\ykxmz\\ykxmz.exe
操作: 阻止
"""
EN_RULE = """Rule Name: ykxmz.exe
----------------------------------------------------------------------
Enabled: Yes
Direction: In
Profiles: Public
Grouping:
LocalIP: Any
RemoteIP: Any
Protocol: UDP
LocalPort: Any
RemotePort: Any
Edge traversal: No
Program: C:\\test\\ykxmz.exe
Action: Block
"""
ALLOW_RULE = """规则名称: LAN Remote TCP
----------------------------------------------------------------------
已启用: 是
方向: 入
配置文件: 域,专用,公用
协议: TCP
本地端口: 8765
程序:
操作: 允许
"""
def main() -> int:
print("=" * 68)
print("一、netsh 输出解析(中英文都要认)")
print("=" * 68)
zh = firewall._parse_fields(ZH_RULE)
check("中文输出: 规则名解析正确",
zh.get("RuleName") == "ykxmz.exe", str(zh.get("RuleName")))
check("中文输出: 操作解析为「阻止」",
zh.get("Action") == "阻止", str(zh.get("Action")))
check("中文输出: 协议解析正确", zh.get("Protocol") == "TCP", str(zh.get("Protocol")))
check("中文输出: 程序路径解析正确",
(zh.get("Program") or "").lower().endswith("ykxmz.exe"),
str(zh.get("Program")))
en = firewall._parse_fields(EN_RULE)
check("英文输出: 规则名解析正确",
en.get("RuleName") == "ykxmz.exe", str(en.get("RuleName")))
check("英文输出: 操作解析为 Block", en.get("Action") == "Block", str(en.get("Action")))
check("英文输出: 协议解析正确", en.get("Protocol") == "UDP", str(en.get("Protocol")))
allow = firewall._parse_fields(ALLOW_RULE)
check("放行规则不会被误判为阻止",
(allow.get("Action") or "").lower() not in firewall._BLOCK_VALUES,
str(allow.get("Action")))
print()
print("=" * 68)
print("二、规则切分与阻止规则识别(模拟完整 netsh 输出)")
print("=" * 68)
combined = ZH_RULE + "\n" + ALLOW_RULE + "\n" + EN_RULE
rules = firewall._split_rules(combined)
check("切分出 3 条规则", len(rules) == 3, f"得到 {len(rules)}")
blocks = [r for r in rules
if (r.get("Action") or "").lower() in firewall._BLOCK_VALUES]
check("其中 2 条是阻止规则", len(blocks) == 2, f"得到 {len(blocks)}")
names = {firewall.os.path.basename((r.get("Program") or "").strip('"')).lower()
for r in blocks}
check("阻止规则都指向本程序",
names == {"ykxmz.exe"}, str(names))
print()
print("=" * 68)
print("三、修复脚本内容(先删阻止,再建放行)")
print("=" * 68)
script = firewall.build_script(8765, 8766)
check("脚本删除了 ykxmz.exe 的规则",
'delete rule name="ykxmz.exe" dir=in' in script)
check("脚本删除了 python.exe 的规则(源码模式遗留)",
'delete rule name="python.exe" dir=in' in script)
check("脚本重建 TCP 放行规则",
'add rule name="LAN Remote TCP"' in script
and "protocol=TCP localport=8765" in script)
check("脚本重建 UDP 放行规则",
'add rule name="LAN Remote UDP"' in script
and "protocol=UDP localport=8766" in script)
# 端口放行 2 条 + 程序级放行 2 条 = 4 条,全部覆盖域/专用/公用
check("脚本使用 profile=any(公用/专用/域都放行)",
script.count("profile=any") == 4, f"出现 {script.count('profile=any')} 次")
# 源码模式下不能把打包版的程序级规则冲掉(真机事故)
target = firewall.target_executable()
check("修复目标是一个真实的可执行文件",
bool(target) and target.lower().endswith(".exe"), str(target))
if not getattr(sys, "frozen", False):
existing = firewall.app_rule_program()
# 注意还要看那个路径**现在还在不在** ——
# 规则指向一个已经删掉的旧副本时,target_executable 会(正确地)
# 退回 python.exe。测试条件漏了这一点就会假失败(改名后就踩了)。
if (existing and "python" not in existing.lower()
and __import__("os").path.isfile(existing)):
check("源码模式下沿用已有的打包版目标,不写 python.exe",
"python" not in target.lower(), f"target={target}")
elif existing:
print(f" (已有规则指向 {existing},但那个文件不在了,"
f"所以退回 python.exe —— 这是对的)")
print(f" 修复将放行: {target}")
check("删除动作在添加动作之前",
script.index("delete rule") < script.index("add rule"))
# 真机上踩到的坑:裸 LF 换行会让 cmd 把整个脚本解析成一堆无效命令
lone_lf = script.count("\n") - script.count("\r\n")
check("脚本全部使用 CRLF 换行(裸 LF 会让 cmd 解析错乱)",
lone_lf == 0, f"发现 {lone_lf} 处裸 LF")
check("脚本以 chcp 936 开头(配合 GBK 存盘)",
script.splitlines()[1].strip() == "chcp 936 >nul",
script.splitlines()[1].strip() if len(script.splitlines()) > 1 else "?")
check("脚本编码声明可用 GBK 编码",
isinstance(script.encode("gbk", errors="replace"), bytes))
# 只删阻止规则治标不治本:必须补程序级放行,否则系统会再生成阻止规则
check("脚本添加了程序级放行规则(治本)",
"LAN Remote App TCP" in script and "LAN Remote App UDP" in script)
check("程序级放行规则指向真实可执行文件",
'program="' in script and ".exe" in script.lower(),
"未找到 program= 指向")
check("程序级规则 enable=yes 且 profile=any",
script.count("enable=yes protocol=") == 2
and script.count("profile=any") >= 4,
f"enable=yes 出现 {script.count('enable=yes protocol=')} 次")
print()
print("=" * 68)
print("四、真实状态查询(本机)")
print("=" * 68)
status = firewall.check(8765, 8766)
for key in ("supported", "ok", "tcp", "udp", "blocked", "blocked_count",
"elevated", "message", "tcp_port", "udp_port"):
check(f"状态包含字段 {key}", key in status)
check("字段类型正确",
isinstance(status["blocked"], list)
and isinstance(status["blocked_count"], int)
and isinstance(status["ok"], bool))
check("状态包含 app_rule(程序级放行)字段", "app_rule" in status)
check("状态包含 blocked_others(其他副本的阻止规则数)",
"blocked_others" in status)
# 阻止规则按程序路径生效:别的副本被阻止不该影响本安装的判定
print()
print(" —— 作用域检查:只统计当前程序 ——")
live = r"C:\Users\shu\Desktop\deepseekagent\ykxmz\ykxmz.exe"
original = firewall.executable_path
try:
firewall.executable_path = lambda: live
scoped = firewall.check(8765, 8766)
print(f" 以「实际安装」视角: 本程序阻止规则={scoped['blocked_count']} 条, "
f"其他副本={scoped['blocked_others']} 条, ok={scoped['ok']}")
check("其他副本的阻止规则不影响本安装判定",
scoped["ok"] is True or scoped["blocked_count"] > 0,
f"blocked={scoped['blocked_count']} others={scoped['blocked_others']}")
check("blocked 只包含当前程序的规则",
all((b.get("Program") or "").lower() == live.lower()
for b in scoped["blocked"]),
str([b.get("Program") for b in scoped["blocked"]]))
check("blocked_count + blocked_others 等于全部阻止规则数",
scoped["blocked_count"] + scoped["blocked_others"]
== len(firewall.list_block_rules()),
f"{scoped['blocked_count']}+{scoped['blocked_others']} "
f"vs {len(firewall.list_block_rules())}")
finally:
firewall.executable_path = original
check("有阻止规则时 ok 必为 False",
status["blocked_count"] == 0 or status["ok"] is False)
print(f" 本机结果: ok={status['ok']} 阻止规则={status['blocked_count']} 条")
print(f" 说明: {status['message']}")
for item in status["blocked"][:3]:
print(f" - {item.get('ProgramBase')} {item.get('Protocol')} "
f"{(item.get('Program') or '')[-48:]}")
if status["blocked_count"] > 0:
check("有阻止规则时 ok 必须为 False(阻止压过放行)",
status["ok"] is False)
check("阻止规则条数与列表长度一致",
status["blocked_count"] == len(status["blocked"]))
print()
print("=" * 68)
print(f"通过 {PASSED} 项,失败 {FAILED} 项")
print("=" * 68)
return 1 if FAILED else 0
if __name__ == "__main__":
sys.exit(main())