198.18.0.2 是什么?

287 天前
 FaiChou

某些软件可以建立虚拟网络接口,在 macOS 上执行 ifconfig 可以看到 utun10,其 ip 地址是 198.18.0.1,Wi-Fi 的 dns 设置也被更改成 198.18.0.2.

但是 198.18.0.2 是什么?它并不是本机某网口的地址。

越研究发现越神奇。

首先使用 route -n get 198.18.0.2 结果如下:

   route to: 198.18.0.2
destination: 198.18.0.2
    gateway: 198.18.0.1
  interface: utun10

但是只要不是 198.18.0.1 和 198.18.0.2 (有时候 0.3 也可能是)则结果如下:

   route to: 198.18.0.4
destination: 128.0.0.0
       mask: 128.0.0.0
    gateway: 198.18.0.1
  interface: utun10

   route to: 198.18.1.2
destination: 128.0.0.0
       mask: 128.0.0.0
    gateway: 198.18.0.1
  interface: utun10

看到这个 destination 应该是 CIDR 128.0.0.0/1 起作用了。

查看路由表:

~ netstat -rn
Routing tables

Internet:
Destination        Gateway            Flags           Netif Expire
default            192.168.31.1       UGScg             en1
default            link#28            UCSIg           utun3
1                  198.18.0.1         UGSc           utun10
2/7                198.18.0.1         UGSc           utun10
4/6                198.18.0.1         UGSc           utun10
8/5                198.18.0.1         UGSc           utun10
16/4               198.18.0.1         UGSc           utun10
32/3               198.18.0.1         UGSc           utun10
64/2               198.18.0.1         UGSc           utun10
100.64/10          link#28            UCS             utun3
100.100.100.100/32 link#28            UCS             utun3
100.124.11.45      100.124.11.45      UH              utun3
127                127.0.0.1          UCS               lo0
127.0.0.1          127.0.0.1          UH                lo0
128.0/1            198.18.0.1         UGSc           utun10
169.254            link#13            UCS               en1      !
169.254.12.71      50:ed:3c:3:2:c     UHLSW             en1      !
169.254.35.85      60:dd:8e:69:5c:d0  UHLSW             en1      !
192.168.31         link#13            UCS               en1      !
192.168.31.1/32    link#13            UCS               en1      !
192.168.31.1       88:c3:97:c8:2:b6   UHLWIir           en1   1169
192.168.31.24      4:cf:8c:29:a4:97   UHLWI             en1   1157
192.168.31.59      c:7a:15:c1:ad:cc   UHLWI             en1      !
192.168.31.73      6:6e:f7:98:f3:4b   UHLWI             en1    349
192.168.31.80      84:c5:a6:9e:4:3    UHLWI             en1    601
192.168.31.129     86:11:14:df:18:ce  UHLWI             en1    555
192.168.31.144     56:f9:cf:1e:97:7d  UHLWI             en1     95
192.168.31.166/32  link#13            UCS               en1      !
192.168.31.189     66:17:81:34:32:5c  UHLWI             en1   1112
192.168.31.199     60:dd:8e:69:5c:d0  UHLWIi            en1   1160
192.168.31.213     50:ed:3c:3:2:c     UHLWIi            en1   1189
192.168.31.214     2:69:d6:3d:12:3d   UHLWI             en1   1179
192.168.31.222     f8:d0:27:54:e4:84  UHLWI             en1   1200
192.168.31.255     ff:ff:ff:ff:ff:ff  UHLWbI            en1      !
198.18.0.1         198.18.0.1         UH             utun10
224.0.0/4          link#13            UmCS              en1      !
224.0.0/4          link#28            UmCSI           utun3
224.0.0.251        1:0:5e:0:0:fb      UHmLWI            en1
239.255.255.250    1:0:5e:7f:ff:fa    UHmLWI            en1
255.255.255.255/32 link#13            UCS               en1      !
255.255.255.255/32 link#28            UCSI            utun3

里面关于 utun10 的几条解释:

