mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 17:10:43 +00:00
琚帶绔?- 淇 MTU 闂锛氬す MSS + 璺緞 MTU 鎺㈡祴锛堝叕缃戝彲鐢ㄧ巼 48% -> 100%锛?- 澶嶇敤 HTTP 杩炴帴锛堝厤鎺夋瘡娆℃柊寤?TLS 鐨?30% 鎻℃墜澶辫触锛?- 姣忓垎閽熷洖澶存壘灞€鍩熺綉锛岃嚜鍔ㄥ垏鍥炲揩 400 鍊嶇殑璺緞 - 鐢婚潰蹇冭烦甯э細闈欐鏃剁渷娴侀噺锛屽鎴风浠嶇煡閬撴祦鏄椿鐨?- 閿佸睆鏃剁粰鍑哄彲鎿嶄綔鐨勬彁绀? 鎵嬭〃绔?- 鍐呯疆 GTS Root R4 / GlobalSign Root CA锛屼慨 SSLHandshakeException - 杩炴帴閿欒缈昏瘧鎴愪汉璇濓紙璇佷功/鏃堕棿/瑙f瀽/瓒呮椂鍒嗗埆鎻愮ず锛?- 缁忎腑杞繛涓婂悗鐢ㄦ湇鍔″櫒鎶ョ殑鍦板潃鍒锋柊宸查厤瀵硅褰?- 鏂板灞€鍩熺綉杩炴帴椤甸潰銆佹湇鍔″櫒寤惰繜妫€娴? 鏈嶅姟鍣ㄧ - 鏀寔 chunked 璇锋眰浣擄紙淇瘡 16 绉掍竴娆$殑杩炴帴閿欎贡涓庡ぇ闈㈢Н 502锛?- 缃戠粶璋冧紭鑴氭湰 net-tune.sh锛堝紑鏈鸿嚜鍔ㄥ簲鐢級 - 绠$悊椤碉細鎵归噺鍒犻櫎銆佺綉缁滀綋妫€銆佷笅杞藉尯 - 闅ч亾鏀?HTTP/2 + 鍙岃繛鎺? 鏂囨。 - 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
261 lines
11 KiB
Python
261 lines
11 KiB
Python
# -*- 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())
|