Files
ykxmz/_build/longstab_dual.sh
T
xmz7891 d4f335b8f9 管理页新增:允许/禁止新设备接入 + 修改设备配对码
== 功能一:允许新设备接入开关 ==

关掉之后只有已经登记过的电脑能继续上线,没见过的新设备一律拒绝。
状态存在 relay_state.json 里,重启不丢。

判断新设备用的是 deviceId,不是配对码 ——
这一点很关键:管理员给老设备改过码之后,
那台设备必须仍然能进来;按码判断的话它会被自己的开关挡在外面。
测试里专门有一条 A3b 守这个行为。

被拒时回 blocked=True,让客户端能区分被管理员挡了
和配对码冲突,而不是去匹配中文错误文案(文案一改就坏)。

== 功能二:修改任意设备的配对码 ==

管理页每台设备一个「改码」按钮,填 6 位数字即生效。
要点:
  * 新旧码冲突检查
  * 旧码映射必须删掉,否则变成孤儿条目,
    管理页配对码占用的数字会虚高
  * 改码踢掉该设备当前会话(会话绑在码上)
  * 立刻持久化

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

1. 改码功能一上线就 500:Session 用了 __slots__,
   根本没有 session_id 属性(会话是以 token 为 key 存在 dict 里的),
   写 s.session_id 直接 AttributeError。
   改成遍历 sessions.items() 拿 key。

2. snapshot() 里有同样的错(清理超时设备那段):
   平时 stale 列表是空的所以从没炸过,一旦真有设备超过 6 小时
   没上报就会 500。这次一起修了。

== 管理页 UI ==
  * 设备小节加了「允许新设备接入」勾选框
  * 每行加「改码」按钮(走 prompt,不引入弹窗层)
  * 改码按钮用 data-recode 而不是 data-device ——
    现有单台删除按 button.danger[data-device] 绑,
    带上 data-device 会被当成删除按钮,点改码变删设备。
    测试 C6 专门断言这一点。

== 测试 ==
新增 _tests/test_admin_device_control.py(23 项),
已注册进 _tests/verify_all.ps1 第 3e 阶段。
2026-10-07 17:01:14 +08:00

92 lines
3.7 KiB
Bash

#!/bin/bash
# 双协议隧道的长时稳定性测量。
#
# 和之前的 longstab.sh 区别:现在有**两个** cloudflared 实例,
# 只有先起的那个能绑上 20241 metrics 端口,所以不能只看 metrics
# 的连接数 —— 要分别从两个日志里数"当前活跃连接"。
#
# 每轮记录:
# * QUIC 实例 / HTTP2 实例 各自最近注册的连接数
# * 公网可用率
# * 掉线、dial 失败、530/502 事件
set -u
BASE=https://relay.xxmxxs.top
UA='LanRemote/1.8.2'
MINUTES=${1:-30}
LABEL=${2:-dual}
ROUNDS=$((MINUTES * 6))
OUT=/root/longstab_${LABEL}.txt
MARK_Q=$(wc -l < /root/lanremote-relay/tunnel.log 2>/dev/null || echo 0)
MARK_H=$(wc -l < /root/lanremote-relay/tunnel-h2.log 2>/dev/null || echo 0)
echo "════════ 双协议隧道长测 · $LABEL · ${MINUTES} 分钟 ════════" | tee "$OUT"
echo " QUIC: $(grep -oE '\-\-protocol [a-z0-9]+|--ha-connections [0-9]+' /etc/systemd/system/lanremote-tunnel.service | tr '\n' ' ')" | tee -a "$OUT"
echo " HTTP2: $(grep -oE '\-\-protocol [a-z0-9]+|--ha-connections [0-9]+' /etc/systemd/system/lanremote-tunnel-h2.service | tr '\n' ' ')" | tee -a "$OUT"
echo " MTU: $(cat /sys/class/net/wlan0/mtu)" | tee -a "$OUT"
echo " 开始: $(date '+%H:%M:%S')" | tee -a "$OUT"
okA=0; totA=0; timesA=()
zeroQ=0; zeroH=0; low=0
declare -a events
for r in $(seq 1 "$ROUNDS"); do
# 各自实例"最近 500 行里,注册后又没掉线"的净连接数 —— 用最近事件近似
nq=$(tail -200 /root/lanremote-relay/tunnel.log 2>/dev/null \
| grep -c 'Registered tunnel connection')
nh=$(tail -200 /root/lanremote-relay/tunnel-h2.log 2>/dev/null \
| grep -c 'Registered tunnel connection')
# 每 3 轮(30 秒)打一次公网
if [ $((r % 3)) -eq 0 ]; then
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}')
totA=$((totA + 1))
if [ "$c" = "200" ]; then
okA=$((okA + 1)); timesA+=("$ms")
else
events+=("[$(date '+%H:%M:%S')] HTTP $c")
printf " [%s] ✗ HTTP %s (Q=%s H=%s)\n" "$(date '+%H:%M:%S')" "$c" "$nq" "$nh" | tee -a "$OUT"
fi
fi
sleep 10
done
echo | tee -a "$OUT"
echo "════════ 结果 ════════" | tee -a "$OUT"
pct=$((okA * 100 / (totA > 0 ? totA : 1)))
echo " 公网可用率: $okA/$totA = ${pct}%" | tee -a "$OUT"
if [ "${#timesA[@]}" -gt 0 ]; then
printf '%s\n' "${timesA[@]}" | sort -n | awk '{
a[NR]=$1
} END {
printf " 耗时: 最小 %d 中位 %d P90 %d P99 %d 最大 %d ms\n",
a[1], a[int(NR/2)+1], a[int(NR*0.9)+1], a[int(NR*0.99)+1], a[NR]
}' | tee -a "$OUT"
fi
echo | tee -a "$OUT"
echo " QUIC 实例事件:" | tee -a "$OUT"
for kw in 'Registered tunnel connection' 'Lost connection' 'Failed to dial' 'no recent network activity'; do
c=$(tail -n +$((MARK_Q+1)) /root/lanremote-relay/tunnel.log 2>/dev/null | grep -c "$kw" || echo 0)
printf " %-34s %s 次\n" "$kw" "$c" | tee -a "$OUT"
done
echo " HTTP/2 实例事件:" | tee -a "$OUT"
for kw in 'Registered tunnel connection' 'Lost connection' 'Failed to dial' 'i/o timeout'; do
c=$(tail -n +$((MARK_H+1)) /root/lanremote-relay/tunnel-h2.log 2>/dev/null | grep -c "$kw" || echo 0)
printf " %-34s %s 次\n" "$kw" "$c" | tee -a "$OUT"
done
echo | tee -a "$OUT"
echo " HTTP 失败时刻:" | tee -a "$OUT"
if [ "${#events[@]}" -gt 0 ]; then
printf ' %s\n' "${events[@]}" | tee -a "$OUT"
else
echo " 一次都没有" | tee -a "$OUT"
fi
echo | tee -a "$OUT"
echo " 存档: $OUT" | tee -a "$OUT"