目前在Ubuntu上使用Clash for Windows的TUN模式时,会发现并不能劫持流量。这个问题困扰了我好久,最近有空深度研究了一下这个问题。
首先我们来看一下Clash目前在Linux上hijack方案。用ip rule查看系统路有表会发现这么几行
ip rule
0: from all lookup local
5210: from all fwmark 0x80000/0xff0000 lookup main
5230: from all fwmark 0x80000/0xff0000 lookup default
5250: from all fwmark 0x80000/0xff0000 unreachable
5270: from all lookup 52
9500: not from all dport 53 lookup main suppress_prefixlength 0
9510: not from all iif lo lookup 1970566510
9520: from 0.0.0.0 iif lo uidrange 0-4294967294 lookup 1970566510
9530: from 198.18.0.1 iif lo uidrange 0-4294967294 lookup 1970566510
32766: from all lookup main
32767: from all lookup default
其中9500到9530需要解释一下
//所有非53端口的请求,先看看默认路由表有没有特殊的配置
9500: not from all dport 53 lookup main suppress_prefixlength 0
// 其他流量,都走路由表1970566510
9510: not from all iif lo lookup 1970566510
9520: from 0.0.0.0 iif lo uidrange 0-4294967294 lookup 1970566510
9530: from 198.18.0.1 iif lo uidrange 0-4294967294 lookup 1970566510
然后查看路由表1970566510,可以看到就是tun设备的路由信息
ip route show table 1970566510
default dev utun proto unspec
所以很简单,仅仅是所有的流量到过tun接口,然后clash在tun中分离出dns。
但是ubuntu使用systemd-resolved来提供本地dns服务,且其使用raw socket直接发送dns请求到网卡,因此忽略了路由表。这就是Clash for Windows无法劫持流量的原因。
那么如何配置?systemd-resolved可以提供全局配置,这个配置不绑定特殊网卡,所以是走路由表的。因此,创建文件/etc/systemd/resolved.conf.d/clash.conf,在里面配置如下信息:
[Resolve]
DNS=114.114.114.114
Domains=~.
重启systemd-resolved服务,问题解决。