macOS 中是如何将 utun 网卡接口接管所有网络请求的?

2023-09-10 18:48:07 +08:00
 FaiChou

比如使用 ClashX Pro 开启了 Enhanced Mode 后,通过 ifconfig 可以看到有一个 utun10:

utun10: [
    {
      address: '198.18.0.1',
      netmask: '255.255.0.0',
      family: 'IPv4',
      mac: '00:00:00:00:00:00',
      internal: false,
      cidr: '198.18.0.1/16'
    }
]

但它是如何接管电脑上所有的网络请求的呢? ClashX Pro 是闭源的,没有办法查看源码。

通过命令 route -n get default 查看默认 route 是 en0 接口:

   route to: default
destination: default
       mask: default
    gateway: 192.168.11.1
  interface: en0
      flags: <UP,GATEWAY,DONE,STATIC,PRCLONING,GLOBAL>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1500         0

难道使用 Network Extension 中的 Packet Tunnel Provider 不需要手动设置网络的转发吗?

我所理解的过程是这样的:

  1. 新建一个 TUN 网络接口
  2. 接管系统的请求
  3. 将请求处理
  4. 处理后的接口转发到其他网络接口
  5. 收到网络请求后其他网络接口转发到 TUN 网络接口中
  6. 处理收到的网络请求
  7. 传递给上层应用

所以总结下我的问题,第二步是如何接管系统所有请求的?第四步是如何转发到其他接口的?在 Linux 中应该是需要手动写吧?在 macOS 中是用 NE 里哪一些 API ?

另外,在 iOS 端也是和 macOS 一样的吧?开启 QX 应用后,在设置中可以看到有 utun 接口。类似的应用都是用 TUN 模式的( Loon 用 TUN 和 HTTP mode 两种模式)。

2831 次点击
所在节点    macOS
28 条回复
slowmist
2023-09-11 09:22:03 +08:00
@MrGba2z 但是软件也可以不遵守规则强制使用某一个
哪个软件这么厉害?
要怎么应对?
lcdtyph
2023-09-11 09:31:33 +08:00
@slowmist
各个平台都有类似的 socket option
macos 上是 IP_BOUND_IF ,或者更简单的,直接 bind 你想使用的那个 interface 的地址再进行 connect 就行了
linux 是 SO_BINDTODEVICE

你想让 223.5.5.5 直连,setsockopt(IP_BOUND_IF) 然后 connect(223.5.5.5.5) 就行了

这样可以让 OS 做路由决策的时候忽略掉其他 interface 的路由,以此避免回环
lcdtyph
2023-09-11 09:40:38 +08:00
@slowmist
比如一些多网口负载均衡的服务就会自己 bind device ,比如 webrtc 好像会多网口同时尝试,quic 草案里也有类似的机制
要想完全避免这种情况只能上透明代理,把 clash 挪到网关上去;或者本机上防火墙规则
slowmist
2023-09-11 10:17:44 +08:00
@lcdtyph
原来是这样啊 解惑了
https://tanronggui.xyz/t/590555
不知道这哥们解决了吗

firewall 不是问题 macos 上有 pf

之前测试 google one vbn
它的 utun 会路由所有的 v4 v6
第一次遇到遇到路由 v6 的 即使本机没有 v6 地址
而且会修改 dns 到 8.8.8.8 4.4 和对应的 v6 地址
cat /etc/resolv.conf
里面是这样显示的

系统设置里面的自定义 dns 已经失效了 google 的 dns 最优先了
不知道用什么方法实现的
julyclyde
2023-09-11 10:32:41 +08:00
@FaiChou “封装后”再发出去那就是另一次发送了。另一次就独立的进行全套的路由选择
以及,eth0 并没有对应的/dev/文件
lcdtyph
2023-09-11 10:56:31 +08:00
@slowmist
我看了一下这哥们问题应该出在路由表

我没用过 google one
不过我猜它可能是直接去改的 resolv.conf 或者用 scutil 来设置的 dns
FaiChou
2023-09-11 11:54:01 +08:00
@slowmist #21 开了 clashxpro 增强,但同时 Tailscale 也开着,Tailscale 的请求貌似就不会走 clashxpro 的 utun ,而是通过路由表走自己的 utun 然后请求再发出去,这样就 bypass 了 clashxpro 。不知道我说的对不。
slowmist
2023-09-11 12:08:20 +08:00
@FaiChou 要看各自的设置和 log 了

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

https://tanronggui.xyz/t/972504

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

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

© 2021 V2EX