Skip to Main Content
after close VPN, analyze why no NetBack to Top

after close VPN, analyze why no Net

6 minutes

tl; dr => 通用解决方案

前置知识

VPN原理 VPN 改动 DNS服务器地址 虚拟DNS 服务器, 所有的 DNS请求都会走虚拟DNS服务器, 相当于 代理工具 接管系统DNS服务器,再由 虚拟DNS服务器 处理 发往真正的DNS服务器 关闭代理工具, 但 虚拟DNS服务器 按理来说是不存在,应当消失, 回归 系统DNS服务器;

该问题触发场景

日常使用 时 尽量 避免

  1. VPN不关闭 且 < 熄屏 或 休眠 太久> 重新打开
  2. 多个DNS软件 同时使用 ( Adguard,VPN, 等)覆写DNS时 被其他软件 接管或中断
  3. 小众VPN 套壳Clash 是老版本, MacOS 新版本中 网络模块没有相应的 补丁修复 Github 上 有相关的issue

优化点:

  1. VPN 用完就关
  2. 尽量使用 小火箭 QX Surge 等及时 更进 系统更新 有网络补丁 和 协议支持的 软件
  3. Install TraceBar

没有遥测数据,没有分析数据,也没有账户。所有数据都保存在内存中,退出后就会丢失
可视化示数据通过互联网传输到目的地的路径,并显示沿途的任何网络问题。 它可以帮助您诊断和定位网络问题,从而确定是您的 Wi-Fi 故障、互联网连接故障、网络服务提供商故障,还是其他原因导致的 同类 专业级软件:Pingplotter

brew tap tracebar-app/tracebar && brew install --cask tracebar

常用命令

# 查看当前DNS服务器地址
cat /etc/resolv.conf
scutil --dns  

# 查看默认的DNS服务器
scutil --dns | grep nameserver

# 路由信息查看
netstat -r

# DNS 解析域名
dig @[DNS服务器] [域名]

连接VPN 前


 cat /etc/resolv.conf                                  ─╯
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 192.168.231.1
nameserver 192.168.1.1

DNS 指向局域网网关 192.168.231.1192.168.1.1

scutil --dns                                          ─╯
DNS configuration

resolver #1
  nameserver[0] : 192.168.231.1
  nameserver[1] : 192.168.1.1
  if_index : 7 (en0)
  flags    : Request A records
  reach    : 0x00000002 (Reachable)

resolver #2
  domain   : local
  options  : mdns
  timeout  : 5
  flags    : Request A records
  reach    : 0x00000000 (Not Reachable)
  order    : 300000

resolver #3
  domain   : 254.169.in-addr.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records
  reach    : 0x00000000 (Not Reachable)
  order    : 300200

resolver #4
  domain   : 8.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records
  reach    : 0x00000000 (Not Reachable)
  order    : 300400

resolver #5
  domain   : 9.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records
  reach    : 0x00000000 (Not Reachable)
  order    : 300600

resolver #6
  domain   : a.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records
  reach    : 0x00000000 (Not Reachable)
  order    : 300800

resolver #7
  domain   : b.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records
  reach    : 0x00000000 (Not Reachable)
  order    : 301000

DNS configuration (for scoped queries)

resolver #1
  nameserver[0] : 192.168.231.1
  nameserver[1] : 192.168.1.1
  if_index : 7 (en0)
  flags    : Scoped, Request A records
  reach    : 0x00000002 (Reachable)
 scutil --dns | grep nameserver                        ─╯
  nameserver[0] : 192.168.231.1
  nameserver[1] : 192.168.1.1
  nameserver[0] : 192.168.231.1
  nameserver[1] : 192.168.1.1

说明 DNS …

连接VPN 后

 cat /etc/resolv.conf                                  ─╯
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 198.18.0.2

DNS 依然被锁定在 198.18.0.2(这通常是 Clash 等代理/VPN 工具使用的 Fake IP 或者是其内置 TUN 模式的 DNS 服务地址) 前后比对,DNS解析地址 被替换, 路由信息被更新“ 当 VPN 关闭后,这个 IP 变得不可达,导致你的 Mac 无法解析任何域名,从而“断网”。

