使用 clash 和路由表实现透明代理
本文内容如有错误,请在评论区指出
需要的工具
要进行全局代理,常见的方式是转发到特定端口、使用 tun 虚拟设备和使用 TPROXY。clash 有 redir port 可以直接转发实现代理,但是只支持 TCP,IPv6 的支持也尚未合并。TPROXY 是 v2ray-core 的推荐方式。而另一种方式则是 tun。本文介绍的是使用 tun 的方式。
要使用这种方式,首先需要一个使用 tun 转发流量的工具,目前 clash 主线并不支持 tun,clash 作者有一个支持 tun 的闭源版本,另外 comzyh 有一个支持 tun 的分支,性能不错,稳定性一般。然后有一个通用的工具 tun2socks,稳定性较好但性能一般。后两者都不错。
需要的知识
基本的路由表、iptables 操作
设置转发路由
首先需要使用 ip tuntap add <tun name> mode tun user <tun user>
创建一个 tun 设备,并使用 ip link set <tun name> up
启用。
然后设置路由 ip address replace <tun address> dev <tun name>
,tun address 取一个不常用的 IP 段,比如 kr328 的脚本中使用 172.31.255.253/30,又比如 go-tun2socks 默认的 10.255.0.1/24。
然后设置路由规则
|
|
把有特定 fwmark 标记的流量路由到 tun 其中 fwmark 号和 route 表号可以自行设定(不要和其他的规则重复)。
然后用 iptables 在 mangle 表上,把需要代理的流量打上 fwmark 标记,使用 -j MARK --set-mark <fwmark id>
即可
绕过部分流量
利用 iptables 支持的丰富规则,我们可以灵活地绕过各种流量,列出几个比较常用的:
-m owner --uid-owner <username or uid>
匹配某个用户的流量,类似的还有--gid-owner
-p <'tcp', 'udp' or 'icmp'>
匹配某种类型流量--dport <port num>
匹配目的端口,类似的--sport
匹配源端口,需要和-p tcp
等连用-d <network name, hostname, subnet(IP CIDR) or IP>
匹配目的网络/主机名/子网/IP-m set --match-set <ipset name> <'dst' or 'src'>
匹配 ipset,可以用于简化规则,ipset 用法自行搜索-m cgroup --cgroup <cgroup id>
匹配 cgroup
有较多规则时可以创建规则链,并把 OUTPUT 或 PREROUTING 链中的流量转入该链(ip6tables 也一样):
|
|
然后在规则链上编写规则即可,需要打标记走代理就 -j MARK --set-mark <fwmark id>
,需要绕过就 -j RETURN
,一般建议先写绕过规则,最后无条件地打标记。注意一定要绕过 clash 的流量(建议 uid/gid 或 cgroup)
使用 cgroup net_cls
cgroup 是 Linux 内核的一个功能,这里需要用到它的 net_cls 子系统。使用起来简单,我们首先运行以下命令创建一个组:
|
|
上述命令可以在开机时运行
这样,如果一个进程的 pid 在 /sys/fs/cgroup/net_cls/<cgroup name>/tasks
中,它就会被 iptables 的 -m cgroup --cgroup <cgroup id>
规则匹配到,并且这些进程的子进程 pid 会自动被添加。如果对安全比较敏感,你可以对该文件进行适当的权限控制。
可以使用一个脚本,以它作为 wrapper 来运行需要的命令
|
|
单独转发 DNS
与 v2ray 不同,clash 不能通过其规则把流量转到 clash 的内置 DNS,且 clash 不支持 sni 解析域名,需要内置 DNS 反查域名。
因此,需要使用 nat 表把 DNS 流量转发到 clash 的 DNS 端口,对 UDP 53 端口的流量,设置适当的绕过规则过滤后,-j REDIRECT --to-ports <clash dns port>
即可。
tun 工具配置
comzyh 的 clash 分支需要在配置文件中设置以下内容
|
|
go-tun2socks 用以下命令启动
tun2socks -tunName <tun name> -proxyServer <clash socks server> -tunAddr <tun address> -tunGw <tun gateway> -tunMask <tun mask> -tunPersist -blockOutsideDns
选一个不常用的 subnet,并取该 subnet 内两个不同地址作为 tun gateway 和 tun address。
比如要使用 172.31.255.253/30 子网。则 tun mask 为 255.255.255.252,tun gateway 可以用 172.31.255.253,tun address 可以用 172.31.255.254,默认参数对应的子网是 10.255.0.1/24