你连上了 VPN,执行了 ifconfig,并找到一条带地址的 utun4 条目。你要访问的站点仍然超时。这个落差很正常:列表只证明存在一个虚拟接口,并不证明它是你的客户端建的、你要走的路由会选中它,或者数据包真的从它出去了。我曾在一台装东西之前就已经有三条 utun 条目的笔记本上,白骂了一下午错误的隧道,从此不再相信接口名。

utun 那一行到底写的是什么

想要全貌时,执行 ifconfig -a。不带参数调用时,ifconfig 只打印当前处于启用状态的接口,所以一个启动失败的隧道可能根本不在大家贴进工单的输出里。ifconfig -l 只返回名字,这是判断连接后是否出现新 utun 的最快方法。

单个接口最值得读,已连接的隧道通常长这样。

utun4: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
    inet 10.8.0.6 --> 10.8.0.5 netmask 0xffffffff
    inet6 fe80::ce81:b1c:bd2c:69e%utun4 prefixlen 64 scopeid 0x15

三个字段给出答案。UP 和 RUNNING 说明内核愿意使用这个接口。POINTOPOINT 加上 --> 对端地址,是隧道而非物理链路的签名。mtu 值解释了一整类「能连上、然后就卡住」的报告:utun 接口通常以更小的 MTU 起来,1380 在多个 macOS 版本里都是如此,客户端还能改写它。字段清单很短,扫一遍 Apple 随系统附带的 ifconfig 手册就够了。

找出接口背后的进程

ifconfig 没有「属主应用」这个概念。两个 VPN 客户端、一个系统服务、上周遗留的一条隧道,在这个层面上产生的条目长得完全一样。在我自己的 Mac 上,utun0 到 utun3 在我安装任何东西之前就已经存在;Continuity 和 iCloud Private Relay 也用隧道,它们都不是你在排查的那条连接。

对于向系统注册配置的隧道,scutil --nc list 是最快的对应办法,它会列出每份配置的状态和服务 ID,已连接的会标出来。

scutil --nc list
* (Connected)   5F2A9C10-...   VPN  Work IKEv2

不注册配置、自己跑隧道进程的客户端根本不会出现在那里。Tunnelblick 和命令行里的openvpn 实例都属于这一类,所以还要查进程表:ps -Ao pid,comm | grep -i openvpn。一条进程拥有隧道之后,utun 编号只属于它。

先测地址,再测路由

接口可以在没有可用地址的情况下启用。只有 IPv6 的配置只显示一条链路本地fe80:: 条目,inet 那一行什么都没有,推送地址没应用成功的客户端留下的形状一模一样。如果目标是 IPv4,而隧道没有 IPv4 地址,路由问题就已经有答案了。

MTU 值得单独检查,因为这个故障不像大小问题。它像是认证通过了,可一旦大传输开始就安静下来。发一个不允许分片的探测包,大小让整包正好匹配接口 MTU;MTU 为 1400 时负载是 1372 字节:

ping -D -s 1372 10.8.0.5

有回应,说明这个大小的包确实穿过隧道。小 ping 正常却沉默,指向 MTU 或路径上丢 ICMP 的某处,而不是认证——认证在拿到接口之前就完成了。

证明目标确实选中了隧道

要紧的问题不是utun4 是否存在,而是发往某个特定地址的流量是否真的从它出去。route -n get 能为单个目的地回答这一点,并打印它会用到的网关和接口:

route -n get 203.0.113.20
  gateway: 10.8.0.5
  interface: utun4

如果同一条命令报的是en0,说明你的 split tunneling 配置就是在按吩咐办事,再怎么翻接口也不会变。netstat -rn -f inet 用在你需要默认路由和整张表一屏看全的时候。

包到底动没动,由计数器说了算。netstat -ib 按接口报告包数和字节数,utun 条目也在内;数字是累计的,隔一会儿读两次再比:

netstat -ib | grep utun4

应用一直重试而计数器不动,说明内核从没把包交给接口。应用照样失败而计数器两个方向都在涨,就把排查推到隧道的另一端。

当 utun 根本不出现

一次看起来成功的登录之后接口列表却是空的,通常说明隧道根本没起来,而不是ifconfig 把它藏了。先看客户端自己的状态,再看系统的:一个从没被批准的 Network Extension,或者更新后被 macOS 关掉的,都不会留下接口。批准项在「系统设置」的「登录项与扩展」里,那里如果是旧条目,值得在重装任何东西之前先关开一次。

utun 的编号在重连之间并不稳定。你完全可能在utun5 十分钟前的位置上拿到utun4 一个新的编号,因为旧接口被拆掉,内核把下一个空闲索引发了出来。把名字写死的脚本会在那一刻悄悄坏掉;改成按地址或按路由去匹配。

读取这一侧保持只读。sudo ifconfig utun4 down 会中断隧道,在全局隧道配置上还会顺手带走你的远程会话——你本来只是想收集证据,这笔交易很差。这里需要的东西没有一样要 root:读标志、地址和计数器,普通用户就能做。

下次 Mac 隧道再闹脾气,按顺序做这几步:用ifconfig -l 确认 utun 出现了,读它的标志、地址和 MTU,把它归到某个进程,问route -n get 目标走的是哪个接口,然后盯着netstat -ib 动没动。每一步排除一层,第一个不对的地方就该动手修。

相关文章