命令方式解析 dig @[DNS服务器] [域名]

dig @114.114.114.114 www.baidu.com

一、 命令行定位与分析步骤 既然怀疑是 DNS 问题,我们可以通过以下命令行组合进行精准排查:

  1. 验证是否只是 DNS 解析失败(排除物理断网) 在终端中尝试直接 ping 一个公网 IP(如 Google 或 腾讯的公共 DNS),再 ping 一个域名:

ping -c 3 114.114.114.114
ping -c 3 baidu.com

分析: 如果 ping 114.114.114.114 能通,但 ping baidu.com 提示 cannot resolve baidu.com: Unknown host,说明网络连接完全正常,100% 是 DNS 的锅。

  1. 查看 macOS 真正的 DNS 配置 正如你截图中 macOS 自带的警告所说,macOS 并不真正依赖 /etc/resolv.conf,它有自己的系统配置框架(Configuration Daemon)。 执行以下命令查看当前生效的 DNS:
scutil --dns

分析: 检查输出中的 nameserver[0]。你会发现即使关闭了 VPN,这里可能依然残留着 198.18.0.2。这是因为 VPN 客户端退出时,未能正常调用系统 API 将修改的 DNS 还原。

  1. 查看网络服务(以 Wi-Fi 为例)的硬件 DNS 设置
networksetup -getdnsservers Wi-Fi

分析: 如果这里输出了 198.18.0.2 或提示存在特定的 DNS,说明 VPN 直接修改了你网卡的硬配置。如果输出 There aren’t any DNS Servers set on Wi-Fi.,说明走的是 DHCP 自动获取(这是正常的,不正常的配置残留在内存的 scutil 守护进程中)。

 ping -c 3 114.114.114.114                                                                ─╯
PING 114.114.114.114 (114.114.114.114): 56 data bytes
64 bytes from 114.114.114.114: icmp_seq=0 ttl=64 time=3.109 ms
64 bytes from 114.114.114.114: icmp_seq=1 ttl=64 time=1.630 ms
64 bytes from 114.114.114.114: icmp_seq=2 ttl=64 time=1.009 ms

--- 114.114.114.114 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.009/1.916/3.109/0.881 ms

 ~ ────────────────────────────────────────────────────── system Node at 08:45:41 AM ─╮
 ping -c 3 baidu.com                                                                      ─╯
PING baidu.com (124.237.177.164): 56 data bytes
64 bytes from 124.237.177.164: icmp_seq=0 ttl=64 time=4.223 ms
64 bytes from 124.237.177.164: icmp_seq=1 ttl=64 time=1.734 ms
64 bytes from 124.237.177.164: icmp_seq=2 ttl=64 time=0.817 ms

--- baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.817/2.258/4.223/1.439 ms

 ~ ────────────────────────────────────────────────────── system Node at 08:45:49 AM ─╮
 scutil --dns                                                                             ─╯
DNS configuration

resolver #1
  nameserver[0] : 198.18.0.2
  if_index : 24 (utun11)
  flags    : Supplemental, Request A records, Request AAAA records
  reach    : 0x00000003 (Reachable,Transient Connection)
  order    : 102200

resolver #2
  nameserver[0] : 198.18.0.2
  if_index : 24 (utun11)
  flags    : Request A records, Request AAAA records
  reach    : 0x00000003 (Reachable,Transient Connection)
  order    : 200000

resolver #3
  domain   : local
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300000

resolver #4
  domain   : 254.169.in-addr.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300200

resolver #5
  domain   : 8.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300400

resolver #6
  domain   : 9.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300600

resolver #7
  domain   : a.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300800

resolver #8
  domain   : b.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 301000

DNS configuration (for scoped queries)

resolver #1
  nameserver[0] : 192.168.231.1
  nameserver[1] : 192.168.1.1
  if_index : 7 (en0)
  flags    : Scoped, Request A records
  reach    : 0x00000002 (Reachable)