2/7 地址范围: 2.0.0.0 到 2.255.255.255
4/6 地址范围: 4.0.0.0 到 7.255.255.255
8/5 地址范围: 8.0.0.0 到 15.255.255.255
16/4 地址范围: 16.0.0.0 到 31.255.255.255
32/3 地址范围: 32.0.0.0 到 63.255.255.255
64/2 地址范围: 64.0.0.0 到 127.255.255.255
128.0/1 地址范围: 128.0.0.0 到 255.255.255.255
198.18.0.1  就表示它自己

所以除了 198.18.0.1 之外其余的都应该解析成 128.0.0.1 才对啊。那 198.18.0.2 为啥也解析成自己了呢?

我的理解: 跑的服务程序可以监听本地网口, 每个网口有对应的 ip 地址,如果监听 0.0.0.0 则表示所有网口,如果监听 127.0.0.1 则表示监听 lo0 ,如果监听 192.168.31.166 (我电脑 en0 地址)则表示监听 en0 网口,任何发送到这个网口的数据(当然要指定好端口号)都会被转发到这个服务程序。

但查看 ifconfig 则看不到 198.18.0.2 是属于哪一个接口的,而它是 utun10(198.18.0.1)的一个子网 ip 。当开启虚拟网口后(软件的增强模式透明模式) dns 被改成 198.18.0.2 是为什么?使用 dig 程序测试也是没问题的:

~ dig @198.18.0.2 -p 53 baidu.com
~ dig @198.18.0.2 -p 53 google.com
~ dig @198.18.0.2 -p 53 fb.com

结果都是 fakeip 。

所以,我哪里理解错了吗?为什么会有 198.18.0.2 ?

5400 次点击
所在节点    程序员
26 条回复
imnpc
287 天前
装了 ClashX ?开了增强模式?
FaiChou
287 天前
@imnpc 对,故意没有说这几个单词的,容易触发关键字,被移动到某节点下,不会出现在首页。
Darin726
287 天前
@FaiChou #2 clash 的增强模式会新建一个虚拟网卡接管本机的网络,你发的这个 IP 就是虚拟网络的内网
FaiChou
287 天前
@Darin726 为什么不是 198.18.0.1 而是 0.2 ? 通过 dig 命令可以测试到 198.18.0.1 也是可以响应 dns 请求的( listen: 0.0.0.0:53 起作用)。为什么要用 0.2 这个子网?
bigshawn
287 天前
虚拟网卡不必在意。
ETiV
287 天前
FaiChou
287 天前
我写了一个程序来测试:

