斐讯N1 – 利用iptables+ipset实现网关自动代理
请先阅读《斐讯N1 – 利用redsocks+ss实现全局翻墙》。
此前,利用iptables将所有发往外网的TCP流量全部改写到了redsocks上,导致国内的网站访问也会绕路海外,这样的体验极差。
因此,本文要做的就是进一步配置iptables,为其配置国内IP网段的白名单,一旦发现是国内IP则不拦截而是直接转发。
配置过程
如果我们知道中国的所有IP网段,那么直接iptables逐条添加规则即可,但是这存在一个问题:效率!
中国的IP网段非常多,都添加到iptables中之后,网络包就会非常低效的逐个遍历判断,时间复杂度为O(n),性能不太好。
iptables提供了很多可插拔的扩展模块,解决这个需求性能问题的模块就叫做ipset,它利用哈希表数据结构高效的在内存中维护所有网段,实现O(1)的查询效率。
接下来,我们利用ipset模块创建一个IP集合,我们把国内IP网段全部录入到这个集合,然后在iptables中借助ipset集合对目标IP进行识别并跳过改写即可。
安装ipset:
1 |
apt install ipset |
创建china网段的集合:
1 |
ipset create china hash:net |
china是集合的自定义名字,后面的hash:net写法是固定的,其表示利用哈希表结构保存网段信息。
那么中国的IP网段有哪些呢?有一个网站提供了一份清单:
1 |
wget http://www.ipdeny.com/ipblocks/data/countries/cn.zone |
里面的内容是这样的一些IP段:
1 2 3 4 5 6 |
223.208.0.0/14 223.212.0.0/15 223.214.0.0/15 223.220.0.0/15 223.223.176.0/20 223.223.192.0/20 |
我们可以循环把它们添加到china集合里:
1 |
for i in $(cat cn.zone); do echo $i; ipset add china $i; done |
在原先的REDSOCKS链中,仅仅对一些内网IP段做了透传:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
root@aml:~# iptables -t nat -nvL --line-number Chain REDSOCKS (2 references) num pkts bytes target prot opt in out source destination 1 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/8 2 0 0 RETURN all -- * * 0.0.0.0/0 10.0.0.0/8 3 0 0 RETURN all -- * * 0.0.0.0/0 100.64.0.0/10 4 174 10440 RETURN all -- * * 0.0.0.0/0 127.0.0.0/8 5 0 0 RETURN all -- * * 0.0.0.0/0 169.254.0.0/16 6 0 0 RETURN all -- * * 0.0.0.0/0 172.16.0.0/12 7 941 58031 RETURN all -- * * 0.0.0.0/0 192.168.0.0/16 8 0 0 RETURN all -- * * 0.0.0.0/0 198.18.0.0/15 9 0 0 RETURN all -- * * 0.0.0.0/0 224.0.0.0/4 10 0 0 RETURN all -- * * 0.0.0.0/0 240.0.0.0/4 11 1022 61620 RETURN all -- * * 0.0.0.0/0 45.77.69.50 12 177 10737 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 12345 |
现在,我们将使用ipset模块识别目标IP网段属于china的,同样做RETURN跳过改写,直接透传:
1 |
root@aml:~# iptables -t nat -I REDSOCKS 11 -m set --match-set china dst -j RETURN |
上述命令在NAT表的REDSOCKS链的11号位置,应用set模块,指定目标地址匹配china集合,如果命令则RETURN跳过后续规则。
再次查看REDSOCKS链:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Chain REDSOCKS (2 references) num pkts bytes target prot opt in out source destination 1 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/8 2 0 0 RETURN all -- * * 0.0.0.0/0 10.0.0.0/8 3 0 0 RETURN all -- * * 0.0.0.0/0 100.64.0.0/10 4 174 10440 RETURN all -- * * 0.0.0.0/0 127.0.0.0/8 5 0 0 RETURN all -- * * 0.0.0.0/0 169.254.0.0/16 6 0 0 RETURN all -- * * 0.0.0.0/0 172.16.0.0/12 7 944 58223 RETURN all -- * * 0.0.0.0/0 192.168.0.0/16 8 0 0 RETURN all -- * * 0.0.0.0/0 198.18.0.0/15 9 0 0 RETURN all -- * * 0.0.0.0/0 224.0.0.0/4 10 0 0 RETURN all -- * * 0.0.0.0/0 240.0.0.0/4 11 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 match-set china dst 12 1025 61800 RETURN all -- * * 0.0.0.0/0 45.77.69.50 13 177 10737 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 12345 |
已经生效。
验证效果
现在请求baidu.com:
1 |
curl baidu.com |
查看REDSOCKS链的ipset规则已经有流量统计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
root@aml:~# iptables -t nat -nvL --line-number Chain REDSOCKS (2 references) num pkts bytes target prot opt in out source destination 1 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/8 2 0 0 RETURN all -- * * 0.0.0.0/0 10.0.0.0/8 3 0 0 RETURN all -- * * 0.0.0.0/0 100.64.0.0/10 4 184 11024 RETURN all -- * * 0.0.0.0/0 127.0.0.0/8 5 0 0 RETURN all -- * * 0.0.0.0/0 169.254.0.0/16 6 0 0 RETURN all -- * * 0.0.0.0/0 172.16.0.0/12 7 951 58623 RETURN all -- * * 0.0.0.0/0 192.168.0.0/16 8 0 0 RETURN all -- * * 0.0.0.0/0 198.18.0.0/15 9 0 0 RETURN all -- * * 0.0.0.0/0 224.0.0.0/4 10 0 0 RETURN all -- * * 0.0.0.0/0 240.0.0.0/4 11 11 660 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 match-set china dst 12 1036 62460 RETURN all -- * * 0.0.0.0/0 45.77.69.50 13 185 11217 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 12345 |
持久化规则
重启后iptables规则和ipset都会清空,所以需要持久化。
前提是大家已经安装过工具:apt install iptables-persistent,默认该工具只会自动保存与加载iptables规则,但是它支持插件扩展保存ipset规则。
首先下载ipset插件:https://github.com/freeyoung/netfilter-persistent-plugin-ipset,然后把10-ipset脚本mv到/usr/share/netfilter-persistent/plugins.d目录,最后chmod a+x 10-ipset。
接下来只需要正常的保存规则即可:
1 2 3 4 |
root@aml:~# netfilter-persistent save run-parts: executing /usr/share/netfilter-persistent/plugins.d/10-ipset save run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save |
我重启验证了ipset规则可以顺利加载进来。
其他
因为DNS的upstream是8.8.8.8,该IP不属于china,所以会走翻墙到海外解析。
类似baidu.com这些国内网站都提供了境外IP,所以在境外解析域名极大可能得到境外的IP入口,所以会导致接下来的TCP连接再次走翻墙出去,这个问题唯有通过在自建DNS中实现域名白名单来实现了。
如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~
