关于校园网HTTP劫持的分析

接上文 https://i-meto.com/shit-scutweb/

最近发现不少应用的联网异常,尤其是网易云音乐的播放时常请求失败,怀疑是垃圾校园网搞的鬼,于是做了一些分析。

通过抓包不难发现有不少类似 http://202.38.196.91/cache/5/05/music.126.net/9733b9************fa0d36a82/653**********bb10ec.mp3 的请求。通过查询 IP 发现这台服务器位于校内,开放了 80 端口,初步判断是一台缓存服务器。

使用 wireshark 进行抓包,得到更详细的请求过程

webp

  • 18,19,20: TCP 三次握手
  • 21: GET 请求下载 QQ 安装包
  • 22: (抢答)302 跳转,同时关闭连接 [FIN]
  • 27: 真正的应答包,[Out-Of-Order]

可以看出这是经典的单向中断访问型劫持,其原理就是通过旁路设备监听数据包,一旦发现特征(如存在相应缓存)就伪造服务器向用户发送 RST 阻止后续 TCP 连接(很像 DNS 污染的原理

network

既然只是抢答包,那么直接在路由器上丢弃就可以了。一种最简单的方式就是通过匹配字符串丢弃,详情见前文。由于效率问题,本文介绍一种基于 TTL/ID 的拦截手段。

劫持包
webp

正常应答包
webp

根据 RFC 的规定,identification 应该是公差为 1 的单调递增数列,TTL 则是每经过一个路由递减。而上图中劫持包的 RST 与握手时不一致,并且 ID 永远都是 0x0080,这是不正常的。

  • 更新:经大牛提醒,这套系统在 ISP 中非常常见,返回的 302 数据包带有 [FIN, PSH, ACK], 而正常的 302 数据包是不会同时带有上面标志位的。

抓到特征后,可以编写规则进行拦截,这里介绍 iptables 的 u32 匹配模式。

u32 允许你从数据包中提取 4 个字节,然后通过指定的掩码,偏移一定数量的单位到某个位置然后比对这个数值是否为某个值或者是否在某个区间中。(man iptables)

u32 的语法其实很简单 iptables -m u32 --u32 "Start&Mask=Range"

  • start: 表示开始取值的位置 / 字节
  • Mask: 表示掩码
  • Range: 表示匹配的范围,可以是一个使用 : 分割开的区间,也可以只是一个数

为了示范,这里贴出劫持包的 IP 报文

0000  45 00 00 e3 00 80 00 00  3a 06 c5 28 70 5a 87 eb
0010  c0 a8 01 7f                                     

TCP 报文

0000  00 50 d7 14 93 f0 17 72  fd 04 3b 71 50 19 39 08
0010  3a 5c 00 00                                     

我们关心的位置是 identification(0x0080), TTL(0x3A), Flag(5019), 也就是 IP 报文中的第 05, 08 位置,TCP 报文的第 10 位置。

对应 u32 规则就是 2&0xFFFF=0x0080, 5&0xFF=0x3A, 0>>22&0x3C@10&25=25.

参考 iptables 文档可以编写出如下规则

iptables -I FORWARD -p tcp --sport 80 -m u32 --u32 "0>>22&0x3C@10&25=25 && 2&0xFFFF=0x0080 && 5&0xFF=0x3A" -j DROP

以上三个规则可以根据需要自行组合,然后配置到路由器上(需要安装 iptables-mod-u32 模块)重启防火墙生效。和之前 string 的方案对比测试,u32 几乎感受不到效率的影响。

参考资料

胡思乱想

如果能把抢答包加个延迟转发就好了,还不用担心误拦截 XD
每次投诉完都要喝点酒,气!


本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可
本文链接:https://i-meto.com/scut-hijack-internet-traffic/