重庆大学校园网多设备检测对抗实战(OpenWrt + ua3f)
声明:本文仅记录在本人自有账号、自有路由器上的网络配置实践,用于多设备共享自用,不涉及破解计费、不针对他人。文中所有账号 / 密码 / token / 公网 IP 均已打码。请遵守所在学校的网络管理规定,风险自负。
背景
重庆大学校园网认证端点迁移到了 login.cqu.edu.cn(旧的固定 IP 认证作废),同时上线了多设备共享检测:一个账号下若被识别出多台设备,会提示"检测到共享 / 请勿使用代理"并冻结一段时间。
我的方案是一台 OpenWrt 路由器做主路由:
客户端 → nftables(TPROXY拦截) → hev-socks5-tproxy → ua3f(UA改写) → 校园网 |
认证部分用了一个自己 fork 改造的 LuCI 插件(适配 login.cqu.edu.cn 的新 JSONP 协议,账号 2025********、密码均在路由器本地配置,不外泄)。本文不讲认证,只讲怎么尽量不被多设备检测,同时还能用。
一个核心认知
ua3f 是个 SOCKS5 终结点:hev-socks5-tproxy 把 TPROXY 拦下的流量交给它,它关闭客户端 TCP、用路由器自己的协议栈重新发起一条新连接。
所以——凡是进了代理的流量,对外的 L3/L4 指纹(TTL、IP-ID、TCP options/时间戳、源端口行为)统一成路由器这一台,再叠加 HTTP UA 改写,对外等效"一台主机"。
结论:检测能抓到的,只有漏出代理的流量。加固 = 让尽量多的流量进代理 + 抑制进不了代理的流量。
下面按"检测维度 → 处理"组织。环境示例:LAN 192.168.1.0/24、WAN 口 eth0.1、WAN 地址 10.244.x.x。
P0:关掉 IPv6(最关键)
TPROXY 规则只处理 IPv4(tproxy ip to)。客户端只要有全局 IPv6 地址,就绕过 NAT 和代理,每台设备的 v6 地址直接暴露,前面所有努力白费。
uci set dhcp.lan.ra_slaac='0' |
network reload会瞬断 WAN,校园门户掉线几十秒后认证守护会自动重连。
P1:拦截范围从"端口白名单"改成"几乎全部 TCP"
很多教程的 TPROXY 只拦 {80,8080,...} 几个端口。实测发现:任意端口的明文 HTTP(例如某服务跑在 :8000)会整条漏出去,真实 UA 直达服务器。
把规则改成"除 443 和 LAN 本地外的全部 TCP 都进代理"(/etc/nfts/100-tproxy.nft):
table inet tproxy_table { |
- 排除
192.168.1.0/24:不劫持本机 SSH/管理页和内网互访(防把自己锁外面,按自己 LAN 段改)。 - 排除
dport 443:HTTPS 直连,避免把 TLS 大流量全压到弱 CPU(性价比折中)。 - 不要排除
10.0.0.0/8:校园认证 / 内网就是10.x,得继续走代理改写。 - 代价:443 仍直连 → 它的 TLS 指纹(见后文残留)改不掉。
P2:统一 TTL —— 以及那个最容易踩的坑
多种客户端 OS 的初始 TTL 不同(Windows 128 / Linux·Android·iOS 64),经路由器再 -1,服务器看到一组离散 TTL 就知道你后面挂了多台不同系统。
新增 /etc/nfts/110-cqu-hardening.nft:
table inet cqu_hardening { |
小坑:nft 里 chain 不能命名为
fwd,那是保留字。
⚠️ 关键坑:不关 flow offload,TTL 改写是假的
OpenWrt 默认开 软件/硬件流量卸载(flow offloading)。被卸载的连接走 fastpath 快速转发,直接跳过 netfilter 的 postrouting hook——也就是说上面的 ip ttl set 64 对这些连接根本没执行。
实测:开着 offload 时 conntrack 里大量连接带 [OFFLOAD] 标记,那条 ttl set 规则的计数远小于真实流量;关掉后单核负载从 0.07 直接飙到 1.16(流量全部回到协议栈)。
所以必须关:
uci set firewall.@defaults[0].flow_offloading='0' |
同理
fullcone(全锥 NAT)在部分实现里也会绕 hook,介意可一并关,代价是 P2P/游戏 NAT 类型变差。
这一步是好多人"配了 TTL 还是被检测"的根因。
P3:封 QUIC
浏览器默认机会性走 HTTP/3(QUIC over UDP 443),它带类 TLS 指纹、流量大,且完全绕过 TCP 代理链路。上面 cqu_forward 里 udp dport 443 reject 一句把它打掉,浏览器会自动回落到 TCP(再被 ua3f 处理)。reject 比 drop 回落更快。
NTP:被忽略的强特征
不同设备默认 NTP 服务器、对时频率都不一样,udp/123 直连出去就是一组多设备特征。处理方式:路由器自己当 NTP server,把客户端的 123 全部重定向到本地(上面 cqu_nat 已含 redirect):
uci set system.ntp.enable_server='1' |
效果:客户端以为在和公网 NTP 对话,其实被路由器本地应答;对外只剩路由器一个 NTP client 同步上游,多设备 NTP 特征收敛成一个。
UA:伪装值本身别穿帮
ua3f 的 -f 一定要是真实存在、当前主流的 UA。我接手时它被设成了带 CoolMarket/14.2.3-...(某 App 尾巴)的串——桌面 Chrome 不可能带这种尾巴,所有设备统一成这个不存在的客户端组合,本身就是个显眼特征。换成干净的:
uci set ua3f.main.ua='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' |
自检脚本
在路由器上跑,逐项确认而不是凭感觉(节选):
NF=/proc/net/nf_conntrack |
客户端侧再配一个多 UA / 多端口探测脚本(思路同经典的 ua_test.sh:用不同 UA、不同端口请求一个回显服务,看服务器实际收到什么),就能定位还有哪一维在漏。测的时候记得关掉客户端自己的代理软件,否则流量绕过路由器,结果不可信。
诚实的残留(路由器侧改不掉)
| 维度 | 状态 |
|---|---|
| HTTPS/443 的 UA(在 TLS 里)、JA3/JA4 | 不做中间人解密就改不了;现代浏览器 JA3 已随机化弱化,JA4 仍可区分 |
| IP-ID(Windows 全局递增) | 经代理的已统一;直连转发的要彻底解决得编 kmod-rkp-ipid(重编固件) |
| TCP 时间戳 / options | 经代理的统一;直连泄露 |
| 并发连接数 / 账号行为 | 任何方案都藏不住"一个号大量并发" |
思路是:把能收敛的都收敛掉,让单一残留维度难以单独定位到"多设备"。
性能取舍
关 flow offload + 几乎全部 TCP 进 ua3f,对弱硬件(入门级单核 + 64MB 内存那种)是实打实的负担:实测关 offload 瞬间单核负载就上 1.1(≈满载),高带宽 / 多设备 / 测速会明显降速、延迟抖动、偶发卡顿,内存也吃紧。
可选:
- 接受:日常网页 / IM / 文档够用。
- 折中:P1 退回只代理少数明文 HTTP 端口,网速回升,但重新暴露非标端口明文(取舍)。
- 换硬件(双核及以上 / x86 软路由):根本解,强烈建议——弱核跑这套本就勉强。
致谢
- 认证插件 fork 自 lurenjiamax/luci-app-cquauth,协议参考 haowang02/cqu-net-auth
- UA 改写 SunBK201/UA3F,TPROXY heiher/hev-socks5-tproxy
- 检测原理参考:褐瞳《校园网防止多设备检测指北》、SunBK201《某大学校园网共享上网检测机制研究》及若干博客园文章