resolver #2
  nameserver[0] : 198.18.0.2
  if_index : 24 (utun11)
  flags    : Scoped, Request A records, Request AAAA records
  reach    : 0x00000003 (Reachable,Transient Connection)

 ~ ────────────────────────────────────────────────────── system Node at 08:45:55 AM ─╮
 ping baidu.com                                                                           ─╯





 ~ ──────────────────────────────────── INT took 7s system Node at 08:49:05 AM ─╮
                                                                                          ─╯
cat /etc/resolv.conf
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 192.168.231.1
nameserver 192.168.1.1

 ~ ────────────────────────────────────────────────────── system Node at 08:49:16 AM ─╮
 ping baidu.com                                                                           ─╯
^C

 ~ ──────────────────────────────────── INT took 6s system Node at 08:49:28 AM ─╮
 dig @192.168.231.1 www.baidu.com                                                         ─╯
;; communications error to 192.168.231.1#53: timed out
;; communications error to 192.168.231.1#53: timed out
;; communications error to 192.168.231.1#53: timed out

; <<>> DiG 9.20.24 <<>> @192.168.231.1 www.baidu.com
; (1 server found)
;; global options: +cmd
;; no servers could be reached

 ~ ─────────────────────────────────────────── took 15s  system Node  at 08:49:59 AM ─╮
❯                                                                                          ─╯
cat /etc/resolv.conf
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 192.168.231.1
nameserver 192.168.1.1

 ~ ────────────────────────────────────────────────────── system Node  at 08:52:48 AM ─╮
❯ ping -c 3 192.168.231.1                                                                  ─╯
PING 192.168.231.1 (192.168.231.1): 56 data bytes
64 bytes from 192.168.231.1: icmp_seq=0 ttl=63 time=4.427 ms
64 bytes from 192.168.231.1: icmp_seq=1 ttl=63 time=1.954 ms
64 bytes from 192.168.231.1: icmp_seq=2 ttl=63 time=2.018 ms

--- 192.168.231.1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.954/2.800/4.427/1.151 ms

 ~ ────────────────────────────────────────────────────── system Node  at 08:52:54 AM ─╮
❯ netstat -nr | grep default                                                               ─╯
default            192.168.1.1        UGScg                 en0
default                                 fe80::%utun0                            UGcIg               utun0
default                                 fe80::%utun1                            UGcIg               utun1
default                                 fe80::%utun2                            UGcIg               utun2
default                                 fe80::%utun3                            UGcIg               utun3
default                                 fe80::%utun12                           UGcIg              utun12
default                                 fe80::%utun13                           UGcIg              utun13

 ~ ────────────────────────────────────────────────────── system Node  at 08:53:20 AM ─╮
❯ sudo route -n delete default 192.168.1.1                                                 ─╯
Password:
delete net default: gateway 192.168.1.1

 ~ ──────────────────────────────────────────── took 4s  system Node  at 08:56:11 AM ─╮
❯ sudo route -n add default 192.168.231.1                                                  ─╯
add net default: gateway 192.168.231.1

 ~ ────────────────────────────────────────────────────── system Node  at 08:56:25 AM ─╮
❯ cat /etc/resolv.conf                                                                     ─╯
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 192.168.231.1
nameserver 192.168.1.1

 ~ ────────────────────────────────────────────────────── system Node  at 08:58:04 AM ─╮
❯ netstat -nr | grep default                                                               ─╯
default            192.168.1.1        UGScg                 en0
default                                 fe80::%utun0                            UGcIg               utun0
default                                 fe80::%utun1                            UGcIg               utun1
default                                 fe80::%utun2                            UGcIg               utun2
default                                 fe80::%utun3                            UGcIg               utun3
default                                 fe80::%utun12                           UGcIg              utun12
default                                 fe80::%utun13                           UGcIg              utun13

 ~ ────────────────────────────────────────────────────── system Node  at 08:58:14 AM ─╮
❯ sudo route -n delete default 192.168.1.1                                                 ─╯
delete net default: gateway 192.168.1.1

 ~ ────────────────────────────────────────────────────── system Node  at 08:58:23 AM ─╮
