mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 12:30:44 +00:00
2.1.2:隧道稳定性加固(继续修「网站还是容易挂」)
2.1.1 修掉了 nettune 死锁之后,公网上到 200,但**过一阵又 530**。
这次抓到的是隧道自己:
cloudflared 的 precheck 输出(tunnel.log):
| UDP Connectivity region1.v2.argotunnel.com FAIL QUIC connection failed |
| TCP Connectivity region1.v2.argotunnel.com FAIL HTTP/2 connection is blocked or unreachable |
| Cloudflare API api.cloudflare.com:443 PASS API is reachable |
| ERROR: Allow outbound QUIC traffic on port 7844 or use HTTP2. |
也就是 **443 通、7844 不通**,而且是**间歇性**的(过几分钟自己又好了,
然后再次断)。Cloudflare 隧道的边缘连接走 7844(QUIC 走 UDP 7844、
HTTP/2 走 TCP 7844)。这条线路对它是间歇性阻断 —— 属于运营商那一侧,
设备改不了,但可以让 cloudflared 自己去适应。
== 两个改动 ==
1. **协议从写死改成 auto**
lanremote-tunnel --protocol quic -> --protocol auto
lanremote-tunnel-h2 --protocol http2 -> --protocol auto
原来两条实例各赌一个协议:那一刻 7844 的 UDP 和 TCP 都不通就一起死,
没有退路(实测连接数掉到 1/0、公网 530)。改成 auto 之后
cloudflared 自己在 QUIC / HTTP/2 之间挑当前能通的那条,
10 条连接全都有自适应能力。
2. **--retries 5 -> 1000000**
原来失败 5 次就退出、靠 systemd Restart=always 拉起来,
每次退出到重启之间网站都是断的。而这条线路的抖动是分钟级的 ——
实测隧道每 3~10 分钟就被重启一次(19:37 / 19:40 / 19:43 / 19:50 / 19:52),
公网跟着一起断。拉大之后抖动期间连接自己恢复,整条隧道不退出。
3. 顺手加日志轮转(tunnel.log 已经 2.98 MB,这台机器硬盘不大)。
== 实测 ==
改前:连接数 1/0,公网 530
改后:连接数 7+2(接近满配 10),公网连测 5 次全部 200
== 同步 ==
relay/deploy.sh 里的 MAIN_PROTO / ALT_PROTO 也改成 auto、
TUNNEL_BASE 的 --retries 也拉到 1000000,新机器装出来就是加固过的。
全量回归 46 个阶段全部通过。
This commit is contained in:
@@ -1,3 +1,35 @@
|
||||
## 2.1.2
|
||||
|
||||
- **隧道稳定性加固**(继续修「网站还是容易挂」)。查到隧道自己的诊断输出:
|
||||
|
||||
```
|
||||
| UDP Connectivity Cloudflare 边缘 FAIL 连不上 |
|
||||
| TCP Connectivity Cloudflare 边缘 FAIL 连不上或被挡住 |
|
||||
| Cloudflare API api.cloudflare.com:443 PASS 通的 |
|
||||
| ERROR: Allow outbound QUIC traffic on port 7844 or use HTTP2. |
|
||||
```
|
||||
|
||||
也就是说:**443 通,7844 不通**,而且是**一阵一阵的**
|
||||
(过几分钟自己又好了,然后再次断)。Cloudflare 隧道的边缘连接走 7844,
|
||||
这条线路对它是间歇性阻断 —— 这属于运营商那一侧,设备改不了。
|
||||
|
||||
**但可以让它自己去适应**:
|
||||
|
||||
- 两条隧道实例原来**各自写死一个协议**(一条只走 QUIC、一条只走 HTTP/2)。
|
||||
那一刻如果 7844 的 UDP 和 TCP 都不通,两条一起死,没有退路。
|
||||
现在都改成 **自动选择**,cloudflared 自己在 QUIC / HTTP/2 之间挑
|
||||
当前能通的那条。等于所有连接都有自适应能力,而不是
|
||||
"8 条赌 UDP、2 条赌 TCP"。
|
||||
|
||||
- 重试次数从 5 提到「一直重试」。原来失败 5 次就退出、靠系统重新拉起,
|
||||
每次退出到重启之间网站都是断的;而这条线路的抖动是分钟级的,
|
||||
5 次根本扛不过去(实测隧道每 3~10 分钟就被重启一次,公网跟着 530)。
|
||||
现在抖动期间连接自己恢复,整条隧道不退出。
|
||||
|
||||
**改完实测**:连接数 7+2(接近满配 10),公网连测 5 次全部 200。
|
||||
|
||||
- 顺手加了日志轮转(隧道日志已经涨到 3 MB,这台小机器硬盘不大)。
|
||||
|
||||
## 2.1.1
|
||||
|
||||
- **修一个会让网站整个挂掉的死锁**(这是「网站还是容易挂」的真因)。
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
2.1.2:隧道稳定性加固(继续修「网站还是容易挂」)
|
||||
|
||||
2.1.1 修掉了 nettune 死锁之后,公网上到 200,但**过一阵又 530**。
|
||||
这次抓到的是隧道自己:
|
||||
|
||||
cloudflared 的 precheck 输出(tunnel.log):
|
||||
|
||||
| UDP Connectivity region1.v2.argotunnel.com FAIL QUIC connection failed |
|
||||
| TCP Connectivity region1.v2.argotunnel.com FAIL HTTP/2 connection is blocked or unreachable |
|
||||
| Cloudflare API api.cloudflare.com:443 PASS API is reachable |
|
||||
| ERROR: Allow outbound QUIC traffic on port 7844 or use HTTP2. |
|
||||
|
||||
也就是 **443 通、7844 不通**,而且是**间歇性**的(过几分钟自己又好了,
|
||||
然后再次断)。Cloudflare 隧道的边缘连接走 7844(QUIC 走 UDP 7844、
|
||||
HTTP/2 走 TCP 7844)。这条线路对它是间歇性阻断 —— 属于运营商那一侧,
|
||||
设备改不了,但可以让 cloudflared 自己去适应。
|
||||
|
||||
== 两个改动 ==
|
||||
|
||||
1. **协议从写死改成 auto**
|
||||
lanremote-tunnel --protocol quic -> --protocol auto
|
||||
lanremote-tunnel-h2 --protocol http2 -> --protocol auto
|
||||
原来两条实例各赌一个协议:那一刻 7844 的 UDP 和 TCP 都不通就一起死,
|
||||
没有退路(实测连接数掉到 1/0、公网 530)。改成 auto 之后
|
||||
cloudflared 自己在 QUIC / HTTP/2 之间挑当前能通的那条,
|
||||
10 条连接全都有自适应能力。
|
||||
|
||||
2. **--retries 5 -> 1000000**
|
||||
原来失败 5 次就退出、靠 systemd Restart=always 拉起来,
|
||||
每次退出到重启之间网站都是断的。而这条线路的抖动是分钟级的 ——
|
||||
实测隧道每 3~10 分钟就被重启一次(19:37 / 19:40 / 19:43 / 19:50 / 19:52),
|
||||
公网跟着一起断。拉大之后抖动期间连接自己恢复,整条隧道不退出。
|
||||
|
||||
3. 顺手加日志轮转(tunnel.log 已经 2.98 MB,这台机器硬盘不大)。
|
||||
|
||||
== 实测 ==
|
||||
|
||||
改前:连接数 1/0,公网 530
|
||||
改后:连接数 7+2(接近满配 10),公网连测 5 次全部 200
|
||||
|
||||
== 同步 ==
|
||||
|
||||
relay/deploy.sh 里的 MAIN_PROTO / ALT_PROTO 也改成 auto、
|
||||
TUNNEL_BASE 的 --retries 也拉到 1000000,新机器装出来就是加固过的。
|
||||
|
||||
全量回归 46 个阶段全部通过。
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
r'''查隧道为什么掉连接(公网 530,连接数 1/0)。
|
||||
|
||||
上一轮才刚修掉 nettune 死锁、把公网拉到 200;这次重启 nettune 之后
|
||||
又变成 530 了。要分清是:
|
||||
* nettune 又卡了(那个死锁没修干净?)
|
||||
* 还是隧道自己掉了(cloudflared 的问题)
|
||||
'''
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT / "_build"))
|
||||
from devssh import run # noqa: E402
|
||||
|
||||
REMOTE = r'''
|
||||
echo "════ 1. 服务状态 + 有没有卡住的 ════"
|
||||
for s in lanremote-relay lanremote-tunnel lanremote-tunnel-h2 lanremote-nettune; do
|
||||
printf ' %-24s %s\n' "$s" "$(systemctl is-active $s)"
|
||||
done
|
||||
echo " --- nettune 卡住吗 ---"
|
||||
systemctl show -p SubState -p MainPID -p ExecMainStartTimestamp lanremote-nettune 2>&1 | sed 's/^/ /'
|
||||
echo " --- 有没有卡住的 systemctl ---"
|
||||
ps -eo pid,etime,cmd 2>/dev/null | grep -E 'systemctl|net-tune' | grep -v grep | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 2. net-tune 的修复在设备上吗 ════"
|
||||
grep -c NETTUNE_SERVICE_CALL /root/lanremote-relay/net-tune.sh
|
||||
echo " unit 里有吗: $(grep -c NETTUNE_SERVICE_CALL /etc/systemd/system/lanremote-nettune.service)"
|
||||
|
||||
echo
|
||||
echo "════ 3. 隧道为什么连接数是 0 ════"
|
||||
journalctl -u lanremote-tunnel --no-pager -n 25 2>/dev/null | tail -25 | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 4. 隧道 unit 长什么样(重启策略 / 协议)════"
|
||||
systemctl cat lanremote-tunnel 2>/dev/null | grep -vE '^#' | head -25 | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 5. cloudflared 进程 ════"
|
||||
ps -eo pid,etime,rss,cmd 2>/dev/null | grep cloudflared | grep -v grep | sed 's/^/ /'
|
||||
'''
|
||||
|
||||
|
||||
def main() -> int:
|
||||
out = run(REMOTE, timeout=300)
|
||||
text = out[1] if isinstance(out, tuple) else str(out)
|
||||
print(text)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
r'''看隧道为什么反复掉(公网 530 的真因)。
|
||||
|
||||
已知:
|
||||
nettune 死锁已修(SubState=exited,不再卡)
|
||||
但隧道每 3~10 分钟被重启一次(部分是我加的预案在救、部分是它自己掉)
|
||||
公网 530
|
||||
|
||||
要查的是 tunnel.log 里 cloudflared 到底在报什么。
|
||||
'''
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT / "_build"))
|
||||
from devssh import run # noqa: E402
|
||||
|
||||
REMOTE = r'''
|
||||
LOG=/root/lanremote-relay/tunnel.log
|
||||
H2LOG=/root/lanremote-relay/tunnel-h2.log
|
||||
|
||||
echo "════ 1. tunnel.log 里的错误行(最近 40 条)════"
|
||||
grep -iE 'error|fail|warn|timeout|retry|refused|EOF|unregister|connection' "$LOG" 2>/dev/null | tail -40 | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 2. tunnel.log 最后 25 行(原样)════"
|
||||
tail -25 "$LOG" 2>/dev/null | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 3. h2 那份的日志 ════"
|
||||
tail -15 "$H2LOG" 2>/dev/null | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 4. 两份日志多大(写爆了会拖慢小机器)════"
|
||||
ls -la "$LOG" "$H2LOG" 2>/dev/null | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 5. cloudflared 版本 + 配置 ════"
|
||||
/usr/local/bin/cloudflared --version 2>&1 | sed 's/^/ /'
|
||||
echo " --- config.yml ---"
|
||||
cat /root/.cloudflared/config.yml 2>/dev/null | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
echo "════ 6. 现在两条隧道的连接数 ════"
|
||||
for p in 20241 20242; do
|
||||
n=$(curl -s --max-time 5 "http://127.0.0.1:$p/metrics" 2>/dev/null | grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}' | head -1)
|
||||
echo " $p -> ${n:-拿不到}"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "════ 7. 公网现在通吗 ════"
|
||||
echo " $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 https://relay.xxmxxs.top/v1/health)"
|
||||
'''
|
||||
|
||||
|
||||
def main() -> int:
|
||||
out = run(REMOTE, timeout=300)
|
||||
text = out[1] if isinstance(out, tuple) else str(out)
|
||||
print(text)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,162 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
r'''增强隧道稳定性 —— 「网站还是容易挂」的真因修法。
|
||||
|
||||
== 查到什么 ==
|
||||
|
||||
cloudflared 自己的 precheck 输出(tunnel.log):
|
||||
|
||||
| UDP Connectivity region1.v2.argotunnel.com FAIL QUIC connection failed |
|
||||
| UDP Connectivity region2.v2.argotunnel.com FAIL QUIC connection failed |
|
||||
| TCP Connectivity region1.v2.argotunnel.com FAIL HTTP/2 connection is blocked or unreachable |
|
||||
| TCP Connectivity region2.v2.argotunnel.com FAIL HTTP/2 connection is blocked or unreachable |
|
||||
| Cloudflare API api.cloudflare.com:443 PASS API is reachable |
|
||||
| ERROR: Allow outbound QUIC traffic on port 7844 or use HTTP2. |
|
||||
|
||||
也就是:**443 通,7844 不通**,而且是**间歇性**的
|
||||
(日志后面又出现 Registered tunnel connection,过一阵又掉)。
|
||||
|
||||
Cloudflare 隧道的边缘连接走 7844(QUIC 走 UDP 7844、HTTP/2 走 TCP 7844)。
|
||||
这条线路对 7844 是间歇性阻断的 —— 这不是设备能修的,
|
||||
但**可以让 cloudflared 自己去适应**。
|
||||
|
||||
== 现在的配置有两个问题 ==
|
||||
|
||||
1. **两条实例各写死一个协议**
|
||||
lanremote-tunnel --protocol quic (只走 UDP 7844)
|
||||
lanremote-tunnel-h2 --protocol http2 (只走 TCP 7844)
|
||||
如果那一刻 7844 的 UDP 和 TCP 都不通,两条一起死 —— 没有退路。
|
||||
实测就是这样:连接数掉到 1/0,公网 530。
|
||||
|
||||
2. **--retries 5**
|
||||
cloudflared 重试 5 次就**退出**,靠 systemd Restart=always 拉起来。
|
||||
每次退出/重启期间网站都是断的。而这个线路的抖动是分钟级的,
|
||||
5 次远远不够扛过去。
|
||||
|
||||
== 改法 ==
|
||||
|
||||
1. `--protocol auto` —— 让 cloudflared **自己**在 QUIC 和 HTTP/2 之间选,
|
||||
哪条通走哪条。两条实例都改成 auto,等于 10 条连接全都能自适应。
|
||||
(而不是现在这样"8 条赌 UDP、2 条赌 TCP")
|
||||
|
||||
2. `--retries` 提到很大(相当于"一直重试,别退出")——
|
||||
抖动期间连接会自己恢复,不会整条隧道退出让网站断掉。
|
||||
|
||||
3. 顺手加日志轮转:tunnel.log 已经涨到 2.98 MB,
|
||||
这台机器只有 460MB 内存 + 小硬盘,无限增长不合适。
|
||||
'''
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT / "_build"))
|
||||
from devssh import run # noqa: E402
|
||||
|
||||
|
||||
def patch_unit(name: str, proto: str) -> str:
|
||||
"""读设备上现有的 unit,改协议和重试次数。
|
||||
|
||||
用 sed 现场改而不是整份重写 —— 现有 unit 里还有
|
||||
metrics 端口、ha-connections、MemoryMax 这些实测调出来的参数,
|
||||
整份重写容易漏掉。
|
||||
"""
|
||||
cmds = [
|
||||
# 协议
|
||||
"sed -i 's/--protocol [a-z0-9]*/--protocol %s/' %s" % (proto, name),
|
||||
# 重试次数:改成很大(一直重试)
|
||||
"sed -i 's/--retries [0-9]*/--retries 1000000/' %s" % name,
|
||||
]
|
||||
return " && ".join(cmds)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
print("=" * 62)
|
||||
print(" 隧道稳定性:协议改 auto + 加大重试 + 日志轮转")
|
||||
print("=" * 62)
|
||||
|
||||
UNIT_DIR = "/etc/systemd/system"
|
||||
|
||||
print()
|
||||
print(" ── 1. 两条隧道都改成 --protocol auto ──")
|
||||
out = run(
|
||||
"cd %s && "
|
||||
"sed -i 's/--protocol [a-z0-9]*/--protocol auto/' "
|
||||
"lanremote-tunnel.service lanremote-tunnel-h2.service && "
|
||||
"echo ' tunnel:'; grep -o -- '--protocol [a-z0-9]*' "
|
||||
"lanremote-tunnel.service; "
|
||||
"echo ' h2:'; grep -o -- '--protocol [a-z0-9]*' "
|
||||
"lanremote-tunnel-h2.service; "
|
||||
# 重试次数
|
||||
"sed -i 's/--retries [0-9]*/--retries 1000000/' "
|
||||
"lanremote-tunnel.service lanremote-tunnel-h2.service && "
|
||||
"echo ' 重试:'; grep -o -- '--retries [0-9]*' "
|
||||
"lanremote-tunnel.service lanremote-tunnel-h2.service"
|
||||
% UNIT_DIR, timeout=120)
|
||||
for ln in out[1].strip().splitlines():
|
||||
print(" " + ln)
|
||||
|
||||
print()
|
||||
print(" ── 2. 日志轮转(tunnel.log 已经 2.98 MB)──")
|
||||
out = run(
|
||||
"cat > /etc/logrotate.d/lanremote <<'EOF'\n"
|
||||
"/root/lanremote-relay/*.log {\n"
|
||||
" size 5M\n"
|
||||
" rotate 2\n"
|
||||
" compress\n"
|
||||
" missingok\n"
|
||||
" notifempty\n"
|
||||
" copytruncate\n"
|
||||
"}\n"
|
||||
"EOF\n"
|
||||
"echo ' logrotate 配置已写'; "
|
||||
"logrotate --debug /etc/logrotate.d/lanremote 2>&1 | tail -3",
|
||||
timeout=120)
|
||||
for ln in out[1].strip().splitlines():
|
||||
print(" " + ln)
|
||||
|
||||
print()
|
||||
print(" ── 3. 重启两条隧道让新参数生效 ──")
|
||||
out = run(
|
||||
"systemctl daemon-reload && "
|
||||
"systemctl restart lanremote-tunnel lanremote-tunnel-h2 && "
|
||||
"echo ' 等 40 秒让连接建立…' && sleep 40 && "
|
||||
"echo \" tunnel: $(systemctl is-active lanremote-tunnel)\"; "
|
||||
"echo \" h2: $(systemctl is-active lanremote-tunnel-h2)\"",
|
||||
timeout=300)
|
||||
for ln in out[1].strip().splitlines():
|
||||
print(" " + ln)
|
||||
|
||||
print()
|
||||
print(" ── 4. 连接数 ──")
|
||||
out = run(
|
||||
"for p in 20241 20242; do "
|
||||
"n=$(curl -s --max-time 5 http://127.0.0.1:$p/metrics 2>/dev/null "
|
||||
"| grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}' "
|
||||
"| head -1); "
|
||||
"echo \" $p -> ${n:-拿不到}\"; done; "
|
||||
"echo ' --- 用的什么协议 ---'; "
|
||||
"grep -o 'protocol=[a-z0-9]*' /root/lanremote-relay/tunnel.log 2>/dev/null "
|
||||
"| tail -6 | sort | uniq -c | sed 's/^/ /'", timeout=120)
|
||||
for ln in out[1].strip().splitlines():
|
||||
print(" " + ln)
|
||||
|
||||
print()
|
||||
print(" ── 5. 公网(连测 5 次看稳不稳)──")
|
||||
out = run(
|
||||
"for i in 1 2 3 4 5; do "
|
||||
"c=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "
|
||||
"https://relay.xxmxxs.top/v1/health); "
|
||||
"echo \" 第 $i 次: $c\"; sleep 3; done", timeout=200)
|
||||
for ln in out[1].strip().splitlines():
|
||||
print(" " + ln)
|
||||
|
||||
print()
|
||||
print(" 说明:3844/7844 那条线路封不封是运营商的事,设备改不了。")
|
||||
print(" 但 --protocol auto 让 cloudflared 自己绕,")
|
||||
print(" --retries 拉大让它别退出 —— 抖动期间能自己恢复。")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -17,7 +17,7 @@ import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
|
||||
VERSION = "2.1.1"
|
||||
VERSION = "2.1.2"
|
||||
NAME = f"ykxmz-{VERSION}"
|
||||
|
||||
AGENT_SRC = ROOT / "dist_exe" / "ykxmz"
|
||||
|
||||
@@ -23,7 +23,7 @@ def _latest_apk() -> Path:
|
||||
(ROOT / "dist").glob("*watch*.apk"),
|
||||
key=lambda p: p.stat().st_mtime, reverse=True)
|
||||
return candidates[0] if candidates else \
|
||||
ROOT / "dist" / "ykxmz-watch-2.1.1.apk"
|
||||
ROOT / "dist" / "ykxmz-watch-2.1.2.apk"
|
||||
|
||||
|
||||
APK = _latest_apk()
|
||||
|
||||
@@ -26,9 +26,9 @@ ROOT = Path(__file__).resolve().parent.parent
|
||||
# 被控端 -> 一个 zip
|
||||
# 服务器端 -> 一个 zip
|
||||
# 控制端 -> 直接给 APK(不打 zip)
|
||||
AGENT_ZIP = ROOT / "dist" / "ykxmz-agent-2.1.1.zip"
|
||||
SERVER_ZIP = ROOT / "dist" / "ykxmz-server-2.1.1.zip"
|
||||
WATCH_APK = ROOT / "dist" / "ykxmz-watch-2.1.1.apk"
|
||||
AGENT_ZIP = ROOT / "dist" / "ykxmz-agent-2.1.2.zip"
|
||||
SERVER_ZIP = ROOT / "dist" / "ykxmz-server-2.1.2.zip"
|
||||
WATCH_APK = ROOT / "dist" / "ykxmz-watch-2.1.2.apk"
|
||||
TOOLCHAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\starklink\toolchain")
|
||||
JAVAC = TOOLCHAIN / "jdk17" / "bin" / "javac.exe"
|
||||
JAVA = TOOLCHAIN / "jdk17" / "bin" / "java.exe"
|
||||
@@ -89,7 +89,7 @@ def main() -> int:
|
||||
for label, path in (("被控端", agent_dir / "README-agent.txt"),
|
||||
("服务器端", relay_dir / "README-server.txt"),
|
||||
("控制端(旁边那份)",
|
||||
ROOT / "dist" / "ykxmz-watch-2.1.1-说明.txt")):
|
||||
ROOT / "dist" / "ykxmz-watch-2.1.2-说明.txt")):
|
||||
raw = path.read_bytes() if path.is_file() else b""
|
||||
check(f"{label}说明有 UTF-8 BOM",
|
||||
raw[:3] == b"\xef\xbb\xbf", raw[:3])
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.lanremote.watch"
|
||||
android:versionCode="5"
|
||||
android:versionName="2.1.1">
|
||||
android:versionName="2.1.2">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
@@ -27,7 +27,7 @@ $d8 = Join-Path $bt "d8.bat"
|
||||
|
||||
$work = Join-Path $android "build"
|
||||
$outDir = Join-Path $root "dist"
|
||||
$apkName = "ykxmz-watch-2.1.1.apk"
|
||||
$apkName = "ykxmz-watch-2.1.2.apk"
|
||||
|
||||
function Step($text) { Write-Host "`n=== $text ===" -ForegroundColor Cyan }
|
||||
|
||||
@@ -65,7 +65,7 @@ $unsigned = Join-Path $work "app-unsigned.apk"
|
||||
--min-sdk-version 24 `
|
||||
--target-sdk-version 34 `
|
||||
--version-code 5 `
|
||||
--version-name "2.1.1" `
|
||||
--version-name "2.1.2" `
|
||||
--auto-add-overlay
|
||||
if ($LASTEXITCODE -ne 0) { throw "aapt2 link 失败" }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
========================================================
|
||||
|
||||
软件名称:ykxmz
|
||||
版本:2.1.1
|
||||
版本:2.1.2
|
||||
作者:小麦子
|
||||
|
||||
装好之后看这一页:怎么确认它在跑、怎么改设置、
|
||||
@@ -197,7 +197,7 @@
|
||||
八、版本记录
|
||||
--------------------------------------------------------
|
||||
|
||||
2.1.1
|
||||
2.1.2
|
||||
* 下载改走 Cloudflare 边缘缓存 —— 安装包和 APK 快了几十倍
|
||||
* 跨网络更稳:隧道**两种协议同时跑**(QUIC + HTTP/2,
|
||||
合计 10 条连接),一种协议犯病另一种还在服务
|
||||
@@ -218,6 +218,6 @@
|
||||
|
||||
--------------------------------------------------------
|
||||
作者:小麦子
|
||||
软件:ykxmz 2.1.1
|
||||
软件:ykxmz 2.1.2
|
||||
许可条款见《许可协议》(LICENSE.txt)
|
||||
--------------------------------------------------------
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
========================================================
|
||||
|
||||
软件名称:ykxmz
|
||||
版本:2.1.1
|
||||
版本:2.1.2
|
||||
作者:小麦子
|
||||
|
||||
请你**在安装之前**花三分钟读完这一页。里面有几条很要紧的
|
||||
@@ -164,6 +164,6 @@ ykxmz 是一套自己搭建的远程管理工具,由三部分组成:
|
||||
|
||||
--------------------------------------------------------
|
||||
作者:小麦子
|
||||
软件:ykxmz 2.1.1
|
||||
软件:ykxmz 2.1.2
|
||||
继续安装,即表示你已阅读并同意《许可协议》。
|
||||
--------------------------------------------------------
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
========================================================
|
||||
|
||||
软件名称:ykxmz(远程管理工具)
|
||||
版本:2.1.1
|
||||
版本:2.1.2
|
||||
作者:小麦子
|
||||
生效日期:2026 年 10 月 5 日
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
> 都不许拿去做下面第三条那些事。**
|
||||
>
|
||||
> (早先这版文件写的是"软件许可协议",里面有一条"不得修改"——
|
||||
> 那和 AGPL 冲突,所以 2.1.1 起拆开了:代码授权归 LICENSE,
|
||||
> 那和 AGPL 冲突,所以 2.1.2 起拆开了:代码授权归 LICENSE,
|
||||
> 使用约束归这份文件。)
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
--------------------------------------------------------
|
||||
作者:小麦子
|
||||
软件:ykxmz 2.1.1
|
||||
软件:ykxmz 2.1.2
|
||||
|
||||
如果你不同意本条款的任何一条,请不要安装或使用本软件。
|
||||
代码授权条款见仓库根目录 LICENSE(GNU AGPL-3.0)。
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
========================================================
|
||||
|
||||
软件名称:ykxmz(远程管理工具)
|
||||
版本:2.1.1
|
||||
版本:2.1.2
|
||||
作者:小麦子
|
||||
生效日期:2026 年 10 月 5 日
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
> 都不许拿去做下面第三条那些事。**
|
||||
>
|
||||
> (早先这版文件写的是"软件许可协议",里面有一条"不得修改"——
|
||||
> 那和 AGPL 冲突,所以 2.1.1 起拆开了:代码授权归 LICENSE,
|
||||
> 那和 AGPL 冲突,所以 2.1.2 起拆开了:代码授权归 LICENSE,
|
||||
> 使用约束归这份文件。)
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
--------------------------------------------------------
|
||||
作者:小麦子
|
||||
软件:ykxmz 2.1.1
|
||||
软件:ykxmz 2.1.2
|
||||
|
||||
如果你不同意本条款的任何一条,请不要安装或使用本软件。
|
||||
代码授权条款见仓库根目录 LICENSE(GNU AGPL-3.0)。
|
||||
@@ -173,7 +173,7 @@
|
||||
========================================================
|
||||
|
||||
软件名称:ykxmz
|
||||
版本:2.1.1
|
||||
版本:2.1.2
|
||||
作者:小麦子
|
||||
|
||||
请你**在安装之前**花三分钟读完这一页。里面有几条很要紧的
|
||||
@@ -334,7 +334,7 @@ ykxmz 是一套自己搭建的远程管理工具,由三部分组成:
|
||||
|
||||
--------------------------------------------------------
|
||||
作者:小麦子
|
||||
软件:ykxmz 2.1.1
|
||||
软件:ykxmz 2.1.2
|
||||
继续安装,即表示你已阅读并同意《许可协议》。
|
||||
--------------------------------------------------------
|
||||
|
||||
@@ -345,7 +345,7 @@ ykxmz 是一套自己搭建的远程管理工具,由三部分组成:
|
||||
========================================================
|
||||
|
||||
软件名称:ykxmz
|
||||
版本:2.1.1
|
||||
版本:2.1.2
|
||||
作者:小麦子
|
||||
|
||||
装好之后看这一页:怎么确认它在跑、怎么改设置、
|
||||
@@ -539,7 +539,7 @@ ykxmz 是一套自己搭建的远程管理工具,由三部分组成:
|
||||
八、版本记录
|
||||
--------------------------------------------------------
|
||||
|
||||
2.1.1
|
||||
2.1.2
|
||||
* 下载改走 Cloudflare 边缘缓存 —— 安装包和 APK 快了几十倍
|
||||
* 跨网络更稳:隧道**两种协议同时跑**(QUIC + HTTP/2,
|
||||
合计 10 条连接),一种协议犯病另一种还在服务
|
||||
@@ -560,6 +560,6 @@ ykxmz 是一套自己搭建的远程管理工具,由三部分组成:
|
||||
|
||||
--------------------------------------------------------
|
||||
作者:小麦子
|
||||
软件:ykxmz 2.1.1
|
||||
软件:ykxmz 2.1.2
|
||||
许可条款见《许可协议》(LICENSE.txt)
|
||||
--------------------------------------------------------
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@
|
||||
; ============================================================================
|
||||
|
||||
#define MyAppName "ykxmz"
|
||||
#define MyAppVersion "2.1.1"
|
||||
#define MyAppVersion "2.1.2"
|
||||
#define MyAppPublisher "小麦子"
|
||||
#define MyAppExeName "ykxmz.exe"
|
||||
|
||||
@@ -163,7 +163,7 @@ Filename: "{app}\{#MyAppExeName}"; Parameters: "--autostart on"; \
|
||||
; 代价是安装器和它是父子关系:用"等整个进程树"的方式调安装器会卡住
|
||||
; (PowerShell 的 Start-Process -Wait 就是)。
|
||||
; 学校批量部署请用 cmd:
|
||||
; cmd /c ykxmz-setup-2.1.1.exe /VERYSILENT /CODE=123456
|
||||
; cmd /c ykxmz-setup-2.1.2.exe /VERYSILENT /CODE=123456
|
||||
; cmd 只等安装器本身,不等孙子进程,不会卡。
|
||||
Filename: "{app}\{#MyAppExeName}"; Parameters: "--silent"; \
|
||||
Description: "立即启动(后台运行,不显示窗口)"; \
|
||||
|
||||
+31
-5
@@ -204,9 +204,26 @@ fi
|
||||
#
|
||||
# (早先这里写的是"两条同时跑会互相争抢",那个结论是错的,已作废。
|
||||
# 再早还写过"运营商封 UDP",那个测量方法本身是错的,也作废。)
|
||||
MAIN_PROTO=quic
|
||||
# ⚠ 用 auto,不要写死 quic / http2。
|
||||
#
|
||||
# 实测(2026-10-08)这条线路对 Cloudflare 隧道的 **7844 端口**
|
||||
# (QUIC 走 UDP 7844、HTTP/2 走 TCP 7844)是**间歇性阻断**的,
|
||||
# 而 443 一直是通的。cloudflared 自己的 precheck 报得很清楚:
|
||||
#
|
||||
# | UDP Connectivity region1.v2.argotunnel.com FAIL QUIC connection failed |
|
||||
# | TCP Connectivity region1.v2.argotunnel.com FAIL HTTP/2 connection is blocked or unreachable |
|
||||
# | Cloudflare API api.cloudflare.com:443 PASS API is reachable |
|
||||
# | ERROR: Allow outbound QUIC traffic on port 7844 or use HTTP2. |
|
||||
#
|
||||
# 写死协议的时候,那一刻 7844 的 UDP 和 TCP 都不通 -> 两条实例一起死
|
||||
# -> 连接数掉到 1/0 -> 公网 530。实测就是这么挂的。
|
||||
#
|
||||
# 改成 auto 之后 **cloudflared 自己**在 QUIC / HTTP/2 之间挑
|
||||
# 当前能通的那条,两条实例都带自适应能力(而不是
|
||||
# "8 条赌 UDP、2 条赌 TCP")。改完实测连接数 7+2、公网连测 5 次全 200。
|
||||
MAIN_PROTO=auto
|
||||
MAIN_CONNS="${QUIC_CONNS:-8}"
|
||||
ALT_PROTO=http2
|
||||
ALT_PROTO=auto
|
||||
ALT_CONNS="${H2_CONNS:-2}"
|
||||
|
||||
# metrics 端口必须**显式钉死**。
|
||||
@@ -581,9 +598,18 @@ EOF
|
||||
# --edge-ip-version 4 这条线路有 IPv6 地址但实际不通,
|
||||
# 边缘默认优先 IPv6 会一直超时
|
||||
# --ha-connections N 每个单元各自多少条连接(默认 quic 8 / h2 2)
|
||||
# --retries 5 连边缘失败时多重试
|
||||
# --metrics ADDR:PORT **必须显式钉死**,见下面的注释
|
||||
TUNNEL_BASE="--no-autoupdate --edge-ip-version 4 --retries 5"
|
||||
# --retries N 连边缘失败时重试多少次
|
||||
#
|
||||
# ⚠ --retries 从 5 提到 1000000(相当于"一直重试,别退出")。
|
||||
#
|
||||
# 原来 5 次就退出,靠 systemd Restart=always 拉起来 ——
|
||||
# 每次退出到重启之间网站都是断的。而这条线路对 7844 的阻断是
|
||||
# **分钟级**的,5 次重试远远扛不过去:实测隧道每 3~10 分钟
|
||||
# 就被重启一次,公网跟着 530。
|
||||
#
|
||||
# 拉大之后,抖动期间连接自己恢复,整条隧道不退出,
|
||||
# 网站也就不会跟着断。
|
||||
TUNNEL_BASE="--no-autoupdate --edge-ip-version 4 --retries 1000000"
|
||||
|
||||
if [ -n "$TOKEN" ]; then
|
||||
# Token 模式:Token 存单独的 600 权限文件,不写进 unit
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ from collections import deque
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
|
||||
VERSION = "2.1.1"
|
||||
VERSION = "2.1.2"
|
||||
|
||||
# ---------------- 参数(都能用环境变量覆盖)----------------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""局域网遥控 · Windows 被控端。"""
|
||||
|
||||
__version__ = "2.1.1"
|
||||
__version__ = "2.1.2"
|
||||
APP_NAME = "ykxmz"
|
||||
|
||||
@@ -27,12 +27,12 @@ VSVersionInfo(
|
||||
[
|
||||
StringStruct("CompanyName", "ykxmz"),
|
||||
StringStruct("FileDescription", "ykxmz"),
|
||||
StringStruct("FileVersion", "2.1.1.0"),
|
||||
StringStruct("FileVersion", "2.1.2.0"),
|
||||
StringStruct("InternalName", "ykxmz"),
|
||||
StringStruct("LegalCopyright", "ykxmz"),
|
||||
StringStruct("OriginalFilename", "ykxmz.exe"),
|
||||
StringStruct("ProductName", "ykxmz"),
|
||||
StringStruct("ProductVersion", "2.1.1.0"),
|
||||
StringStruct("ProductVersion", "2.1.2.0"),
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user