```
const http = require('http');
const server = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Content-Type', 'text/plain');
res.end('Hello');
});
const ifrq = "198.18.0.2";
server.listen(3000, ifrq, () => {
console.log(`Server running at http://${ifrq}:3000/`);
});
```

开启增强模式后 如果 ifrq 是 198.18.0.1 则可以正常绑定到这个地址,打开这个地址 3000 端口后正常响应。
但如果将 ifrq 改成 198.18.0.2 ,则服务起不了 Error: listen EADDRNOTAVAIL: address not available 198.18.0.2:3000
jsq2627
287 天前
dns server 没有 listen on 198.18.0.2
198.18.0.2 走的也是 128.0/1 这条路由,被当成普通流量送往了 utun10
utun10 是虚拟网关,它检查到 dst ip 是 198.18.0.2 之后,认为这是一个 dns 请求,给与 fake ip dns 响应
leonshaw
287 天前
一种可能是 redirect ;一种是独立的协议栈,可以理解为你通过 utun 发给了另一台虚拟主机。
jsq2627
287 天前
surge/clash 没有选择直接 bind 198.18.0.1:53 ,应当是出于兼容性考虑,如果本机有其他程序 bind 0.0.0.0:53 ,会导致一方失败。
FaiChou
287 天前
@jsq2627 #8
"198.18.0.2 走的也是 128.0/1 这条路由,被当成普通流量送往了 utun10"
第一:使用 `route -n get 198.18.0.2` 的结果为什么和 198.18.0.4 有差别呢?

第二:我搜了下 clash-meta 的源码,没有找到 `198.18.0.2` 的关键字,clashxpro 和 surge 没有开源,所以也看不到具体的实现。所以 "检查到 dst ip 是 198.18.0.2 之后,认为这是一个 dns 请求" 可能是这样的,但并不能确定。

另外,谢谢回复。
vzyw
287 天前
jsq2627
287 天前
@FaiChou
clash-meta 相关代码在这里:
https://github.com/MetaCubeX/Clash.Meta/blob/53f9e1ee7104473da2b4ff5da29965563084482d/listener/sing_tun/server.go#L145
取了 options.Inet4Address 的下一位地址作为 DNS 地址。
options.Inet4Address 来源在这里:
https://github.com/MetaCubeX/Clash.Meta/blob/Alpha/config/config.go#L1343
是从 fake-ip-range 配置项取出来的第一个地址。


route -n get 198.18.0.2 结果可以看到有个 flag `WASCLONED`,简而言之这是 macOS 动态生成的一条路由,缓存用途
https://etutorials.org/Networking/Integrated+cisco+and+unix+network+architectures/Chapter+8.+Static+Routing+Concepts/Route+Cloning/
jsq2627
287 天前
"检查到 dst ip 是 198.18.0.2 之后,认为这是一个 dns 请求"
在 clash meta 的实现:
https://github.com/MetaCubeX/Clash.Meta/blob/53f9e1ee7104473da2b4ff5da29965563084482d/listener/sing_tun/dns.go#L38
并且这里只检查 dst ip ,不检查 port 。因此 dig @198.18.0.2 baidu.com -p 12345 这样使用任意 port 都可以得到 DNS 响应。
yov123456
287 天前
其实 这个是作者随便写的一个地址。。配置 hijack 后写什么地址都行,clashx 是取了网关地址+1
jsq2627
287 天前
@yov123456 正解,198.18.0.2 和 dns-hijack 走的都是同一套逻辑
FaiChou
287 天前
@jsq2627 #13 谢谢。执行 route -n get ip 时候确实漏掉了一些关键信息,比如 198.18.0.2 的 flag 其中有 H, 说明是个 HOST 点对点的地址,不需要经过路由。所以冒昧再问一个问题,这个 198.18.0.2 在哪里被添加成 HOST 的?难道在 dnsAdds 的 ListenerHandler 处理的吗?如果是一个普通的监听服务器,如果 198.18.0.2 没有对应的网口则监听失败,和我 append 中的情况一样。所以这一块核心在哪里?找了一会没有找到。
jsq2627
287 天前
“198.18.0.2 的 flag 其中有 H, 说明是个 HOST 点对点的地址,不需要经过路由”
这个说法不完全对。所有 /32 路由都会被标记为 H 。他们还是会经过路由,需要查路由表确定发送到哪个 gateway

“198.18.0.2 在哪里被添加成 HOST 的”
正如我之前解释,198.18.0.2/32 这是一条由系统动态生成的 route ,用于缓存加速(匹配一条 /32 比匹配 128.0/1 效率更高,所以系统首次匹配完后,会生成一条 /32 路由缓存)。因为它是一条 /32 路由,所以标上了 H flag
jsq2627
287 天前
netstat -rna 你会发现还有很多其他动态生成的路由,不仅局限于 198.18 段
jsq2627
287 天前
“难道在 dnsAdds 的 ListenerHandler 处理的吗?如果是一个普通的监听服务器,如果 198.18.0.2 没有对应的网口则监听失败,和我 append 中的情况一样”

注意这里不是监听,不是 socket/bind 。而是虚拟网卡,流经网卡的所有 packet 都会由程序捕捉到,无论 src/dst ip/port 是什么。
哪些 packet 会经过虚拟网卡,则是由系统路由表决定的

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

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

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

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

© 2021 V2EX