❯ sudo route -n add default 192.168.231.1                                                  ─╯
route: writing to routing socket: Network is unreachable
add net default: gateway 192.168.231.1: Network is unreachable

 ~ ────────────────────────────────────────────────────── system Node  at 08:58:31 AM ─╮
❯ cat /etc/resolv.conf                                                                     ─╯
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 192.168.231.1
nameserver 192.168.1.1

 ~ ────────────────────────────────────────────────────── system Node  at 08:58:40 AM ─╮
❯ netstat -nr | grep default                                                               ─╯
default                                 fe80::%utun0                            UGcIg               utun0
default                                 fe80::%utun1                            UGcIg               utun1
default                                 fe80::%utun2                            UGcIg               utun2
default                                 fe80::%utun3                            UGcIg               utun3
default                                 fe80::%utun12                           UGcIg              utun12
default                                 fe80::%utun13                           UGcIg              utun13

❯ ping -c 3 192.168.231.1 ─╯

PING 192.168.231.1 (192.168.231.1): 56 data bytes

64 bytes from 192.168.231.1: icmp_seq=0 ttl=63 time=4.427 ms

64 bytes from 192.168.231.1: icmp_seq=1 ttl=63 time=1.954 ms

64 bytes from 192.168.231.1: icmp_seq=2 ttl=63 time=2.018 ms

— 192.168.231.1 ping statistics —

3 packets transmitted, 3 packets received, 0.0% packet loss

round-trip min/avg/max/stddev = 1.954/2.800/4.427/1.151 ms

 ~ ────────────────────────────────────────────────────── system Node  at 08:52:54 AM ─╮

❯ netstat -nr | grep default ─╯

default 192.168.1.1 UGScg en0

default fe80::%utun0 UGcIg utun0

default fe80::%utun1 UGcIg utun1

default fe80::%utun2 UGcIg utun2

default fe80::%utun3 UGcIg utun3

default fe80::%utun12 UGcIg utun12

default fe80::%utun13 UGcIg utun13

破案了!这是一起非常典型的多网卡/双网关路由冲突引发的“高级故障”。

你的测试结果给出了最关键的线索:

ping 192.168.231.1 可以通,说明物理链路和该网段是通的。

netstat -nr | grep default 暴露了致命问题:你的 IPv4 默认网关(default)指向的是 192.168.1.1,走的是 en0 接口。

一、 深度原理分析:为什么会断网?
回到你上一张图的 /etc/resolv.conf:

Plaintext
nameserver 192.168.231.1
nameserver 192.168.1.1
你当前系统里其实并存了两个物理网络(或者一个多网段的复杂网络),一个是 192.168.231.x,另一个是 192.168.1.x。

数据包的迷路过程:
当你执行 dig @192.168.231.1 www.baidu.com 时,系统查路由表发现,要前往 192.168.231.1 不需要走默认网关,因为它属于本地直连网段。
但是,你的默认路由(负责所有外网流量)被死死绑定在了 192.168.1.1 上。当 VPN 关闭后,192.168.1.1 这个网关可能根本没有通往外网的权限,或者它是个死网关。

总结: 你的 Mac 目前误把没有外网能力的 192.168.1.1 当作了主力出口,而把真正能上网的 192.168.231.1 晾在了一边。

二、 命令行解决方案
我们需要明确告诉 macOS:把外网出口(默认网关)切换回 192.168.231.1。

步骤 1:手动修正 IPv4 默认路由
强行删除错误的 192.168.1.1 默认网关,并指向正确的 192.168.231.1:

Bash
# 1. 删除当前指向 192.168.1.1 的默认路由
sudo route -n delete default 192.168.1.1

# 2. 添加真正能上网的 192.168.231.1 作为默认网关
sudo route -n add default 192.168.231.1
步骤 2:彻底清除残留的 utun 虚拟接口路由(可选)
你的输出中有一大堆 utun0 到 utun13 的 IPv6 残留。虽然它们是 IPv6,但为了防止干扰,可以直接让网络服务重新加载:

