服务端 zip 加一键部署脚本(cloudflared 安装 + 部署 + 公网,全自动)

用户要求:服务器端文件里放一个 .sh,双击就能检查 cloudflared 装没装、
自动部署、配好公网,以后全自动。

== 新增 ==

relay/deploy.sh        一键部署主脚本,7 步全自动:
                       环境检查 -> 装 cloudflared -> 部署程序 -> 网络调优
                       -> 写 4 个 systemd 服务 -> 配隧道 -> 启动自检打公网地址
relay/deploy-tune.sh   网络调优,可单独重跑:
                       keepalive 30/10/3 + 路径 MTU 探测 + MSS 1360
                       + 接口 MTU 1400 + mask networkd-wait-online
                       每一项都写明了实测依据

用法:
    bash deploy.sh                           复用已有凭据,全自动
    TUNNEL_TOKEN=eyJh... bash deploy.sh      Token 模式
    bash deploy.sh --hostname relay.你的域名  换域名
    bash deploy.sh --skip-tunnel             只装中转
    bash deploy.sh --help                    全部参数

重跑 = 升级;已有数据/配对码/管理密码/凭据/手改过的 config.yml 都不动。

== 自动化到什么程度 ==

* cloudflared 不在就自动下载装上(并校验能执行)
* 隧道支持两种模式:已有凭据文件、或 TUNNEL_TOKEN
* **不传 --hostname 且没有 Token 时明确提示要填**,不会静默用一个写死的值
  (用户明确说过:这个中转站是他自己用的,不对外开放,
   绝不能把私人域名烧成默认值)
* deploy-tune.sh 的 MTU 取 1400:路径 MTU 实测 1472,
  而 MSS 钳制只管 TCP、QUIC 走 UDP 完全不受保护;
  接口 MTU 降到 1400 后 QUIC 建齐 10 条连接从 28 秒缩到 12 秒

== 顺带修掉两个真 bug ==

1. write_tunnel_unit 写的文件名漏了 .service 后缀 ——
   文件写下去了但 systemd 完全看不见,enable 还会安静地失败。
2. 发布包一直缺 site_shots/(老 bug):
   package_remote.py 用 iterdir() + is_file() 收文件,目录进不去。
   新机器装完官网截图全是 404。只有从 zip 解压真跑一遍才暴露。
   同时把 deploy.sh 里 site_shots 的检查降级成警告(缺截图不该让部署失败)。

另外给 deploy-tune.sh 清旧 MSS 规则的循环加了 10 次上限 ——
原写法在 -D 报成功但规则仍在时会死循环把整个部署卡死。

== 验证 ==

* _build/test_deploy_sh.sh        沙箱 65 项,全通过
* _build/test_zip_deploy.sh       从发布 zip 解压再跑,30 项,全通过
* _build/test_deploy_real.sh      **真机 Debian 上实测**(新增):
    zip 解出 17 个文件 -> 语法/LF/无 BOM 通过
    --help 退出码 0 且无副作用、未知参数退出码 2
    沙箱安装成功、幂等重跑哨兵不被冲
    现有三个中转服务全程 active,自检 200
