#!/bin/bash # 1) 把 MTU 1400 固化下来(重启也在) # 2) 在 MTU 1400 下对照 quic+6 / quic+8 / quic+10 # # 为什么要固化 MTU: # QUIC 走 UDP,**我们那条 --set-mss 1400 的 iptables 规则只管 TCP**。 # 实测把 wlan0 MTU 从 1500 降到 1400 之后: # QUIC 建齐 6 条连接的时间 28 秒 -> 13 秒 # dial 失败次数 2 -> 1 # 原因:UDP 丢包不会回 ICMP,QUIC 发了超出路径 MTU 的包只能等超时。 # 把接口 MTU 压到 1400,QUIC 的包就都在安全范围内。 # # 为什么还要试更多连接: # 已经看到 http2+8 建齐只要 12 秒且 0 失败(QUIC+6 是 28 秒/2 次失败)。 # 连接多 = 单条掉线影响小。但 QUIC 的连接建立更贵,得实测平衡点。 set -u BASE=https://relay.xxmxxs.top UA='LanRemote/1.8.2' SVC=/etc/systemd/system/lanremote-tunnel.service NETTUNE=/etc/systemd/system/lanremote-nettune.service BACKUP=/root/tunnel.bak.v4.$(date +%s) cp -a "$SVC" "$BACKUP" N=60 MTU=1400 MSS=1360 echo "════════ 1. 固化 MTU(写进 net-tune 服务)════════" echo " 现在的 net-tune 服务:" systemctl cat lanremote-nettune 2>/dev/null | grep -E 'ExecStart' | sed 's/^/ /' # 把 MTU 设置追加进去(幂等:已有的先删掉) cp -a "$NETTUNE" "${NETTUNE}.bak.$(date +%s)" 2>/dev/null || true python3 - <<'PYEOF' from pathlib import Path p = Path("/etc/systemd/system/lanremote-nettune.service") if not p.is_file(): print(" ! net-tune 服务不存在,跳过") raise SystemExit(0) text = p.read_text(encoding="utf-8") # 去掉旧的 MTU/MSS 行 lines = [l for l in text.splitlines() if "ip link set wlan0 mtu" not in l and "--set-mss" not in l] out = [] for line in lines: out.append(line) # 在每个 ExecStart 之后补上 MTU 设置 if line.strip().startswith("ExecStart="): out.append("ExecStart=/sbin/ip link set wlan0 mtu 1400") out.append("ExecStart=/sbin/iptables -t mangle -C OUTPUT -p tcp " "--tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360 || " "/sbin/iptables -t mangle -A OUTPUT -p tcp " "--tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360") p.write_text("\n".join(out) + "\n", encoding="utf-8") print(" 已写入 MTU 1400 + MSS 1360") PYEOF systemctl daemon-reload echo " 立即执行一次:" ip link set wlan0 mtu $MTU && echo " wlan0 MTU -> $(cat /sys/class/net/wlan0/mtu)" iptables -t mangle -C OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS 2>/dev/null \ || iptables -t mangle -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS echo " MSS 规则: $(iptables -t mangle -S OUTPUT | grep TCPMSS | head -1)" echo " net-tune 现在的内容:" systemctl cat lanremote-nettune 2>/dev/null | grep ExecStart | sed 's/^/ /' echo " 服务状态: $(systemctl is-enabled lanremote-nettune 2>/dev/null) / $(systemctl is-active lanremote-nettune 2>/dev/null)" wait_conns() { local want="$1" limit="$2" t0 t1 n t0=$(date +%s) while true; do n=$(curl -s --max-time 4 http://127.0.0.1:20241/metrics 2>/dev/null \ | grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}') n=${n:-0} t1=$(date +%s) [ "$n" -ge "$want" ] || [ $((t1 - t0)) -ge "$limit" ] && { echo "$n $((t1 - t0))"; return; } sleep 3 done } run_group() { local conns="$1" echo "════════ quic + $conns (MTU $MTU)════════" cp -a "$BACKUP" "$SVC" sed -i "s/--protocol [a-z0-9]*/--protocol quic/" "$SVC" sed -i "s/--ha-connections [0-9]*/--ha-connections $conns/" "$SVC" systemctl daemon-reload local mark; mark=$(wc -l < /root/lanremote-relay/tunnel.log 2>/dev/null || echo 0) systemctl restart lanremote-tunnel local res; res=$(wait_conns "$conns" 150) local n s n=$(echo "$res" | awk '{print $1}'); s=$(echo "$res" | awk '{print $2}') local df; df=$(tail -n +$((mark+1)) /root/lanremote-relay/tunnel.log 2>/dev/null | grep -c 'Failed to dial' || echo 0) echo " 建齐 $n/$conns,用 ${s} 秒,dial 失败 ${df} 次" local ok=0 times=() for i in $(seq 1 "$N"); do out=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 25 -H "User-Agent: $UA" "$BASE/v1/health") c=$(echo "$out" | awk '{print $1}'); ms=$(echo "$out" | awk '{printf "%d", $2*1000}') [ "$c" = "200" ] && { ok=$((ok+1)); times+=("$ms"); } done local pct=$((ok * 100 / N)) local stats="无数据" [ "${#times[@]}" -gt 0 ] && stats=$(printf '%s\n' "${times[@]}" | sort -n | awk '{a[NR]=$1} END { printf "中位 %d P90 %d P99 %d 最大 %d", a[int(NR/2)+1], a[int(NR*0.9)+1], a[int(NR*0.99)+1], a[NR]}') printf " 可用率 %d%% (%d/%d) %s ms\n" "$pct" "$ok" "$N" "$stats" echo "quic+$conns|$n|$s|$df|$pct|$stats" >> /tmp/v4.txt echo } rm -f /tmp/v4.txt run_group 6 run_group 8 run_group 10 echo "════════ 汇总 ════════" printf " %-10s %-14s %-10s %-8s %s\n" "配置" "建齐/耗时" "dial失败" "可用率" "延迟" while IFS='|' read -r label n s df pct stats; do printf " %-10s %-14s %-10s %-8s %s\n" "$label" "${n}条 ${s}s" "$df" "${pct}%" "$stats" done < /tmp/v4.txt echo BESTN=$(sort -t'|' -k5 -rn /tmp/v4.txt | head -1 | sed 's/quic+//' | cut -d'|' -f1) echo " → 采用 quic + $BESTN" cp -a "$BACKUP" "$SVC" sed -i "s/--protocol [a-z0-9]*/--protocol quic/" "$SVC" sed -i "s/--ha-connections [0-9]*/--ha-connections $BESTN/" "$SVC" systemctl daemon-reload systemctl restart lanremote-tunnel sleep 5 echo " 最终参数: $(grep -oE '\-\-protocol [a-z0-9]+|--ha-connections [0-9]+' "$SVC" | tr '\n' ' ')" echo " MTU: $(cat /sys/class/net/wlan0/mtu)" echo " 备份: $BACKUP"