Bash
# 触发网络接口配置更新(将 en0 软重启)
sudo ifconfig en0 down && sudo ifconfig en0 up
步骤 3:调整 macOS 网络服务优先级(长久之计)
如果你的 Mac 同时连接了多个网络接口(比如 Wi-Fi 和以太网,或者两个不同的虚拟网络),你需要让提供 192.168.231.x 的那个接口在系统里处于最高优先级。

先查看你所有的网络服务名称:

Bash
networksetup -listnetworkserviceorder
假设你的以太网叫 USB 10/100/1000 LAN,Wi-Fi 叫 Wi-Fi。如果你希望以太网优先,可以使用以下命令调整顺序(把你希望优先的服务写在最前面):

Bash
# 示例命令,请根据你上一步查到的实际名称修改
sudo networksetup -ordernetworkservices "USB 10/100/1000 LAN" "Wi-Fi" "Bluetooth PAN"
三、 验证网络
完成路由调整后,请再次测试:

Bash
# 1. 再次检查默认网关是否已变为 192.168.231.1
netstat -nr | grep default

# 2. 测试域名解析
dig www.baidu.com

# 3. 测试外网是否畅通
ping -c 3 baidu.com



当 VPN 关闭后发生断网,其根本原因通常是 VPN 软件未能干净地撤销它对系统网络栈(DNS、路由表、虚拟网卡、防火墙)的接管。按照一个标准的数据包从“域名解析”到“物理网卡发出”的 正常网络访问链路,我们可以从上到下、由表及里地梳理出一套完整的命令行(CLI)排查与验证指南。🌐 正常网络访问链路排查总览为了方便记忆,排查链路分为以下 5 个核心节点:应用层/DNS 映射(/etc/resolv.conf)系统 DNS 解析引擎(mDNSResponder / scutil)网络层路由转发(netstat / route)链路层/物理网卡状态(ifconfig / networksetup)系统防火墙与流量拦截(pfctl)🛠️ 各链路节点排查与命令总结节点 1:配置文件层(检查基础 DNS 地址)数据包发出的第一步,是检查系统基础的域名解析服务器指向。查看命令:Bashcat /etc/resolv.conf
异常表现: nameserver 后面依然残留 VPN 的私有 DNS(如 198.18.0.2 等 Fake IP 映射地址)。正常表现: 应该指向你的局域网网关(如 192.168.1.1)或公共 DNS(如 114.114.114.114)。节点 2:系统 DNS 解析层(检查实际 DNS 路由与解析能力)macOS 并不直接依赖上一步的配置文件,而是通过配置画布(Configuration Daemon)管理。查看实际生效 DNS:Bashscutil --dns
检查 nameserver[0] 是否为有效的外网 DNS。测试指定 DNS 接口解析:Bash# 强制使用你本地的网关(如 192.168.231.1)去解析外网域名
dig @192.168.231.1 www.baidu.com
测试系统默认 DNS 解析:Bashdig www.baidu.com
异常表现: dig 提示 timed out 或 no servers could be reached(即使网关能 ping 通)。此节点修复命令(刷新 DNS 缓存):Bashsudo killall -HUP mDNSResponder
节点 3:网络层路由转发(检查默认网关)DNS 解析成功(或直接访问 IP)后,数据包需要知道从哪一个“出口”发往外网。查看全局路由表(特别是默认网关):Bashnetstat -nr | grep default
测试物理网关的连通性:Bash# 替换为你实际的网关 IP
ping -c 3 192.168.231.1
异常表现: 1. 存在多个 default 路由,导致路由冲突。2. default 错误的指向了已关闭的 VPN 虚拟网卡(如 utunX),或者指向了一个没有外网能力的死网关(如多网卡环境下的错误内网网关)。此节点修复命令(重置默认路由):Bash# 删除错误的网关,并添加正确的物理网关
sudo route -n delete default 192.168.1.1
sudo route -n add default 192.168.231.1
节点 4:链路层与硬件接口(检查物理网卡状态)确保你的物理网卡(以太网/Wi-Fi)处于激活状态,且获得了正确的 IP 分配。查看所有网络接口状态:Bashifconfig
检查你的物理网卡(如 en0)是否带有 status: active 以及正确的 inet (IP 地址)。查看硬件端口与服务的绑定关系:Bashnetworksetup -listallhardwareports
此节点修复命令(网卡软重启/重新触发 DHCP):Bash# 以 en0 为例,先禁用再启用,强制重新向路由器申请 IP 和路由
sudo ifconfig en0 down && sudo ifconfig en0 up
节点 5:防火墙与安全策略层(检查流量拦截)很多现代 VPN 软件(如 Clash 增强模式、Surge、Tailscale 等)会写入内核级别的防火墙(PF)转发规则。软件关闭时如果未清理,会把所有非 VPN 流量直接丢弃(Drop)。查看防火墙状态与规则:Bashsudo pfctl -s rules
异常表现: 存在大量指向 127.0.0.1 或是虚拟网卡的 redirect (rdr) 转发规则。此节点修复命令(强制关闭 PF 防火墙拦截):Bashsudo pfctl -d
📋 快速排查口诀表排查顺序检查目标核心 CLI 命令正常标准Step 1配置文件cat /etc/resolv.confnameserver 为物理网关或公网 DNSStep 2DNS 解析dig www.baidu.com能正确返回 A 记录(IP 地址)Step 3路由网关netstat -nr | grep defaultdefault 唯一且指向真正能上网的物理网关Step 4物理链路ping -c 3 [网关IP]0% packet loss(延迟通常在几毫秒内)Step 5流量拦截sudo pfctl -d彻底关闭可能残留的防火墙拦截规则


