目前在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服务,问题解决。