nftables+clash打造透明代理时的dns处理问题
在ubuntu上启用一个透明代理,这样局域网设备或者基于ocserv的VPN拨入进来可以无缝的访问需要代理才能访问的网站,同时VPN拨入进来后只有需要代理的流量走VPN,从而避免本地的访问速度变慢。
考虑到对iptables实在不太熟悉,且觉得很多的配置过于繁琐也反人类,最终选择通过nftables劫持流量给到服务器上部署的clash端口。
关于详细的配置或者需要配置UDP的透明代理,可以参考如下文章
https://koswu.github.io/2019/08/19/tproxy-config-with-nftables/
ntables的配置参考:
root@clash:~# cat /etc/nftables.conf #!/usr/sbin/nft -f flush ruleset define lan = { 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4, 240.0.0.0/4 } table ip nat { chain proxy { ip daddr $lan return ip protocol tcp redirect to :7892 } chain prerouting { type nat hook prerouting priority 0; policy accept; jump proxy } }
其中7892端口是给到本地的clash的redir-port,clash上的配置参考:
root@clash:~# cat /etc/clash/config.yaml | head -n 10 tproxy-port: 7890 mixed-port: 7891 redir-port: 7892 allow-lan: true bind-address: '*' mode: rule log-level: info
ocserv的配置省略,可以参考这个项目:
用于初始化 ocserv 的 Dockfile 脚本
★ 609
正常来说到上面这步骤透明代理已经配置完成,但实际在应用过程中一步一步踩到了各种坑:
坑1:
正常来说,在现在的环境下,操作系统中使用代理软件无需考虑DNS解析的问题,但透明代理时部分网站访问不正常。
原因:当使用透明代理时存在DNS污染的问题。客户端拿到错误的IP后发起请求,会导致部分网站访问不正常。
解决方案:内网存在一个不被污染的DNS服务器地址,直接配置给客户端即可解决问题。
坑2:
配置完DNS后,访问部分网站时,发现并没有完全按照clash定义的规则进行处置。尤其是访问ChatGPT时,没有走代理链。
原因:使用socks5代理时(socks4不支持),浏览器会将域名封装在流量中发往代理服务器。此时代理服务器可以使用domain类的命中规则对此次代理直接命中接管,或使用系统自带DNS解析出一个保留地址或国外IP后,命中国外规则走代理处理。无论哪种情况代理服务器是可以拿到域名信息的。
但使用透明代理时且使用第三方DNS时,代理服务器拿不到域名信息自然规则也就失效。
解决方案:在坑1的过程中并没有考虑到DNS的传递问题,当时简单的理解直接解决DNS污染问题了。
Surge/Clash(新版)都采用Fake IP功能,该定义出自
。简单的说就是客户端需要从代理软件进行域名解析,同时代理软件需要维护一个域名与IP对应的临时数据库。增加的clash的配置文件参考:
dns: enable: true ipv6: false listen: 0.0.0.0:53 enhanced-mode: fake-ip nameserver: - 8.8.8.8 fallback: - 8.8.8.8
坑3:
按如上的配置终于能正常进行运转了,但是使用vpn拨入内网的时候发现了一个新的问题,ocserv下发的no-route配置段不起作用了。所有的流量全部走VPN了。
原因:ocserv的no-route或者route字段只能对IP地址(段)起作用,无法针对域名。后续排查了很久后才找到原因是因为坑2新加的Fake IP功能导致所有的域名都在一个保留IP地址段下(198.18.0.0/24),客户端拿不到正确的IP地址,自然no-route是失效的。
解决方案:dns的前端还需要套一层dnsmasq或者其他的轻量dns服务器,同时对国内域名进行解析使得客户端拿到正确的IP地址,自然ocserv的no-route字段就生效了。
dnsmasq的国内域名解析列表可以参考这个项目,需要注意的是dnsmasq的上游需要指向clash的dns字段,clash的dns字段监听端口需要改成5353从而释放标准端口给dnsmasq使用:
Chinese-specific configuration to improve your favorite DNS server. Best partner for chnroutes.
★ 5.6k
最终实现效果图:
ocserv配合clash+dnsmasq解决国内外分流问题
ocserv中通过route/no-route配置使得下发路由表到客户端,从而实现流量分流。大家一般通过该配置来选择哪些IP地址的路由需要到到服务端转发来解决路由流向的问题。
家庭宽带的上传一般来说比较小,或即使ocserv的服务端部署在大带宽服务器上,大家也希望尽量只有需要的流量才通过服务器中转,减少无用流量上VPN设备转发从而减少时延提升用户体验。但ocserv下发的路由表最多支持下发200条路由表。
为了尽可能的在200条路由表内塞下route或者no-route,大家发挥聪明才智通过合并cidr或者扩大cn的路由表范围等方式,有了很多优秀的no-route表,例如:
★ 488
之前我也是通过这种方式进行分流,但使用中仍旧有很多不好的体验:
cn-no-route部分时候在openconnect中无效
总容量200条,减去内网需要占用的条数,仍旧有较多路由重定向不准确
在客户端无法有效的排错该路由是否走vpn隧道
部分CN的IP如果想从vpn隧道通过,则改动非常大,且不一定能实现
我在部署本文引言中提到的透明代理时,突然想到,其实可以利用dnsmasq+clash的fake-ip功能一劳永逸解决分流的问题。
原理
Fake-IP定义可以参考 ,原理是客户端向clash服务端请求域名时,服务端会返回一个198.16.0.0/16的临时IP,并记录该IP与域名的对应关系用于后续发起请求时的访问。
有了这个原理,实现的过程就很简单了,只需要删除原来的所有no-route表,下发一个route表,涵盖内网IP段和198.16.0.0/16即可。
同时客户端的dns指向ocserv的dnsmasq的地址,设置需要调度到服务端的流量指向clash让其返回fake ip即可。
而dnsmasq分流没有ocserv的200条路由表(域名)限制,github上也有一个非常好的中国域名的解析列表。
使用方法为:dnsmasq的上游dns指定为clash的dns地址(若clash和dnsmasq在同一IP上,则需要修改clash的dns端口监听为非53端口,例如5353),配置文件使用如下仓库。
Chinese-specific configuration to improve your favorite DNS server. Best partner for chnroutes.
★ 5.6k
ocserv的配置修改如下:
此时重启ocserv服务端后,客户端连接后则正确按照指定方式分流了。
使用该方法的缺点是只能通过dns解析的方式对流量进行调度,无法对直接访问IP的方式进行调度,不过可以在内网搭建一个xio解析服务变相的解决这个问题,
但以上仍然无法解决硬编码的IP地址问题,这种情况只能通过本地增加路由表解决。
推荐本站淘宝优惠价购买喜欢的宝贝:
以下内容需要兑换:本文链接:https://hqyman.cn/post/8628.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~