返回首页

再战运营商缓存之 使用 iptables 对付死 X 缓存劫持

起因

与移动的缓存问题进行斗争要追溯到两年前,那时候因为移动竟然连 cnpm 的数据都进行缓存。并且令人喷饭的是:移动的缓存服务器不但经常速度慢到堪比万年王八跑马拉松,甚至还经常宕机,导致我只想安安静静的写个代码却不得不面对一片鲜红的报错:

1.jpg

就此事我也不止一次的投诉到移动的客服部门并且要求至少将我这个宽带的账号加到所谓“白名单”中。当时还写过有理有据的投诉邮件:

2.png

但是不知道是福建移动的客服和技术部门是临时工还是其他什么原因,在承诺会解决问题后也一直没有改善。不得已,只能暂时用比较蠢的办法去解决这个问题:使用路由器上的 iptables 判断数据包的内容,如果数据包内包含已知的移动缓存服务器地址(范围)就丢弃这个包:

iptables -I FORWARD -m string --string "Location: http://211.143.146." --algo bm -j DROP

这个方法有效,但是移动的缓存服务器是无穷无尽的,每次都去添加规则真的让人头大。而且这样进行文本的对比太占用资源可能会造成网速下降。后来不得已换了其他运营商的宽带,也就慢慢忘了这茬。

但是最近因为搬家后重新用上了移动的宽带(无奈之举,小区只有移动的口),又要开始面对移动无穷无尽的缓存黑洞:下载些东西总会被移动友好的劫持,并且慷慨的用小水管般的下载速度回馈广大新老用户。

3.png

4.png

无奈之下只能重新想办法对付令人作藕的移动缓存。

分析劫持过程

重新打开许久没用的 Wireshark,选定一个确定会被劫持到缓存服务器的地址,抓包分析一下劫持的经过:

5.png

可以看到我们对源站发起 GET 请求之后,源站返回了一个 302 跳转的包。显然这个 302 跳转包是移动伪造的劫持包。那应该就这个劫持包来分析一下特征并将其丢弃应该就可以对移动的缓存说 886 了。

分析了几个移动返回的 302 劫持包后,发现一个特征:这些包的 TTL 都比较小,范围是 20-30 之间。正常的服务器给的包应该没这么低(吧)。

6.png

7.png

解决

继续使用路由器的 iptables,根据这个特征,写一个 iptables 规则来丢弃这些劫持包:

iptables -I FORWARD -p tcp -m tcp -m ttl --ttl-gt 20 -m ttl --ttl-lt 30 -j DROP

这样是不是就完美了呢!不,考虑到可能还真的有其他幺蛾子服务器发来的真实数据包的 TTL 也在 20-30 的区间范围内,应该再加一层判断。对比了移动的 302 劫持包和正常的 302 跳转包的报文后,发现移动的劫持包的状态位包含 FIN, PSH, ACK 而正常的 302 跳转包一般不会这三个都有:

移动的劫持包 ↓
8.png

正常的 302 包 ↓
9.png

(同时可以看到正常 302 包的 TTL 都没这么低)

那么就在 iptables 规则里加上状态位是否包含 FIN, PSH, ACK 的判断:

iptables -I FORWARD -p tcp -m tcp -m ttl --ttl-gt 20 -m ttl --ttl-lt 30 --tcp-flags ALL FIN,PSH,ACK -j DROP

这样应该就能在丢弃移动劫持包的同时尽可能减少误伤正常数据包的可能。

测试一下

访问一下刚才确定会被劫持的地址:

A.png

Bravo! 看起来移动的劫持包已经被路由器的 iptables 丢弃了,所以可以下载源站的内容了。

总结

这个方法不一定对所有地区的运营商劫持都有效果,主要还是靠分析一下运营商劫持包的特征加以判断再写成 iptables 规则进行丢弃,有需要的同学可以自己试一下。