This commit is contained in:
xmz7891
2026-10-07 17:28:09 +08:00
parent d4f335b8f9
commit facb156aca
10 changed files with 2331 additions and 89 deletions
+149
View File
@@ -0,0 +1,149 @@
#!/bin/bash
# 网络调优 —— 供 deploy.sh 一键部署时调用,也可以单独重跑。
#
# 用法:
# bash deploy-tune.sh # 用默认值
# bash deploy-tune.sh --prefix /tmp/x # 装到沙箱目录(测试用)
# bash deploy-tune.sh --help
#
# ────────────────────────────────────────────────────────────────
# 分工(重要:同一个值绝不能有两处来源)
# ────────────────────────────────────────────────────────────────
# 本脚本负责: TCP keepalive、开机加速
# net-tune.sh 负责:MSS 钳制、接口 MTU、路径 MTU 探测
#
# 本脚本第 2 步会**调用 net-tune.sh**,所以单独跑本脚本
# 也能拿到完整的调优效果。
#
# 早先两边都设了一遍 MSS 和 MTU,结果"到底哪个值生效"很难查
# (net-tune.sh 写着保持 1500,本脚本写着压到 1400,谁后跑谁赢)。
# 现在只有一个出处:net-tune.sh。
#
# ────────────────────────────────────────────────────────────────
# 本脚本做的两件事,各自的实测依据
# ────────────────────────────────────────────────────────────────
#
# ① TCP keepalive 改成 30/10/3(默认是 7200/75/9)
# 为什么:这条 4G 线路会**静默丢连接** —— 不发明文 FIN/RST,
# 对端就以为连接还在。而 Linux 默认要 7200 秒(2 小时)才发现死链。
# 于是隧道/长轮询会挂在一条早已死掉的连接上,表现就是
# "过了几分钟突然 502 / 连接超时"。
# 改成 30 秒首发探测、每 10 秒一次、3 次没回应判死 ——
# 最快 60 秒就能发现并重建。
#
# ② mask 掉 systemd-networkd-wait-online
# 这台机器 NetworkManager 和 systemd-networkd 同时在跑,
# 但 wlan0 归 NetworkManager 管。
# systemd-networkd-wait-online 傻等一个不归它管的网络,
# 干等 2 分钟超时然后 failed,把 network-online.target 拖住 ——
# relay / tunnel 全跟着等。
# 实测:用户空间启动 2 分 6 秒 -> 14 秒;
# 掉电重启后公网恢复 2 分 10 秒 -> 24 秒。
# ────────────────────────────────────────────────────────────────
set -u
PREFIX=""
while [ $# -gt 0 ]; do
case "$1" in
--prefix) PREFIX="${2:-}"; shift 2 ;;
--help|-h)
echo "用法: bash deploy-tune.sh [--prefix DIR]"
echo
echo " 本脚本负责 TCP keepalive 和开机加速;"
echo " MSS 钳制 / 接口 MTU 由 net-tune.sh 负责,第 2 步会调用它。"
echo
echo " --prefix DIR 安装根目录(默认 /),测试时指到临时目录"
echo " --help 显示这段帮助"
exit 0 ;;
*) echo "未知参数: $1(用 --help 看用法)"; exit 2 ;;
esac
done
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
SYSCTL_DIR="$PREFIX/etc/sysctl.d"
SYSCTL_FILE="$SYSCTL_DIR/97-ykxmz-network.conf"
echo " 网络调优(前缀: ${PREFIX:-/})"
# ────────────────────────────────────────────────────────────────
# 1. TCP keepalive:30 秒就发现死链
# ────────────────────────────────────────────────────────────────
echo
echo " [1/4] TCP keepalive(默认 7200 秒太慢,死链要挂 2 小时才被发现)"
mkdir -p "$SYSCTL_DIR"
# 注意:MSS / MTU / mtu_probing 由 net-tune.sh 负责,
# 别往这个文件里加那些 —— 会变成两处来源。
cat > "$SYSCTL_FILE" <<'EOF'
# ykxmz: 这条 4G 线路会静默丢连接(不发明文 FIN/RST),
# 而 Linux 默认要 7200 秒才发现死链 —— 表现就是"过几分钟突然 502"。
# 改成 30 秒首发探测、每 10 秒一次、3 次没回应判死。
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3
EOF
if [ -w /proc/sys/net/ipv4/tcp_keepalive_time ]; then
sysctl -p "$SYSCTL_FILE" >/dev/null 2>&1 || \
sysctl --system >/dev/null 2>&1 || true
fi
printf " keepalive: %s 秒首发 / %s 秒间隔 / %s 次判死\n" \
"$(cat /proc/sys/net/ipv4/tcp_keepalive_time 2>/dev/null || echo '?')" \
"$(cat /proc/sys/net/ipv4/tcp_keepalive_intvl 2>/dev/null || echo '?')" \
"$(cat /proc/sys/net/ipv4/tcp_keepalive_probes 2>/dev/null || echo '?')"
echo " 配置文件: $SYSCTL_FILE"
# ────────────────────────────────────────────────────────────────
# 2. MSS / 接口 MTU / 路径探测 —— 交给 net-tune.sh(唯一出处)
# ────────────────────────────────────────────────────────────────
echo
echo " [2/4] MSS 钳制 / 接口 MTU / 路径探测(调用 net-tune.sh)"
TUNE="$SCRIPT_DIR/net-tune.sh"
NETTUNE_OK=0
if [ -f "$TUNE" ]; then
if bash "$TUNE"; then
NETTUNE_OK=1
else
echo " ⚠ net-tune.sh 报错,继续"
fi
else
echo " ⚠ 找不到 net-tune.sh($TUNE)"
echo " 它负责 MSS 钳制和接口 MTU,缺了它这次就只做了 keepalive 那一半。"
fi
# ────────────────────────────────────────────────────────────────
# 3. 加快开机(mask networkd-wait-online)
# ────────────────────────────────────────────────────────────────
echo
echo " [3/4] 关掉 systemd-networkd-wait-online(网络不归它管,白等 2 分钟)"
if command -v systemctl >/dev/null 2>&1; then
systemctl disable --now systemd-networkd-wait-online.service \
>/dev/null 2>&1 || true
systemctl mask systemd-networkd-wait-online.service \
>/dev/null 2>&1 || true
echo " 状态: $(systemctl is-enabled systemd-networkd-wait-online.service 2>&1)"
else
echo " [跳过] 没有 systemctl"
fi
# ────────────────────────────────────────────────────────────────
# 4. 收尾
# ────────────────────────────────────────────────────────────────
# MSS / MTU 只对**新建连接**生效。net-tune.sh 自己会把正在跑的隧道
# 重启一遍;只有它没跑成的时候这里才补一次,免得重启两遍。
echo
echo " [4/4] 收尾"
if [ "$NETTUNE_OK" = "1" ]; then
echo " net-tune.sh 已经处理过隧道重建,这里不重复重启"
elif command -v systemctl >/dev/null 2>&1; then
for svc in lanremote-tunnel lanremote-tunnel-h2; do
if systemctl is-active --quiet "$svc" 2>/dev/null; then
echo " $svc 正在跑,补一次重启让新参数生效"
systemctl restart "$svc" >/dev/null 2>&1 || true
fi
done
else
echo " [跳过] 没有 systemctl"
fi
echo
echo " 网络调优完成(keepalive 见上;MSS/MTU 见 net-tune.sh 的输出)"