在 Linux 上开 clash tun 模式 clash 是怎么劫持 dns 的

2022-09-16 18:38:07 +08:00
 nzhl

看了下, 感觉它既没有改写 /etc/hosts 也没改写 /etc/resolv.conf , 很好奇怎么做到的

7181 次点击
所在节点    DNS
19 条回复
aragakiyuii
2022-09-16 18:44:43 +08:00
seers
2022-09-16 18:52:54 +08:00
好像是 iptables 规则
nzhl
2022-09-16 19:02:01 +08:00
@aragakiyuii 有没有更具体的 就是他是怎么监听到 dns 请求的
nzhl
2022-09-16 19:05:12 +08:00
@seers 没 我看了 路由表里只有被劫持后的 198 网断
aragakiyuii
2022-09-16 19:07:20 +08:00
@nzhl 监听的 0.0.0.0:53 你看文档的配置文件
nzhl
2022-09-16 19:11:42 +08:00
@aragakiyuii 为啥监听 0000 53 能起作用 不是默认会让访问 etc resolv 文件里面指定的 dns server 吗
wangyu17455
2022-09-16 21:33:08 +08:00
clash 监听流过 tun 设备的一切流量,然后从中筛出你配置了 dns 劫持的目的地址,然后拦截,解析,向你在 clash 配置文件里设置的 dns 服务器发请求,然后收到回复,然后伪造一个源地址和你发送的 dns 查询的目的地址相同的回复
nzhl
2022-09-16 22:36:25 +08:00
@wangyu17455 问题从 routing table 来看, 只有已经经过了 DNS 的劫持的流量 (198.18.0.0/16) 才会流入 clash 创建的网卡

下面是关闭然后开启 tun 模式系统路由表的变化, 只是新增了一条
198.18.0.0/16 dev utun proto kernel scope link src 198.18.0.1
看上去这条记录只拦截 198.18 网段, 应该在这之前有一层 DNS 劫持把流量导入到了这个网段

> ip route
// tun mode disable
default via 192.168.50.1 dev wlo1 proto dhcp src 192.168.50.132 metric 20600
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-befa72e4dba9 proto kernel scope link src 172.18.0.1 linkdown
192.168.50.0/24 dev wlo1 proto kernel scope link src 192.168.50.132 metric 600
> ip route
# tun mode enable
default via 192.168.50.1 dev wlo1 proto dhcp src 192.168.50.132 metric 20600
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-befa72e4dba9 proto kernel scope link src 172.18.0.1 linkdown
192.168.50.0/24 dev wlo1 proto kernel scope link src 192.168.50.132 metric 600
198.18.0.0/16 dev utun proto kernel scope link src 198.18.0.1
wangyu17455
2022-09-16 22:43:18 +08:00
@nzhl 你系统其实有很多张路由表的,用 ip route show table 名字或者数字就能看见,你执行 ip rule 就会发现 clash 让所有流量都查询他自己创建的一张表,然后你用 ip route show table 名字 就能看见那张表的默认路由就是 dev utun ,你也可以用 ip route get 随便写一个 ip 上去来佐证这一点,它会打印出到这个 ip 走了哪条路由
nzhl
2022-09-16 22:44:50 +08:00
接上层,我其实好奇的就是这个对 DNS 的拦截是怎么做的, 因为 TUN 是 premium 的功能,只是功能开源了但是代码没开源。

我理解要拦截 DNS 有几个做法:
1. cat /etc/hosts

# Standard host addresses
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# This host address
127.0.1.1 nzhl-manjaro


2. cat /etc/resolv.conf

# Generated by NetworkManager
nameserver 192.168.50.1 # 这是我的华硕路由器


3. 根据 5 楼的说法以及看他配置似乎确实是在监听 53 端口, 但是首先我发现 53 端口啥也没有

