基于DNS污染、关键词阻断、IP封锁的透明防火墙的研究

那啥,标题不知为啥有几个字显示不出来,应该是:基于DNS污染过滤、关键词阻断检测、IP封锁分流的透明防火墙方案

0x00:透明防火墙 と 透明反防火墙

所谓透明,在网络术语上讲指某个网络设备对上网用户而言不可见。透明防火墙自然对用户也是透明的,因为从未有人承认透明防火墙的存在,所以在中国大陆参考系中我们看到的只是Twitter、Facebook、Youtube这些网站坏掉了。反之,透明反防火墙也是透明的,我们可以将其部署到一台路由设备中(本文以OpenWRT为例),使得连接到该路由上的设备看不到防火墙的存在,实现零配置自由访问网络。透明防火墙使用且仅使用三个技术:由封锁严重程度从浅到深分别是DNS污染、关键词阻断、IP封锁。本文将分别从这三个方面讨论相关原理与破解方案。

0x01:DNS污染 と DNS污染过滤

DNS污染的原理很简单,即查询特定网站的DNS报文通过防火墙时会被抢先返回虚假的地址,由于UDP报文的无连接特性,先到者会被采纳而后续报文会被丢弃,从而达到污染目的。在针对某一个域名或某一类的域名,返回的虚假地址是固定的几个。例如在作者的实验环境中,查询Twitter、Facebook等域名会返回59.24.3.173与37.61.54.158两个中的某一个IP地址,而查询webcache.googleusercontent.com或plus.google.com会返回另外的两组IP,说明对于不同的域名有不同的防火墙设备处理。即便针对不同域名有不同组的虚假IP列表,但总量依旧是有限的,由于目前的防火墙并不会丢弃掉正确的解析结果,所以只需在路由器上过滤掉错误的解析即可收到后续正确解析。可以利用iptables的u32模块过滤掉虚假的IP地址:

iptables -t mangle -A PREROUTING -p udp --sport 53 -m u32 --u32 "22&0xFFFF@16=0x3B1803AD,0x253D369E" -j DROP #generic
iptables -t mangle -A PREROUTING -p udp --sport 53 -m u32 --u32 "22&0xFFFF@16=0x5D2E0859,0x4E10310F,0xF3B9BB27,0x2E52AE44,0x0807C62D,0xCB620741,0x9F6A794B,0x2E52AE44" -j DROP #webcache.googleusercontent.com
iptables -t mangle -A PREROUTING -p udp --sport 53 -m u32 --u32 "22&0xFFFF@16=0x4A7D2766,0x4A7D2771,0x4A7D7F66,0x4A7D9B66,0xD155E58A" -j DROP #plus.google.com

上文脚本中的IP地址为作者自己按域名总结,读者也可以使用网络上能够找到的完整列共48个污染地址编写脚本。

0x02:IP封锁 と IP封锁分流

IP封锁是最严厉的封锁方案,即将某个地址的IP流量导向黑洞路由直接丢弃,或者在某个IP或IP段的某些端口上进行TCP SYN干扰造成不能连接。例如Twitter,以及现在的Google,完全无法连接到80与443端口。对于这种类型的阻断,只能考虑走代理,可用的方法包括工作在IP层上的VPN,或者在TCP层上的Socks5代理配合redsocks透明转发。作者使用的是Shadowsocks官方提供的透明转发ss-redir。IP分流可以使用ipset实现:

ipset create vpn nethash
ipset add vpn 74.125.0.0/16 #Google
ipset add vpn 173.194.0.0/16 #Google
ipset add vpn 199.59.148.0/22 #Twiter
iptables -t nat -A PREROUTING -p tcp -m set --match-set vpn dst -j REDIRECT --to-port 1080

0x03:关键词阻断 と 关键词阻断检测

关键词阻断指防火墙检测到HTTP请求的Host字段中有匹配的网站,或Uri中有匹配的路径或搜索字符串时向连接双方发送TCP RST包造成连接断开。关键词阻断是使用最广泛的机制,如果要完美预防,则必须检查每一个HTTP请求,例如使用Autoproxy等浏览器插件订阅GFWList关键词列表。但该列表过于庞大(近5000行),且由于字符串匹配的性能问题,部署到路由器设备中非常地不合适,而且真正的关键词列表会依据突发事件经常更新,由社区维护的GFWList并不具有真正的时效性。由于上述种种缺点,作者采用另外的方法,即检测RST包,在防火墙时限的90秒内将IP加入分流的ipset,这样可以做到连接被防火墙阻断后刷新页面即可自动通过代理正常访问。由于Safari、Chrome浏览器会在连接失败时自动重试,故使用这些浏览器的用户将不会看到首次阻断的页面,从而达到透明代理的体验。触发关键词时防火墙通常会同时发送3个以上的RST包(可能和多个设备有关),可以用来简单区分是正常的RST还是防火墙发来的RST。这个统计次数的操作在iptables中可以借助recent模块完成:

ipset create rst iphash timeout 90
iptables -t nat -A PREROUTING -p tcp -m set --match-set rst dst -j REDIRECT --to-port 1080
iptables -t mangle -A PREROUTING -p tcp --tcp-flags RST RST -m recent --name rst --rcheck --seconds 1 --hitcount 2 -j SET --add-set rst src
iptables -t mangle -A PREROUTING -p tcp --tcp-flags RST RST -m recent --name rst --set

0x04:总结

至此,防火墙对用户基本实现透明。完整的配置脚本可在190号档案找到,在OpenWRT下添加到firewall.user即可。参考文献:FreeRouter_V2项目

One thought on “基于DNS污染、关键词阻断、IP封锁的透明防火墙的研究

  1. Pingback: 一些有趣的实验(第二季) | LXF's X Factory

Leave a Reply

Your email address will not be published. Required fields are marked *

Using REAL email address will help you receive reply notifications.

Current ye@r *