最近有个需求是在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使用:
最终实现效果图:
发表回复