V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
FaiChou
V2EX  ›  程序员

198.18.0.2 是什么?

  •  2
     
  •   FaiChou ·
    FaiChou · 2023-09-16 11:01:26 +08:00 · 6234 次点击
    这是一个创建于 429 天前的主题,其中的信息可能已经有所发展或是发生改变。

    某些软件可以建立虚拟网络接口,在 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 ?

    第 1 条附言  ·  2023-09-16 11:44:01 +08:00
    写一个程序来测试:

    ```javascript
    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.
    26 条回复    2023-09-17 00:26:23 +08:00
    imnpc
        1
    imnpc  
       2023-09-16 11:02:50 +08:00
    装了 ClashX ?开了增强模式?
    FaiChou
        2
    FaiChou  
    OP
       2023-09-16 11:03:55 +08:00
    @imnpc 对,故意没有说这几个单词的,容易触发关键字,被移动到某节点下,不会出现在首页。
    Darin726
        3
    Darin726  
       2023-09-16 11:07:28 +08:00
    @FaiChou #2 clash 的增强模式会新建一个虚拟网卡接管本机的网络,你发的这个 IP 就是虚拟网络的内网
    FaiChou
        4
    FaiChou  
    OP
       2023-09-16 11:10:24 +08:00
    @Darin726 为什么不是 198.18.0.1 而是 0.2 ? 通过 dig 命令可以测试到 198.18.0.1 也是可以响应 dns 请求的( listen: 0.0.0.0:53 起作用)。为什么要用 0.2 这个子网?
    bigshawn
        5
    bigshawn  
       2023-09-16 11:13:10 +08:00
    虚拟网卡不必在意。
    ETiV
        6
    ETiV  
       2023-09-16 11:17:18 +08:00 via iPhone
    FaiChou
        7
    FaiChou  
    OP
       2023-09-16 11:17:47 +08:00
    我写了一个程序来测试:

    ```
    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
        8
    jsq2627  
       2023-09-16 12:26:27 +08:00 via iPhone
    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
        9
    leonshaw  
       2023-09-16 12:27:09 +08:00 via Android
    一种可能是 redirect ;一种是独立的协议栈,可以理解为你通过 utun 发给了另一台虚拟主机。
    jsq2627
        10
    jsq2627  
       2023-09-16 12:28:30 +08:00 via iPhone   ❤️ 1
    surge/clash 没有选择直接 bind 198.18.0.1:53 ,应当是出于兼容性考虑,如果本机有其他程序 bind 0.0.0.0:53 ,会导致一方失败。
    FaiChou
        11
    FaiChou  
    OP
       2023-09-16 12:50:01 +08:00
    @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
        12
    vzyw  
       2023-09-16 14:09:09 +08:00
    jsq2627
        13
    jsq2627  
       2023-09-16 14:12:14 +08:00   ❤️ 1
    @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
        14
    jsq2627  
       2023-09-16 14:18:42 +08:00
    "检查到 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
        15
    yov123456  
       2023-09-16 14:21:58 +08:00 via iPhone
    其实 这个是作者随便写的一个地址。。配置 hijack 后写什么地址都行,clashx 是取了网关地址+1
    jsq2627
        16
    jsq2627  
       2023-09-16 14:27:21 +08:00
    @yov123456 正解,198.18.0.2 和 dns-hijack 走的都是同一套逻辑
    FaiChou
        17
    FaiChou  
    OP
       2023-09-16 14:53:15 +08:00
    @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
        18
    jsq2627  
       2023-09-16 14:59:34 +08:00 via iPhone
    “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
        19
    jsq2627  
       2023-09-16 15:01:42 +08:00 via iPhone
    netstat -rna 你会发现还有很多其他动态生成的路由,不仅局限于 198.18 段
    jsq2627
        20
    jsq2627  
       2023-09-16 15:06:03 +08:00 via iPhone   ❤️ 1
    “难道在 dnsAdds 的 ListenerHandler 处理的吗?如果是一个普通的监听服务器,如果 198.18.0.2 没有对应的网口则监听失败,和我 append 中的情况一样”

    注意这里不是监听,不是 socket/bind 。而是虚拟网卡,流经网卡的所有 packet 都会由程序捕捉到,无论 src/dst ip/port 是什么。
    哪些 packet 会经过虚拟网卡,则是由系统路由表决定的
    wdf1286
        21
    wdf1286  
       2023-09-16 16:43:02 +08:00
    首先,他不能是 198.18.0.1 ,因为这是你本机的 ip ,向本机 ip 发送的数据包会直接进本地回环,不进 clash 注册的那个 tun 设备,进而导致 clash 根本收不到你发出去的 dns 请求,无法劫持你的 dns ,也就不能正常的代理连接,至于为什么是 198.18.0.2 ,没有太多的原因,就是随手取的
    FaiChou
        22
    FaiChou  
    OP
       2023-09-16 18:18:13 +08:00
    @wdf1286 并不赞同,可以看到 append 中的例子,是可以绑定 192.18.0.1 并且正常收到请求的。" clash 注册的那个 tun 设备"的 ip 地址就是 198.18.0.1 ,和 127.0.0.1 还有 192.168.11.109 (我的电脑)等都是网口的地址,198.18.0.1 是 utun 的网口地址,127.0.0.1 是 lo0 ,192.168.11.109 是 en0 的。如果程序监听 0.0.0.0 ,则向前面这三个网口的地址发起请求都可以正常收到。
    FaiChou
        23
    FaiChou  
    OP
       2023-09-16 18:32:10 +08:00
    @FaiChou #22 并且没有选用 198.18.0.1 的原因在 10 楼已经给出答案了。如果其他程序 bind 了所有网口 53 端口,那么会冲突。
    FaiChou
        24
    FaiChou  
    OP
       2023-09-16 18:44:23 +08:00
    @jsq2627 #14 这个代码中有检查 port: targetAddr.Port() == 53 ,并且经过测试(clashxpro 的测试) `dig @198.18.0.2 baidu.com -p 12345` 是没有结果的。所以应该是有一点错误的。
    CRVV
        25
    CRVV  
       2023-09-16 22:13:12 +08:00   ❤️ 1
    macOS 的 tun 只支持 point-to-point 模式,就是说你要设置一个本机的地址,再设另一个 point 的地址,然后默认情况下只有 dst 是对面地址的 ip packet 会被送到 tun 里面。198.18.0.2 就是设置的那个地址。
    这个 tun 的实现挺奇怪的,好像也可以把两个地址设成一样的。
    不能 bind .2 的原因很简单,它不是你这台机器的 ip 地址。

    “198.18.0.2 在哪里被添加成 HOST 的”
    这是 tun 实现的一部分。

    这一堆东西基本上就是在折腾 macOS 奇怪的 tun 实现,没什么意思,要真想搞明白就自己写代码创建一个 tun ,然后把路由表改一改看什么情况下会把 dst 哪里的 packet 发给 tun 。Linux 的 tun 就很正常,没这些奇怪的东西。
    gvdlmjwje
        26
    gvdlmjwje  
       2023-09-17 00:26:23 +08:00
    你用 clash 就会有
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5582 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 07:00 · PVG 15:00 · LAX 23:00 · JFK 02:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.