ykxmz 1.5.0锛氭墜琛ㄧ TLS 璇佷功鍏煎 + 涓夌鍒嗗紑鎵撳寘 + 涓嬭浇鍖?

鎵嬭〃绔?- 鍐呯疆 GTS Root R4 / GlobalSign Root CA
  淇?SSLHandshakeException: Chain validation failed
  锛堝粔浠锋墜琛ㄧ郴缁熸牴璇佷功搴撳父缂?GTS Root R4锛?- 杩炴帴閿欒缈昏瘧鎴愪汉璇濓細璇佷功 / 鏃堕棿 / 瑙f瀽 / 瓒呮椂鍒嗗埆缁欐彁绀?- 缁忎腑杞繛涓婂悗鐢ㄦ湇鍔″櫒鎶ョ殑鍦板潃鍒锋柊宸查厤瀵硅褰曪紙鍘熸潵涓€鐩存樉绀烘棫 IP锛?- 鐗堟湰鍙?1.3.0 -> 1.5.0锛圓ndroidManifest 涔嬪墠婕忔敼浜嗭級

鏈嶅姟鍣ㄧ
- 鏀寔 chunked 璇锋眰浣擄細淇瘡 16 绉掍竴娆$殑杩炴帴閿欎贡涓庡ぇ闈㈢Н 502
- 缃戠粶璋冧紭 net-tune.sh锛氬す MSS 1400 + 璺緞 MTU 鎺㈡祴
  锛堝叕缃戝彲鐢ㄧ巼 48% -> 100%锛屽疄娴?15 鍒嗛挓 180/180锛?  鍋氭垚寮€鏈烘湇鍔?lanremote-nettune.service锛屽苟浼氳嚜鍔ㄩ噸寤洪毀閬?- 鏂板涓嬭浇鍖猴細GET /v1/downloads 鍒楄〃 + GET /download/<鏂囦欢>
  鍙厑璁哥櫧鍚嶅崟鍚庣紑銆佷弗鏍兼牎楠屾枃浠跺悕锛堟尅鐩綍绌胯秺锛?  绠$悊椤靛姞涓嬭浇鍗$墖
- 闅ч亾鏀?HTTP/2 + 鍙岃繛鎺ワ紙QUIC 鍦ㄨ繖鏉$嚎璺笂鍙敤鐜囧彧鏈?48%锛?- 缃戠粶浣撴銆佹壒閲忓垹闄よ澶?
鎵撳寘鏂瑰紡鍙樻洿
- 鍘熸潵鏄笁涓儴鍒嗗悎鎴愪竴涓?zip锛岀幇鍦?*鍒嗘垚涓変釜鐙珛浜х墿**锛?    ykxmz-agent-1.5.0.zip    琚帶绔?    ykxmz-server-1.5.0.zip   鏈嶅姟鍣ㄧ
    ykxmz-watch-1.5.0.apk    鎺у埗绔紙鐩存帴缁?APK锛屼笉鎵?zip锛?  涓変釜鍖?鏂囦欢閮藉甫涓婅鍙崗璁?/ 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭?