终极病灶分析:什么是 link#27?
看看你之前的路由表输出:

Plaintext
default            link#27            UCSg                utun16
在 macOS 中,link#X(如 link#27)代表的是系统内核直接绑定的链路层接口(Link-layer Interface)。
当 VPN 软件(特别是开启了 TUN 模式、Enhance 模式或智能路由的客户端)运行时,它会在内核中创建一个名为 utun16 的虚拟网卡,并把全局默认路由的下一跳直接绑死在物理链路 link#27 上。

这就是为什么你断开 VPN 后依然无法访问的原因:
普通的 sudo route delete default 只能删除常规的 IP 路由,但这种由 VPN 强行写入内核、绑定在 link# 上的链路层条件路由(UCSg 标记)具有极高的优先级,它像胶水一样粘在系统里。即使你以为 VPN 关了,系统在发送 SSH 数据包时,依然通过 link#27 丢给了已经失效的 utun16,导致 Codeberg 的服务器直接断开或根本收不到正确的握手包。

🛠️ 终极命令行解决方案
我们必须用点“暴力”手段,将这些残留的虚拟网卡接口和内核路由彻底抹去。

步骤 1:强行卸载/关停残留的 utun16 接口
既然流量总是被吸进 utun16,我们直接在链路层把它禁用:

Bash
sudo ifconfig utun16 down
(如果执行后路由表里还有别的 utunX 占领 default,可以针对性地将其 down 掉)

步骤 2:强制刷新 macOS 内核路由表(终极重置)
既然常规命令删不掉 link#27,我们直接通过重启 macOS 网络核心配置框架,逼迫系统重新扫描物理网卡:

Bash
# 1. 强制清理并重置系统的网络配置守护进程(这会顺便冲刷掉内核残留的 link 路由)
sudo configd -b -d

# 2. 软重启你的物理网卡 en0,让它重新拿回唯一的 default 控制权
sudo ifconfig en0 down && sudo ifconfig en0 up
步骤 3:验证路由表是否恢复纯净
现在执行以下命令,观察输出:

Bash
netstat -nr | grep default
【正确标准】: 此时输出应该有且只有一行,且必须指向你的物理网关,绝对不能再出现 link# 或 utun:

Plaintext
default            192.168.1.1        UGSc           en0
🧪 最终验证
当路由表被彻底清洗干净,只剩下物理网卡 en0 后,再次发起冲击:

Bash
ssh -vT git@codeberg.org
这一次,数据包终于能顺着真正的物理网线飞往 Codeberg 了!




从这份最新的路由表来看,你的 IPv4 路由表现在是非常干净且正确的:

只有一个 IPv4 默认网关 default 指向 192.168.1.1,并且成功绑定在物理网卡 en0 上。

之前残留的 link#27 和 utun16 的 IPv4 拦截已经彻底消失了。

剩下的 utun0 到 utun13 都是 IPv6 的本地链路多播路由(fe80:: 开头),属于 macOS 的正常系统组件(或 OrbStack 的内部通信),不会影响你的 IPv4 外网访问。

既然 IPv4 路由表已经完全正常,为什么 ssh -vT git@codeberg.org 依然卡在 kex_exchange_identification?

这就排除了路由表的嫌疑,问题被锁死在以下两个最后可能的原因:

🔍 终极原因定位与验证
1. 终端的环境变量中残留了代理
虽然你的 VPN 软件关闭了,路由也清干净了,但如果你当前使用的这个终端窗口是在关闭 VPN 之前打开的,它里面可能依然保留着旧的 ALL_PROXY 或 HTTP_PROXY 环境变量。SSH 会尝试去走这个已经死掉的代理端口,导致连接直接被挂断。

验证与解决命令:
在当前终端直接执行以下命令,清空所有可能的代理变量:

Bash
unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY
或者,直接新开一个全新的终端标签页(Terminal Tab)来测试。

2. 运营商或本地宽带网络对 Codeberg 的 22 端口进行了封锁
Codeberg(217.197.84.140)的服务器在海外。在不挂 VPN 的纯国内物理网络下,部分地区的运营商(如移动、长城宽带等)常常会直接拦截或干扰境外非主流 Git 平台的 22 端口(SSH 握手包被审查直接阻断)。

验证命令(测试 22 端口是否能正常建立流传输):

Bash
nc -vzt codeberg.org 22
或者使用带有探测性质的 curl:

Bash
curl -v ssh://codeberg.org:22
分析: 如果执行 nc 很久没反应,或者显示 Connection refused,说明你的物理宽带网络在没有 VPN 的情况下,本身就无法直接连接 Codeberg 的 SSH 服务。

🛠️ 终极解决方案
如果你清空了环境变量(或换了新终端),并且发现不挂 VPN 就是连不上 Codeberg 的 22 端口,请使用以下两个终极对策:

对策 A:使用 Codeberg 官方提供的 SSH 备用端口(443)
为了应对 22 端口被防火墙或运营商封锁的情况,Codeberg 官方支持通过 443 端口(通常用于 HTTPS,不易被封)来走 SSH 协议。

修改你的 ~/.ssh/config,将 codeberg 的配置改成这样:

Plaintext
Host codeberg.org
    HostName altssh.codeberg.org
    User git
    Port 443
    IdentityFile ~/.ssh/id_ed25519_codeberg
    IdentitiesOnly yes
修改完后,直接测试:

Bash
ssh -vT git@codeberg.org
这个方法非常有效,它依然走的是你的 SSH 密钥认证,但完美绕过了被运营商封锁的 22 端口。

对策 B:切换为 HTTPS 协议克隆/推送
如果 SSH 无论如何都不通,最省心的办法就是放弃 SSH 协议,改用 HTTPS 协议(通过 Codeberg 的账号 + Token/密码)进行代码管理:

Bash
# 修改你本地 Git 仓库的远程连接地址为 HTTPS
git remote set-url origin https://codeberg.org/你的用户名/你的仓库名.git


❯ ping baidu.com                               ─╯
ping: cannot resolve baidu.com: Unknown host

 ~ 
❯ cat /etc/resolv.conf                         ─╯
#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 223.5.5.5

 ~ ────────── system Node  at 10:39:09 AM ─╮
❯ dig @223.5.5.5 www.baidu.com                 ─╯
;; communications error to 223.5.5.5#53: timed out
;; communications error to 223.5.5.5#53: timed out
;; communications error to 223.5.5.5#53: timed out

; <<>> DiG 9.20.24 <<>> @223.5.5.5 www.baidu.com
; (1 server found)
;; global options: +cmd
;; no servers could be reached

现在的问题和之前的 Hosts 已经没有关系了。这就是最典型、最致命的 “VPN 关闭/残留引发的系统全局 DNS 死锁”。

看这三个连续的致命报错:

Could not resolve host: mirrors.aliyun.com(连国内的阿里云都无法解析)

ping: cannot resolve baidu.com: Unknown host(百度无法解析)

dig @223.5.5.5 www.baidu.com ... timed out(直接向阿里公共 DNS 53端口发包全完超时)

🔍 根源分析:你的 Mac 经历了什么?
虽然你的 /etc/resolv.conf 里写着 nameserver 223.5.5.5,但因为你之前开启过 VPN(TUN 模式、增强模式或系统代理),VPN 在断开或者关闭时,没有干净地把接管的系统底层路由表(Routing Table)和虚拟网卡(utun)卸载掉。

导致的结果是:你的 Mac 依然盲目地把所有 DNS 流量(53端口)丢给一个已经不存在的 VPN 虚拟网关,导致你现在连国内网络、DNS 服务器全部失联。

强行重置 macOS 网络层

# 🛠️ 针对以太网的终极修复步骤
## 找出你当前以太网的准确“服务名称”
不同的扩展坞,以太网在系统里的名字不一样。我们先用这个命令列出你所有的网络接口:

```Bash
networksetup -listallnetworkservices

❯ networksetup -listallnetworkservices                                                           ─╯

An asterisk (*) denotes that a network service is disabled.
Ethernet
Thunderbolt Bridge
Wi-Fi
Shadowrocket

看一眼输出结果:

你会看到类似 AX88179A、USB 10/100/1000 LAN、Thunderbolt Ethernet 或 Ethernet 的名字。请记住这个名字(下面以 Ethernet 为例,如果你的叫别的,请自行替换)。

通用解决方案

网络环境描述:关闭VPN 软件; 网络保留一种(有线或无线)简化排查和解决难度
方案 默认使用有线网络Ethernet , 根据你自己的 网络 微调

强行给以太网注入国内骨干 DNS

用官方命令强行把你的有线网络 DNS 冲刷干净,彻底摆脱 VPN 残留:

# "Ethernet"
sudo networksetup -setdnsservers "Ethernet" 223.5.5.5 119.29.29.29

物理层重启以太网卡(重洗路由表)

我们需要让你的有线网卡重新向路由器申请一次内网 IP 和网关。

查明以太网的物理设备名:

networksetup -listallhardwareports
找到你以太网服务对应的 Device(比如 en0 en2)。

强行断开并重启该网卡:

Bash
# 是 en0
sudo ifconfig en0 down && sudo ifconfig en0 up

# 定位到是en0
 networksetup -listallhardwareports                                                             ─╯


Hardware Port: Ethernet
Device: en0
Ethernet Address: d0:11:e5:8a:4f:6c

Hardware Port: Ethernet Adapter (en5)
Device: en5
Ethernet Address: 9a:86:59:a9:af:e2

Hardware Port: Ethernet Adapter (en6)
Device: en6
Ethernet Address: 9a:86:59:a9:af:e3

Hardware Port: Ethernet Adapter (en7)
Device: en7
Ethernet Address: 9a:86:59:a9:af:e5

Hardware Port: Thunderbolt Bridge
Device: bridge0
Ethernet Address: 36:fd:e1:09:fc:c0

Hardware Port: Wi-Fi
Device: en1
Ethernet Address: d0:11:e5:79:c5:4f

Hardware Port: Thunderbolt 1
Device: en2
Ethernet Address: 36:fd:e1:09:fc:c0

Hardware Port: Thunderbolt 2
Device: en3
Ethernet Address: 36:fd:e1:09:fc:c4

Hardware Port: Thunderbolt 4
Device: en4
Ethernet Address: 36:fd:e1:09:fc:cc

VLAN Configurations
===================

瞬间冲刷全网 DNS 缓存

sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

🧪 验证网络

现在,拔掉再重新插一下你的以太网网线,让它亮起绿灯。然后再次在终端测试:
该步骤 不可省略, 有时就是这步没有操作

ping -c 3 baidu.com

dig @223.5.5.5 www.baidu.com

只要 ping 能够通,你的系统网络就彻底复活了!

Read Also