写这篇文章的出发点,是为了记录我折腾校园网的一些历程。也算是学到一些东西,顺手记录一下,方便以后回忆。
顺序并不代表重要程度,只是我折腾的顺序。

一切的开始:二层校验

我们学校的校园网一开始并没有做复杂的多设备检测,只要上网的 MAC 地址和认证网页登录时的 MAC 地址相同,就可以正常上网。

这段时期是最爽的时期,只需要接一个路由器即可解决。

TTL

TTL 也就是 Time To Live,包存活时间,是网络层中的概念。 TTL 是为了防止无用包一直占用网络资源而设计的。包每经过一个路由器,TTL 都会减 1。一般设备默认 TTL 常见是 64,但由于经过自己的路由器到达校园网时就变成了 63,这也是很明显的特征了。

解决方法就是通过 OpenWrt 防火墙修改转发 TTL 为 64。这样原本经过路由器后 TTL 为 63 的数据包,都会被改回 64。

UA 信息

UA 也就是 User Agent,存在于应用层的请求头里。 通常用来确认用户的客户端信息,方便服务端返回对应的数据。比如访问网页时,手机与电脑的 UA 信息就不相同,发送不同的 UA 数据,服务端也会返回不同的数据,以适配不同的屏幕比例等等。

虽然现在的网络通信大部分都是加密通信,但还是有大量明文通信。如果 UA 信息出现在明文里,那么就很容易坐实多设备。

我能想到效率最高的解决方法就是分流。我的方法是 443 直连,443 以外的所有通信都要过一遍 UA3F,明文信息都要匹配 UA 特征,然后换成一个统一的 UA 信息。

这样也会带来一些问题。比如手机登录一些网页时比例会不正常,因为 UA 被替换成了电脑的;游戏客户端也可能登录不成功,因为客户端自己的 UA 信息也被替换了。

TCP 时间戳

很明显这是传输层的概念。TCP 时间戳一开始是为了计算 RTT 时间,以及防止序列号回绕。 RTT 指的是 Round Trip Time,也就是一次数据往返的时间。序列号回绕则是为了防止旧的数据包和新的数据包撞在一起。

每个设备的 TCP 时间戳不一样,也就导致了每个设备发出的 TCP 时间戳特征不相同,很轻易就能判断出多设备。

解决方法就是通过路由器移除 TCP 时间戳。坏处也很明显,会影响 RTT 估算和 PAWS 这类机制。下载大文件时不一定马上出错,但在高吞吐或者网络情况复杂的时候,稳定性肯定会打折扣,甚至可能出现重传、卡顿或者连接异常。

固定 TCP 初始接收窗口

这也是传输层的概念。 这个我不太了解,大概指的是在 TCP 三次握手建立连接的阶段,接收端会在第一个数据包,也就是 SYN-ACK 或 SYN 包里,通知对方“我的接收缓冲区目前最多能同时容纳多少字节的数据”。

意思大概是,不同设备握手包里的 TCP 初始接收窗口信息也不相同,所以它也会变成一个多设备特征。

一样可以通过 OpenWrt 防火墙更改,不过是有代价的。这个参数是直接影响网速的参数之一,改得不合适,网络体验会明显变差。

IPID

很明显是网络层的概念。 当数据超过 MTU 时,就会将数据分片,以满足链路上的 MTU 限制。每个被分片的数据包都会用 IPID 来区分。MTU 指的是 Maximum Transmission Unit,也就是最大传输单元。

由于不同系统的 IPID 生成方式不一样,所以这里的 IPID 也会成为多设备的特征。

一样可以通过 OpenWrt 防火墙固定 IPID 来解决。但是如果把所有数据包的 IPID 强行固定为 0 或者某个固定常数,一旦网络中真的发生了 IP 分片,例如经过某些特殊链路时 MTU 变小了,接收端收到一堆 IPID 都是 0 的不同数据碎片,就可能把它们错误地拼接在一起,导致下载文件损坏。

DPI

Deep Packet Inspection,也就是深度包检测。据我所知,我们学校好像确实有这么一台设备。之前是可以查看的,之后学生网段访问这个 IP 都会被重定向。

DPI 会通过分析数据包来判断多设备特征。举一个例子,一个看起来像 Windows 设备的网络特征背后,却出现了微信手机端的长连接,这就很可疑。

DNS 也会影响判断。 大部分 DNS 都是跑在明文 53 端口上的,如果之后再升级,可以试试 TCP 分片乱序和 TCP 混合注入。简单来说,就是将 TCP 数据包分片,并且错开顺序发送。如果 DPI 设备想查看数据包信息,就需要将数据包放入缓存,再拼接为正常顺序。在高吞吐的场景下,这对性能影响很大。

不过这也只是增加 DPI 判断难度,未必奏效,而且对自己的网络性能也是有损耗的。DPI 真要发力,几乎是无解的。我的解决方法是局域网内的设备都尽量表现得像电脑,UA 修改的也都是电脑的,一定程度上可以解决这个问题。