一、背景介绍

lean的openwrt固件已经颇具盛名,就不过多介绍了。它本地化做得非常好,集成并且默认配置好了很多实用功能,而这些功能在其他固件中往往都需要一个一个找到并手动配置。再加上其开源代码,根据自己的需求往不同路由器里添加适宜的功能就非常方便了(至少不用重复造轮子去集成这么多功能并且解决了冲突)。

但是,正因为它整合了很多功能,而且解决功能之间的潜在冲突,所以如果要调整其内部核心集成的功能模块,就会出现牵一发而动全身的情况。。。

比如我这次,要修改dnsmasq的上游dns,折腾了一个下午发现完全不生效,甚至路由器原本自己的dns解析直接就挂掉了。。。。

二、lean固件的PAC配置详解

PAC(Proxy auto-config)代理自动配置是一种网页浏览器技术,用于定义浏览器该如何自动选择适当的代理服务器来访问一个网址。 浏览器执行pac文件包含的类似JavaScript的函数,实现访问不同网站使用不同的代理规则。但是我们要在路由器层面实现PAC就有很多难题了,首先路由器工作在网络层及以下,很难知道这个连接访问的服务是什么(HTTPS请求如果打开SNI扩展甚至连域名都拿不到),其次维护策略路由的ipset是一件很费力的事情,甚至一个超大的ipset会拖垮路由器转发性能尤其是是对于mt7621这种,不开硬件nat跑满千兆都要吃大半CPU的乐色。

要做到路由器侧PAC并实现透明代理(或者说策略路由),也不是不可以,但是得换一种思路,因为不能像在浏览器里直接根据请求判断,那就从路由器侧能获取到得内容下手:DNS解析、ip-filter。首先下发dns服务器地址为路由器本身(或者拦截用户侧dns),dns请求里必然附带了域名,得到域名和对应的IP,后续前往此ip的连接变可以认为跟该域名相关,那么便能按照PAC中的规则进行匹配了。同时,用户的连接经过路由器时,根据上述的规则(针对ip)进行匹配,除去直接放行的比如内网地址或者用户设置的,其他连接全部转发(redirect)到路由器的ss-redir服务上。ss-redir根据请求的ip,前面得到的ip域名关系,结合PAC规则进行判断是否走代理,就成功啦。

可见DNS在互联网访问中是核心的一环,访问主机需要解析域名,请求对应的服务也需要域名解析的支持。比如的KMS激活服务, 主机映射,广告屏蔽, 容器服务发现,内网服务直通,网络加速,流量负载均衡等,都依赖于路由器本地的DNS域名解析服务。

lean的openwrt通过dnsmasq这样一个常规的DNS/DHCP服务,就在小小的路由器里实现上述功能,可谓之精巧。

通常来说,KMS服务、主机映射只需要配置dnsmasq就行了,没什么问题。 容器服务发现,内网服务直通 则是需要修改本地dns解析,也就是hosts文件实现,这个也没啥。广告屏蔽的话就是维护一系列的域名名单,禁止解析有关广告的域名即可。而最后的网络加速和流量负载均衡就比较复杂了,一方面要拿到正确的解析结果也就是IP地址,另一方还要根据IP地址启用不同的路由策略,策略路由是通过IPTABLES和$$R客户端实现的,其本身就带按规则匹配功能,并且能动态更新规则,性能也还不错,这也是为何偏爱用lean集成的功能的原因了。

关于kms服务和自定义解析内容,这两个属于dnsmasq的基础功能,网上一大堆教程,改改/etc/dnsmasq.conf就行,就不细说了。不过,有一点很坑得就是,lean的固件启动dnsmasq实际上是使用的位于/var/etc/dnsmasq.conf的配置,如果配置项冲突会导致各种莫名其妙的事情方式(这就是我被坑了一下午的原因),所以建议比对/var/etc下面的配置进行修改。

关于策略路由和$$R这块,其核心原理是通过iptables+$$-redir+$$ 代理规则 实现的。不过做了一些修改,以适应路由器环境:

不在列表的域名->dnsmasq->ISP DNS-> (这也是默认的访问路线)
在列表的域名->pdnsd->proxy->DNS ->指定的访问路线

其中pdnsd是一个缓存DNS代理服务器 ,用来加速并获取正确的域名解析结果,这里的pdnsd也可以换成其他DNS服务,不过限制是运行在5335端口。另外,dnsmasq也有一份域名解析规则,跟前面$$的域名列表一致,用以区分不同线路的解析,不在列表的会走默认ISP DNS,在列表的会去往本地5335端口。(就是这个坑爹规则坑了我一个下午)

(这里我也有个疑惑:为何lean对在匹配列表中的域名用本地5335进行DNS查询,按理说应该用代理进行查询,这样返回的结果才最适合代理后的网络环境的呀)

lean的固件是实现了根据匹配规则进行透明代理,也就是路由器的lan侧用户是无感的,用户还是按照原来的方式访问,路由器这边拦截请求做匹配后在发送,用户只会发现访问速度比原来更快了。这个透明代理是通过iptables和$$-redir实现的,在路由器做NAT时(子网ip转换为wan口ip以发到公网),OUTPUT策略根据ip规则,redirect到$$-redir监听端口,从而实现对用户侧流量劫持。之后就是$$R一系列操作,根据域名来判断流量通道了。

三、使用自定义的DNS服务

上一部分提到了分流策略先是进入了路由器iptables的nat,根据ip规则,判断流量直接出去还是走$$-redir处理。对于要导入$$的流量,这时候就按照$$的代理规则进行处理,根据域名列表判断是否需要代理,需要代理的会去访问本地5335端口的DNS服务,返回的ip会被$$记住,之后访问这些ip就会走代理啦。

然而我们这里要使用自己的DNS服务器,也就是说不仅监听常规53端口,还要监听5335端口用来接收


发表评论