鏂囨。
- 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
This commit is contained in:
xmz7891
2026-10-06 19:08:02 +08:00
parent 5b424c39c0
commit 7f267dd900
20 changed files with 3770 additions and 2943 deletions
+274
View File
@@ -0,0 +1,274 @@
# -*- coding: utf-8 -*-
r"""把打包改成"三端分开出"。
用户要求:
"三端分别打包,控制端不用打包成 zip,直接上传 apk"
所以产物是三个文件(原来是一个大 zip):
dist/ykxmz-agent-1.5.0.zip 被控端(Windows)
dist/ykxmz-server-1.5.0.zip 服务器端(随身 WiFi / Linux)
dist/ykxmz-watch-1.5.0.apk 控制端(手表,直接给 APK 不打 zip)
三个包里都带上三份文档(许可协议 / 安装前必读 / 安装后须知),
这样用户拿到哪一个都知道自己在装什么、有什么红线。
"""
from __future__ import annotations
import re
import sys
from pathlib import Path
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
PKG = ROOT / "_build" / "package_remote.py"
# 从 "def main() -> int:" 起,到文件末尾的 if __name__ 之前,全换成新的
NEW_MAIN = '''def _zip_dir(zip_path: Path, source: Path, arc_root: str) -> int:
"""把一个目录打成一个 zip(内部带一层 arc_root 目录名)。"""
if zip_path.exists():
zip_path.unlink()
count = 0
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED,
compresslevel=6) as archive:
for item in sorted(source.rglob("*")):
if item.is_file():
archive.write(item, Path(arc_root) / item.relative_to(source))
count += 1
return count
def _copy_docs(target: Path) -> int:
"""把三份正式文档拷到目标目录(UTF-8 BOM + CRLF)。"""
done = 0
for name in ("LICENSE.txt", "BEFORE-INSTALL.txt", "AFTER-INSTALL.txt"):
src = DOCS / name
if src.is_file():
write_readme(target / name, src.read_text(encoding="utf-8"))
done += 1
else:
print(f" [警告] 缺少文档 {src}")
return done
def main() -> int:
if not AGENT_SRC.is_dir():
print(f" [失败] 找不到被控端: {AGENT_SRC}")
return 1
if not APK_SRC.is_file():
print(f" [失败] 找不到 APK: {APK_SRC}")
return 1
dist = ROOT / "dist"
dist.mkdir(parents=True, exist_ok=True)
work = dist / "_build_tmp"
if work.exists():
shutil.rmtree(work, ignore_errors=True)
results = []
# ================= 1. 被控端 =================
print(" [1/3] 被控端(Windows)")
agent_name = f"ykxmz-agent-{VERSION}"
agent_dir = work / agent_name
shutil.copytree(AGENT_SRC, agent_dir,
ignore=shutil.ignore_patterns("data", "received",
"*.idsig", "*.log"))
for tool in TOOLS:
if not (agent_dir / tool).is_file():
src = ROOT / "tools" / tool
if src.is_file():
shutil.copy2(src, agent_dir / tool)
write_readme(agent_dir / "README-agent.txt", AGENT_README)
for junk in ("先看这个.txt", "使用说明.txt"):
target = agent_dir / junk
if target.is_file():
target.unlink()
_copy_docs(agent_dir)
if not (agent_dir / "ykxmz.exe").is_file():
print(" [失败] 被控端里没有 ykxmz.exe")
return 1
agent_zip = dist / f"{agent_name}.zip"
n = _zip_dir(agent_zip, agent_dir, agent_name)
results.append(("被控端", agent_zip, n))
# ================= 2. 服务器端 =================
print(" [2/3] 服务器端(随身 WiFi / Linux)")
server_name = f"ykxmz-server-{VERSION}"
server_dir = work / server_name
server_dir.mkdir(parents=True)
# 文件清单写死容易漏 —— watchdog.sh / net-tune.sh 都漏过一次。
# 改成:relay 目录里所有 .py / .sh 都带上。
wanted = sorted(
[f for f in RELAY_SRC.iterdir()
if f.suffix in (".py", ".sh") and f.is_file()],
key=lambda f: f.name)
for src in wanted:
shutil.copy2(src, server_dir / src.name)
write_readme(server_dir / "README-server.txt", RELAY_README)
_copy_docs(server_dir)
for must in ("relay.py", "install.sh", "watchdog.sh", "net-tune.sh"):
if not (server_dir / must).is_file():
print(f" [警告] 服务器端少了 {must}")
server_zip = dist / f"{server_name}.zip"
n = _zip_dir(server_zip, server_dir, server_name)
results.append(("服务器端", server_zip, n))
# ================= 3. 控制端(直接给 APK)=================
print(" [3/3] 控制端(手表)—— 不打 zip,直接给 APK")
# 顺带把说明也放一份在旁边,方便看
watch_note = dist / f"ykxmz-watch-{VERSION}-说明.txt"
write_readme(watch_note, WATCH_README)
results.append(("控制端", APK_SRC, 1))
shutil.rmtree(work, ignore_errors=True)
# ================= 汇总 =================
print()
print(" ================ 产物 ================")
ok = True
for label, path, count in results:
if not path.is_file():
print(f" {label}: ✗ 缺失!")
ok = False
continue
size = path.stat().st_size / 1024 / 1024
extra = f"({count} 个文件)" if count > 1 else ""
print(f" {label:6} {path.name:34} {size:6.2f} MB {extra}")
if not ok:
return 1
# ================= 验证 =================
print()
print(" 验证压缩包内容:")
for label, path, _count in results:
if path.suffix != ".zip":
continue
with zipfile.ZipFile(path) as archive:
names = archive.namelist()
bad = archive.testzip()
if bad:
print(f" [失败] {path.name} 里有坏文件: {bad}")
return 1
print(f" {path.name}: {len(names)} 个条目,完整")
with zipfile.ZipFile(results[0][1]) as archive:
names = archive.namelist()
if not any("ykxmz.exe" in n for n in names):
print(" [失败] 被控端包里没有 ykxmz.exe")
return 1
with zipfile.ZipFile(results[1][1]) as archive:
names = archive.namelist()
for must in ("relay.py", "install.sh", "watchdog.sh", "net-tune.sh"):
if not any(must in n for n in names):
print(f" [失败] 服务器端包里没有 {must}")
return 1
print()
print(" 三个产物齐全")
return 0
'''
# 手表说明单独抽出来(原来嵌在 main 里)
WATCH_README_BLOCK = '''WATCH_README = f"""========================================================
控制端(安卓手表) 版本 {VERSION}
========================================================
【装】
把 ykxmz-watch-{VERSION}.apk 传到手表上安装。
手表如果提示"未知来源",在设置里允许一下。
【连】
1) 打开 App,首页有四个东西:
中转设置(跨网络用) 填服务器端给的地址
局域网连接(同一个WiFi)同一个 WiFi 时走这条,最快
输入配对码连接 经中转连
服务器:还没测 点右边「检查服务器」看延迟
2) 电脑和手表在同一个 WiFi -> 点「局域网连接」,自动搜到电脑,点一下就连
电脑在外面 -> 点「输入配对码连接」,填电脑上那个 6 位码
3) 连上后是 10 个标签页:
媒体 屏幕 文件 语音 电脑 网络 系统 教室 效率 娱乐
【连不上时看这个】
App 会把错误翻译成人话:
"证书校验失败" -> 手表系统太旧或网络被劫持
"证书时间不对" -> 把手表的日期时间调成自动获取
"连接超时" -> 网络慢或被防火墙挡
"电脑拒绝连接" -> 电脑上 ykxmz 没开
"域名解析不了" -> 手表没联网
首页的「检查服务器」能测出到中转的延迟(快/一般/慢三档配色)。
【回退】
系统页最上面三个按钮:
回退上一步 撤销刚才那一步
回退全部 把能撤的都撤了
看能回退什么 列出还能撤哪些
能撤的:所有开关、所有画面(全屏大字/投图/通知等)
撤不了的:关机、重启、删文件、杀进程 —— 这些**不会**出现在回退列表里,
免得你以为什么都能退回去。
"""
'''
WATCH_PATTERN = re.compile(r'WATCH_README = f""".*?"""\n\n\n', re.S)
def main() -> int:
text = PKG.read_text(encoding="utf-8")
if "ykxmz-agent-" in text:
print(" 已经改过")
return 0
# 1. 把 WATCH_README 提到顶层的常量
# 原来它是嵌在 main() 里 write_readme 的第三个参数
old_watch = re.search(
r' write_readme\(watch_dir / "README-watch\.txt", f"""'
r'.*?"""\)\n', text, re.S)
if old_watch:
text = text[:old_watch.start()] + text[old_watch.end():]
print(" 摘掉了 main 里内嵌的手表说明")
else:
print(" [提示] 没找到内嵌的手表说明(可能已改)")
# 2. 插入 WATCH_README 常量(放在 RELAY_README 之后)
anchor = 'def write_readme(path: Path, text: str) -> None:'
if "WATCH_README =" not in text and anchor in text:
text = text.replace(anchor, WATCH_README_BLOCK + anchor, 1)
print(" 加了 WATCH_README 常量")
# 3. 换掉 main()
start = text.find("def main() -> int:")
end = text.find('if __name__ == "__main__":')
if start < 0 or end < 0 or end < start:
print(" [失败] 找不到 main() 的边界")
return 1
text = text[:start] + NEW_MAIN + text[end:]
print(" 替换了 main()(改成出三个产物)")
PKG.write_text(text, encoding="utf-8", newline="\n")
import ast
try:
ast.parse(text)
print(" package_remote.py 语法 OK")
except SyntaxError as exc:
print(f" 语法错误: 行 {exc.lineno}: {exc.msg}")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())