#!/bin/bash # 网络调优:修 MTU 问题(这次找到的**真正根因**)。 # ════════════════════════════════════════════════════════════════ # 证据链 # ════════════════════════════════════════════════════════════════ # 现象:新建 TLS 连接约 30% 失败,但连接一旦建立就接近 100% 成功 # -> 典型的大包被丢、小包能过 # # ping 实测(到 1.1.1.1,-M do 禁止分片): # 包 1448 通 包 1488 丢 包 1500 全丢 # 接口 MTU 写着 1500,但实际路径扛不住。 # TLS 握手要发大证书包 -> 被丢 -> 握手失败。 # # ════════════════════════════════════════════════════════════════ # 实测效果(同一台设备,各 24 次) # ════════════════════════════════════════════════════════════════ # 不夹 MSS(1500) 87% # MSS 1300 100% # MSS 1360 100% # MSS 1400 100% <- 采用(离路径上限还有余量) # MSS 1440 100% # # 15 分钟长测(180 次):见安装日志 # # ════════════════════════════════════════════════════════════════ # 注意:**不要改接口 MTU** # ════════════════════════════════════════════════════════════════ # 把 wlan0 的 MTU 降到 1400 反而掉到 50% —— # 链路本身能过 1448 的包,压小接口 MTU 是过度限制, # 包变小、来回变多,命中丢包窗口的概率反而更高。 # MSS 只限制 TCP 段,不动链路层,更精准。 set -u MSS_VALUE=${MSS_VALUE:-1400} echo " 1) 打开路径 MTU 探测" sysctl -w net.ipv4.tcp_mtu_probing=1 >/dev/null echo " tcp_mtu_probing = $(cat /proc/sys/net/ipv4/tcp_mtu_probing)" echo " 2) 夹 MSS 到 $MSS_VALUE(只限制 TCP 段,不改链路层)" for chain in OUTPUT POSTROUTING; do # 先清掉所有旧值,避免重启后越积越多 for old in 1300 1360 1400 1440; do while iptables -t mangle -C "$chain" -p tcp --tcp-flags SYN,RST SYN \ -j TCPMSS --set-mss "$old" 2>/dev/null; do iptables -t mangle -D "$chain" -p tcp --tcp-flags SYN,RST SYN \ -j TCPMSS --set-mss "$old" 2>/dev/null || break done done iptables -t mangle -A "$chain" -p tcp --tcp-flags SYN,RST SYN \ -j TCPMSS --set-mss "$MSS_VALUE" 2>/dev/null done iptables -t mangle -L -n 2>/dev/null | grep -i mss | sed 's/^/ /' echo " 3) 接口 MTU 保持 1500(实测降到 1400 反而掉到 50%)" ip link set dev wlan0 mtu 1500 2>/dev/null || true echo " wlan0 mtu = $(cat /sys/class/net/wlan0/mtu 2>/dev/null)" # ════════════════════════════════════════════════════════════════ # 4) 关键:让已经在跑的隧道重建连接 # ════════════════════════════════════════════════════════════════ # MSS 夹取只对**新建连接**生效(它改的是 SYN 包里的 MSS 选项)。 # 隧道如果是在规则生效之前建的,它那条 TCP 连接还用着旧 MSS —— # 实测:隧道 17:01 建、规则 17:22 生效,可用率一直卡在 76%; # 重启隧道之后立刻回到 100%。 # # 开机时不会走到这一步(本服务 Before=lanremote-tunnel.service, # 规则先于隧道生效);但**手动重跑本脚本**时需要重建, # 否则改了等于没改。 if systemctl is-active --quiet lanremote-tunnel 2>/dev/null; then echo " 4) 隧道正在运行,它用的是旧 MSS —— 重启让它重建连接" systemctl restart lanremote-tunnel echo " 已重启(新连接会用上 MSS=$MSS_VALUE)" else echo " 4) 隧道未运行,跳过重建(开机时本服务先于它执行)" fi echo " 网络调优已应用(MSS=$MSS_VALUE)"