之前用 OpenWrt 的时候比较省心,装一个 Passwall(2) 之类的插件就可以实现透明代理,原理说白了也就是通过 tproxy 和一些 iptables 的重定向规则。iptables 这个东西难用已经是不争的事实了,我之前尝试在 Ubuntu/Debian 分别用 iptables/nftables 配置透明代理规则,试过了 mark 和 gid 等各种姿势,但不管怎么尝试总是会有流量出现回环,以及局域网设备流量不知去向的问题,所以索性省心一点用 Clash.Meta 内置的 TUN 模式来解决问题,同时相较于原版 Clash 也能够更好支持 VLESS 协议
基本的 Clash.Meta 配置文档在 官网 已经讲的比较清楚了,理论上来讲直接开启 TUN 就可以实现透明代理了,不过因为官网的文档基本上是针对单网口上网设备(比如手机、平板和 PC 之类)写的,对于多网口的路由器,还是有一些额外的配置需要注意
内网 IP 出口
在非网关单网口设备上,无论是访问 192.168.1.x 还是 114.114.114.114,出口的网卡都是同一个,那么 TUN 配置好 auto-detect-interface: true
一般就不会有什么大问题;对于路由器而言,就需要进行如下配置
1 | interface-name: ppp0 |
和上一篇文章一样,双网口设备 br0
需要改成对应 lan 接口名
TUN 协议栈的选择
理论上来说对于 linux 系统,选择默认的 stack: system
就可以了,不过在我的测试过程中发现了一个很奇怪的问题:保持其他配置不变的情况下,使用 system
协议栈会导致小爱音箱出现“网络服务遇到问题”的错误提示;而换用 gvisor
则一切正常。目前尚未 Google 到相关的具体原因,Clash.Meta 的日志也比较正常看不出端倪,实际使用下来两种协议栈资源的消耗并没有很大区别,并且也都能够轻松跑满带宽,所以直接选用 gvisor
作为协议栈
网段分组策略代理
总有一些设备是完全不需要代理的(在 TUN 模式下直连流量还是会走一遍 Clash.Meta,不过问题不大),通过 dnsmasq 进行 mac ip 绑定,划分更小的网段
1 | # rule-proxy, 192.168.1.0/24 |
然后 Clash.Meta 的规则就可以写成
1 | rules: |
Docker 与健康检查
使用 Docker Compose 来部署 Clash.Meta 会非常方便快捷
1 | services: |
这样 docker stop clash
和 docker restart clash
就能非常方便终止和重启服务,由于 metacubex/clash-meta
基于 busybox
镜像,本身就有 wget
命令可用于健康检查。/dev/net/tun
的设备映射和 NET_ADMIN
的权限是必不可少的(除非想要自己手动改路由表)