不管你是遇到加小尾巴跳转,iframe 嵌套广告,302 跳转,还是 JavaScript 脚本劫持.
只要是基于旁路设备监听抢答数据包这个原理的劫持行为.
这套 iptables 规则就能应对.
注意:目前仍在实验阶段,浙江移动测试有效,无法保证不会对正常的连接产生破坏.
主要原理:基于 IP 头 TTL 值的判断丢包.并使用 ACK 空应答包,和装满数据的 TCP 包来更新 TTL,防止正常 TTL 变动导致连接断开.
需要模块
bpfu32connmarkmark注意
connmark的标志位需要 0x7FF 长度来记录 MSS 值,还有 0xFF 来记录 TTL 值.默认记录位置为 0x07FF00FF.mark的标志位需要 0x1 长度.默认记录位置为 0x00000001.工作原理
SYN+ACK包的 TTL 值和 MSS 协商值.ACK|ACK&&PSH,且 TCP Data 长度为 0 或长度为 MSS 协商值的包对保存的 TTL 值更新.|  |      1nfroot      2017-01-23 00:10:48 +08:00 之前看劫持包的 TTL 都不对的时候 就在想这个问题了 只是对这个太不了解…… 自己技能也达不到这个级别…… 点赞 | 
|      2RobertYang      2017-01-23 00:22:23 +08:00 via Android 点赞,被电信插广告他们还不认 | 
|  |      3lslqtz      2017-01-23 05:00:57 +08:00 如果旁路设备知道客户端与它的 TTL ,那么旁路设备再检测服务器 TTL 加起来的话。 | 
|  |      4est      2017-01-23 09:24:27 +08:00 crazy idea 。。。居然能在 iptables 做这么多事。。。学习了。 | 
|  |      5est      2017-01-23 09:27:30 +08:00 结合  ip netns 可以只对浏览器生效。这样可以限制误伤范围。 | 
|      6TMily      2017-01-23 10:30:04 +08:00 额 能不能将特定 WAN 口改为特定防火墙区域呢,多拨的话,都不一定是哪个口拨上的说 | 
|  |      7KCheshireCat OP | 
|  |      8KCheshireCat OP | 
|  |      9est      2017-01-23 11:27:03 +08:00 @KCheshireCat 能不能用 bytecode 实现服务器主动发一条 TTL 到达不了客户端的 ACK,PSH 但是墙能收到。。。然后 seq 号是不是就混乱了呢? | 
|  |      10est      2017-01-23 11:28:09 +08:00 @KCheshireCat 你们二次元头像党又是玩技术的太可怕了。 | 
|      11aru      2017-01-23 13:45:52 +08:00 1.  能否限制只对 tcp port 80 起作用(也许能降低 cpu 占用率?) 2. openwrt 下有没有朋友来搞搞? | 
|  |      12feng32      2017-01-23 20:04:07 +08:00 好东西,等晚上回去在 openwrt 上测试一下,依赖的模块是否都现成的看一下 | 
|  |      13KCheshireCat OP @est iptables 本职工作是防火墙啊,要发包大概要打补丁实现了吧,这方面我不太懂 | 
|  |      14KCheshireCat OP @aru 我用 x86 的 AMD 速龙 x4 老爷机跑满 100M 是一点问题也没有,几乎没有负载,轻轻松. 路由器的嵌入式平台就不知道了,只对 80 起效是可以做到的,但是上网主要流量也就是 80 的多啊... | 
|      15aru      2017-01-23 23:19:20 +08:00 @KCheshireCat  p2p 下载基本都是非 80 的,而且流量很大。我的大流量应用就是 PT ,经常达到 200Mbps ,估计加上这个会是一个瓶颈。 今天尝试在 lede ( openwrt fork )上添加项目的 iptables ,找不到 bpf 模块 :( | 
|  |      16KCheshireCat OP @aru  你需要针对端口限制的话可以在要填"{your WAN}"的那两行加入端口匹配条件. 然后一般来说容易缺失的 iptables 模块就是 u32 或者 bpf 了,大多数人只是用 iptables 解决些简单的需求,所以不会用到这种需要写字节码的模块. 不过可以自己编译 openwrt 固件的时候把这几个模块一起编译进去,再或者你可以看看 openwrt 官方源有没有提供补全 iptables 的包,这样就不用自己编译了. | 
|      17aru      2017-01-24 00:03:18 +08:00 @KCheshireCat  u32 我编译和加载了, bpf 实在没找到配置选项,网上找了挺多地方,没发现究竟是哪个配置参数 | 
|      18JJaicmkmy      2017-01-25 20:57:22 +08:00 @KCheshireCat 如果是自己的服务器的话,可以在服务器上也 DROP 掉 RST 的包,对 SS 有奇效。 | 
|  |      19KCheshireCat OP @JJaicmkmy #18  这么弄的话好像会触发路由黑洞,以前看别人提过。 | 
|  |      20Siril      2017-02-06 14:34:52 +08:00 awesome idea , but.....  看 issue ,疑似有误伤,求解惑。 不知可否在其他发行版复现这个问题 | 
|  |      21KCheshireCat OP  1 | 
|  |      22Siril      2017-02-06 15:42:17 +08:00 @KCheshireCat    但愿能找到改进措施。 ---------- 下面是脑洞: 仔细考虑后,即使利用 libnetfilter_queue 做出一个,抛开稳定性、吞吐量不谈, 我感觉按延迟也不靠谱, ack 的时间受目标服务器负载的影响,不能说明问题; 主动学习数据包长度、 ttl 值 也难免误伤, 恐怕还要解析数据包内容 一般也就是内容有固定特征的 302 redirect 、 meta-refresh 、 javascript 啥的。 字符串黑名单过滤之。 思路有了,项目起名叫 WFG 不错。 XD | 
|  |      23KCheshireCat OP @Siril #22  最早最早的时候我也是用 string 模块过滤字段的,但这么作通用性太差,自己用还不错,写作项目的话以后维护起来会变成又臭又长的规则表,而且对单个用户来说有用的可能就其中的几个。某条规则什么的时候已经失效也没法验证。 最重要的是运营商改劫持模板方便,我们验证规则,抓包困难。这样十分吃力。 | 
|  |      24Siril      2017-02-06 16:30:23 +08:00 | 
|  |      25Siril      2017-02-06 16:38:31 +08:00 啊不能改自己的回复,  突然想到如果 libnetfilter 可行, 何必玩高级花样。 既然真正的 response 在假的之后到达,那么假数据包太容易辨认了。 甚至可否将服务端返回的数据包缓存个多少毫秒超时,如果后续没有就发送这个,后续有“重复”的则 DROP 掉前一个。 --------- 可能 proxy server 更适合实现这样的功能。 | 
|  |      26akw2312      2017-02-19 03:06:25 +08:00 手邊的四川移動機器 測試有效 不過... 如果劫持是那種整個 TCP 都劫持走的目測也沒辦法了吧.. tcp traceroute 一看都被劫持走的那種 (icmp 正常, tcp 非 80 443 8080 也正常) |