我在一台 Mac mini 上打开 qBittorrent,把 Network Interface 设为 utun4,重启后花了一下午盯着一个 torrent 卡在获取元数据,而 VPN 仍显示连接正常。设置本身原则上没错,是名字过期了。macOS 会在服务启动时分配 utun 编号,所以上周还正确的 utun4 指向了一条已不存在的隧道,客户端把套接字绑在了一个没有路由的设备上。下面这套顺序是我现在用的:从运行中的隧道读出接口,在客户端里选中它,重启会话,然后用一次传输和一次故意断开验证绑定。

打开高级设置,找到接口字段

在 qBittorrent 窗口里用 Cmd+, 打开首选项,进入高级页面。真正起作用的是 Network Interface 这个字段:它列出系统的接口名,默认是 Any Interface,也就是由操作系统为客户端打开的每个套接字选择路由。项目的 选项说明 记录了这个字段和该默认值,而且各平台上的设置相同,尽管里面的名字并不一样。

这里有两个细节容易出错。列表显示的是 en0、en1 以及 utun0 到 utun9 这类设备名,从不显示 VPN 服务商的产品名,所以在做出合理选择之前必须先建立对应关系。另外,选择是在 BitTorrent 会话启动时生效,而不是按下 OK 的那一刻,所以看起来已保存的改动可能仍在旧的绑定上运行。

用 Cmd+Q 正常退出程序,并在重新打开之前确认进程已经消失。只关闭窗口只是把它隐藏起来,而被隐藏的客户端仍保留会话、监听端口和旧接口。

pgrep -fl qbittorrent

找到 VPN 实际占用的接口

先通过服务商自己的客户端连接 VPN,然后读取系统的视角,而不是客户端菜单。下面的命令会列出每个接口及其地址,显示系统认为哪些处于活动状态,并打印路由表;你要找的是承载服务商分配的私有网段的那个 utun 设备。

ifconfig -a | grep -A4 '^utun'
scutil --nwi
netstat -rn -f inet | head -n 5

三项读数能告诉你哪个设备是隧道。utun 条目需要属于 VPN 地址池的 inet 地址。scutil --nwi 显示系统认为哪些接口活动、哪个是主接口。netstat -rn 显示默认路由指向哪里;如果 utun 已有地址而默认路由仍指向 en0,隧道就没有承载全部流量,这会改变绑定之后的效果。

当可能同时存在两条隧道时,例如工作配置和个人配置,两个 utun 设备都会出现,但只有一个是可用的。字节计数器能给出答案:记下计数器,加载一个页面或开始一次小传输,看哪一个在变化。

netstat -ib | grep utun

也不要认为编号是稳定的。重新连接可能给同一条隧道分配另一个 utun 名,而 iCloud 或 Continuity 服务可能在你连上 VPN 之前很久就占着 utun0。

让绑定与隧道的范围相匹配

这个字段只是把一个设备绑上去,仅此而已。如果 VPN 是把 0.0.0.0/0 全部导入 utun 的全局隧道,绑定到该设备就会让每个对等连接和每个 tracker 请求都走 VPN。 如果 VPN 是只路由少数子网的分流隧道,绑定到 utun 就会把对等流量送到一个没有对应路由的设备上,传输会停下而不是泄漏。两种结果都比 Any Interface 安全,但只有一种能让客户端继续工作。客户端之外不会改变任何东西:浏览器和其他应用各自保留路由,所以要覆盖所有应用就得从 VPN 一侧强制执行。

在选择之前先读清情况:

What you seeWhat it means for the bind
A utun with a provider address and the default route pointing at itFull tunnel; the bind covers peer and tracker traffic
A utun with a provider address but the default route still on en0Split tunnel; the bind will stall transfers unless the provider routes 0.0.0.0/0
No utun carrying a provider addressThe VPN is down or connects on demand; bring it up before selecting
A utun number that changed since the last sessionThe saved name is stale; reselect and restart

地址族也很重要。只分配 IPv4 的服务商会让被绑定的接口没有 IPv6 地址,于是 IPv6 对等连接会失败,而不是从 Wi-Fi 溜出去。另外,绑定套接字并不能固定域名解析:tracker 主机名由 macOS 解析器处理,它遵循系统的 DNS 配置,而不是所选设备。

看起来正确的选择失败的三种方式

第一种是没有重启。字段显示 utun4,首选项看起来已配置好,测试传输却仍然从 Wi-Fi 出去,因为正在运行的会话保留了旧绑定。完全退出,用 pgrep 确认,重新打开,再重新开始传输。

第二种是重新连接后的旧名字。被绑定的设备一旦消失,对等连接就会失败,客户端往往报告 tracker 错误,而不是明确提示接口已消失,看起来就像种子死了。重新读 ifconfig,选新名字,再重启。

第三种是假定绑定会以关闭方式失败。选择接口只是请系统把套接字挂到一个设备名上;这个名字缺失或被复用时会发生什么,设置界面并不保证。下一节的断开测试才是唯一算数的证据。

用真实传输和一次断开进行验证

使用你被允许运行的传输,例如某个 Linux 发行版镜像,并在 VPN 连接时开始。观察前后各接口的计数器,并与 VPN 客户端自己的数据计数比较;在对等列表填充的过程中,两者应当一起上升。

netstat -ib | grep utun
pgrep -fl qbittorrent

然后从 VPN 自己的界面断开,观察传输。对等连接应当掉线,新连接应当在隧道断开后不久失败。如果速度还在继续,说明绑定没有生效,你该回到重启这一步,而不是去查防火墙。

重新连接并再次检查所选的名字,因为隧道可能以另一个 utun 回来。记下隧道类型、接口名以及 VPN 断开时的预期行为,能为下次省事:这个设置是按机器、按服务商的,既熬不过客户端升级,也熬不过更换 VPN 应用。

相关文章