loca1h0st's Blog
loca1h0st's Blog

nftables+clash打造透明代理时的dns处理问题

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的配置省略,可以参考这个项目:


正常来说到上面这步骤透明代理已经配置完成,但实际在应用过程中一步一步踩到了各种坑:

坑1:

正常来说,在现在的环境下,操作系统中使用代理软件无需考虑DNS解析的问题,但透明代理时部分网站访问不正常。

原因:当使用透明代理时存在DNS污染的问题。客户端拿到错误的IP后发起请求,会导致部分网站访问不正常。

解决方案:内网存在一个不被污染的DNS服务器地址,直接配置给客户端即可解决问题。


坑2:

配置完DNS后,访问部分网站时,发现并没有完全按照clash定义的规则进行处置。尤其是访问ChatGPT时,没有走代理链。

原因:使用socks5代理时(socks4不支持),浏览器会将域名封装在流量中发往代理服务器。此时代理服务器可以使用domain类的命中规则对此次代理直接命中接管,或使用系统自带DNS解析出一个保留地址或国外IP后,命中国外规则走代理处理。无论哪种情况代理服务器是可以拿到域名信息的。

但使用透明代理时且使用第三方DNS时,代理服务器拿不到域名信息自然规则也就失效。

解决方案:在坑1的过程中并没有考虑到DNS的传递问题,当时简单的理解直接解决DNS污染问题了。

Surge/Clash(新版)都采用Fake IP功能,该定义出自RFC3089。简单的说就是客户端需要从代理软件进行域名解析,同时代理软件需要维护一个域名与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使用:

最终实现效果图:

https://blog.mrtblogs.net/wp-content/uploads/2023/03/image-1024x533.png

发表回复

textsms
account_circle
email

loca1h0st's Blog

nftables+clash打造透明代理时的dns处理问题
最近有个需求是在ubuntu上启用一个透明代理,这样局域网设备或者基于ocserv的VPN拨入进来可以无缝的访问需要代理才能访问的网站,同时VPN拨入进来后只有需要代理的流量走VPN,从而避免本…
扫描二维码继续阅读
2023-03-13