用 Firewalld + systemd.slice + redir 實現 TCP + UDP 透明代理
现在网上已经有不少用 iptables 或 nftables 实现透明代理(Tproxy)的例子了。绝大多数关于透明代理的教程都是通过 iptables 实现的,也有少量使用新一代的 nftables 内核防火墙前端来实现。然而,消费级电脑上通常会装有更简化的防火墙程序,例如 Fedora/CentOS/SUSE 自带的 Firewalld,或 Ubuntu 的 UFW。在用这些简化前端的同时,直接操作 nftables 和 iptables 的话可能会造成冲突,更好的解法是全部工作都由 firewalld/ufw 来做。
本文就以 firewalld 为例,用它的 direct rules 来实现透明代理(没错,firewalld 并不提供关于透明代理的抽象,所以并不比 iptables 有优势)。
想要实现的效果
- TCP 和 UDP 流量自动转给 Clash(或 shadowsocks 等)
- Clash 本身不会把流量转发给自己
- 可以让某些 程序 不转发给 clash,直接联网
Get started
先来设置变量,指向 clash 的 redir-port
:
export proxy_port=7892 # 按你 clash 的设置修改
接着设置 firewalld 和 ip route。 Firewalld 的 direct rules 语法几乎等同于 iptables(因为实际上就是调用 iptables 来执行 direct rules)。所以这里直接照抄 systemd.slice + iptables + redir:如何在 Arch Linux 上配置透明代理 的规则,稍有修改:
#tcp sudo firewall-cmd --direct --add-chain ipv4 nat clash sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -m cgroup --path "clash.slice" -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 0.0.0.0/8 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 10.0.0.0/8 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 127.0.0.0/8 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 169.254.0.0/16 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 172.16.0.0/12 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 192.168.0.0/16 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 224.0.0.0/4 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -d 240.0.0.0/4 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 nat clash 2 -p tcp -j REDIRECT --to-port "$proxy_port" sudo firewall-cmd --direct --add-rule ipv4 nat OUTPUT 1 -p tcp -j clash #udp sudo ip rule add fwmark 1 table 100 sudo ip route add local default dev lo table 100 sudo firewall-cmd --direct --add-chain ipv4 mangle clash sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -m cgroup --path "clash.slice" -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 0.0.0.0/8 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 10.0.0.0/8 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 127.0.0.0/8 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 169.254.0.0/16 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 172.16.0.0/12 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 192.168.0.0/16 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 224.0.0.0/4 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 1 -d 240.0.0.0/4 -j RETURN sudo firewall-cmd --direct --add-rule ipv4 mangle clash 2 -p udp -j TPROXY --on-port "$proxy_port" --tproxy-mark 1 sudo firewall-cmd --direct --add-rule ipv4 mangle OUTPUT 0 -p udp -j clash # 这里可能有错(`failed: iptables-restore: line 3 failed`),欢迎指正 sudo firewall-cmd --direct --add-chain ipv4 nat CLASH_DNS sudo firewall-cmd --direct --remove-rules ipv4 nat CLASH_DNS sudo firewall-cmd --direct --add-rule ipv4 nat CLASH_DNS 1 -p udp -j REDIRECT --to-port 1053 sudo firewall-cmd --direct --add-rule ipv4 nat OUTPUT 0 -p udp --dport 53 -j CLASH_DNS
其中,sudo firewall-cmd --direct --add-rule ipv4 nat clash 1 -m cgroup --path "clash.slice" -j RETURN
将放到 clash.slice
下的 service 给绕过 clash 了。
Clash 要以 systemd unit 的形式 来运行。为了让 clash 不把自己的流量循环转回给自己,给它的 unit 分配给 clash.slice
。
[Service] Slice=clash.slice
其它不想走 clash 的程序也可以以类似方式分配给 clash.slice。
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!
- 来自作者
- 相关推荐