> sudo netstat -tlunp|grep 53
tcp 0 0 127.0.0.1:53000 0.0.0.0:* LISTEN 586/clash-core-serv
udp 0 0 0.0.0.0:34622 0.0.0.0:* 537/avahi-daemon: r
udp 0 0 224.0.0.251:5353 0.0.0.0:* 405557/chrome --ena
udp 0 0 224.0.0.251:5353 0.0.0.0:* 405557/chrome --ena
udp 0 0 224.0.0.251:5353 0.0.0.0:* 405599/chrome --typ
udp 0 0 224.0.0.251:5353 0.0.0.0:* 405599/chrome --typ
udp 0 0 0.0.0.0:5353 0.0.0.0:* 537/avahi-daemon: r
udp6 0 0 :::51972 :::* 537/avahi-daemon: r
udp6 0 0 :::5353 :::* 537/avahi-daemon: r
nzhl
2022-09-16 22:49:28 +08:00
@wangyu17455 兄弟 我试了下 ip rule

> ip rule
0: from all lookup local
9500: from all to 198.18.0.0/16 lookup 1970566510
9510: from all ipproto icmp goto 9560
9520: not from all dport 53 lookup main suppress_prefixlength 0
9530: not from all iif lo lookup 1970566510
9540: from 0.0.0.0 iif lo uidrange 0-4294967294 lookup 1970566510
9550: from 198.18.0.1 iif lo uidrange 0-4294967294 lookup 1970566510
9560: from all nop
32766: from all lookup main
32767: from all lookup default

看着

9520: not from all dport 53 lookup main suppress_prefixlength 0
这一行有点像在拦截 53 ?
wangyu17455
2022-09-16 22:52:46 +08:00
@nzhl clash 的配置文件中,dns-hijack 之所以放在 tun 的配置底下而不是放在 dns 的配置底下就是因为 dns-hijack 依赖 tun ,假如你不配置 dns 劫持,只是把 /etc/resolv.conf 设置成 127.0.0.1 ,那么依赖系统进行解析的软件就都走了 clash 的 dns 了,但是不排除有的软件不依赖系统进行解析,走他自己设置的 dns ,这时候你就需要设置 dns-hijack 为 any:53 了,这样你本机发出的任何基于 udp53 端口的 dns 查询都会被 clash 拦截从而走 clash
nzhl
2022-09-16 22:55:43 +08:00
感谢兄弟 有点懂了 我好好领悟下
wangyu17455
2022-09-16 23:05:39 +08:00
@nzhl not{不是} (from all dport 53){来自任意来源的,目的端口是 53 的} lookup main{查找 main 路由表} suppress_prefixlength 0 连起来就是说目的端口不是 53 的走 main 路由表
nzhl
2022-09-16 23:14:13 +08:00
那应该是下面一条 非闭环的走 1970566510, 然后

> ip route show table 1970566510
default dev utun proto unspec

一旦走到 1970566510 就相当于被 clash 接管了, 这个理解没错把兄弟 @wangyu17455
wangyu17455
2022-09-16 23:23:12 +08:00
@nzhl
brianyao
2022-09-23 12:46:22 +08:00
based on 官方文档 & 我的理解:

1. tun 下的 dns-hijack 仅针对 tun 下的 tcp/udp 的请求进行 hijack ,即先匹配,再 hijack ,所以才有了 0.0.0.0:53 和 tcp://any53 的写法(解决某些特定场景下,会直接请求:target ip:port ,如果你不想一条一条加,就全部 hijack )

2. tun 是一个 L2 协议,所以 tun 本身是不涉及 domain 的操作的(在这一点上,和 socks5 不一样,socks5 的包里可以包裹 domian )在 tun 上的只有 L3 的东西,如 ip 、port 、protocol ,这也解答了 1 中的通配写法

3. 新版本 clash ,具有 auto-route 、auto- direct- interface 的 feature ,能够自动劫持内核网络栈流量,仅需开启 ipv4-forward 就可以,不需要再配置 iptables 。
shuiguomayi
75 天前
@brianyao 这里提到的新版本指的是 premium 版本吗?
stephenhero
36 天前

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/880652

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX