斐讯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:

创建china网段的集合:

china是集合的自定义名字,后面的hash:net写法是固定的,其表示利用哈希表结构保存网段信息。

那么中国的IP网段有哪些呢?有一个网站提供了一份清单:

里面的内容是这样的一些IP段:

我们可以循环把它们添加到china集合里:

在原先的REDSOCKS链中,仅仅对一些内网IP段做了透传:

现在,我们将使用ipset模块识别目标IP网段属于china的,同样做RETURN跳过改写,直接透传:

上述命令在NAT表的REDSOCKS链的11号位置,应用set模块,指定目标地址匹配china集合,如果命令则RETURN跳过后续规则。

再次查看REDSOCKS链:

已经生效。

验证效果

现在请求baidu.com:

查看REDSOCKS链的ipset规则已经有流量统计:

持久化规则

重启后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。

接下来只需要正常的保存规则即可:

我重启验证了ipset规则可以顺利加载进来。

其他

因为DNS的upstream是8.8.8.8,该IP不属于china,所以会走翻墙到海外解析。

类似baidu.com这些国内网站都提供了境外IP,所以在境外解析域名极大可能得到境外的IP入口,所以会导致接下来的TCP连接再次走翻墙出去,这个问题唯有通过在自建DNS中实现域名白名单来实现了。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~