OpenVPN 显示已连接却没有任何流量,这句话背后至少对应五种互不相关的故障。在不知道哪一层失败之前就改防火墙规则,只会让未知数翻倍,把烂摊子留给下一位工程师。正确的做法是从进程往外查,因为下面每一步要么排除一个环节,要么把丢包位置缩得更小。这里的顺序很重要:在还不知道绑定的是哪个地址时抓包,只能证明某种情况,却证明不了你需要的那一种。

套接字要么已绑定,要么没有

服务报告为活动状态,仍可能绑定在你从未设想的地址或传输协议上。直接查询套接字本身:ss -lunp 列出 UDP 监听,ss -ltnp 列出 TCP,值得看的列是本地地址而不是状态。

空结果通常意味着三种情况之一:进程启动后就退出、加载了另一份配置文件,或者监听的地址与拨号的目标不一致。

ss -lunp | grep 1194
ss -ltnp | grep 1194

local 指令把监听固定在一个地址上,因此同一台主机上指向别处的客户端会被拒绝,而服务从外面看仍然健康。实例名也可能 指向一个你从未编辑过的文件,这在同时运行两套配置的主机上很常见。

抓外层报文,而不是隧道

在物理接口和真实端口上过滤,把接口换成你自己的:tcpdump -ni eth0 udp port 1194。出方向报文没有回音,说明问题在上游:运营商过滤、NAT 设备,或者你以为的那个远端地址并不是它。两个方向都静默,说明是客户端路由或本机防火墙。能收到回包但隧道没有进展,说明问题在控制通道,也就是密钥或加密算法不匹配,而不是过滤。

两个方向都要抓,并且让抓包文件保持简短。长时间的抓包会把关键的那三秒埋掉,而答案几乎总是在第一次交换里。

先看计数器,只有计数器说不清时才动跟踪

从计数器开始,因为它不花成本。nft list ruleset 或 iptables -L -n -v 会回答这里唯一重要的问题:规则到底命中没有?顺序决定结果,因为先匹配者生效,这就是为什么在后面 ACCEPT 之前放一条宽泛 DROP 会让那个 ACCEPT 形同虚设,也是为什么追加规则很少能真正修好什么。

属主身份同样会让人踩坑。内核把本机生成的报文归给打开套接字的那个进程,而 OpenVPN 通常以 root 运行,因此绑定普通用户 ID 的规则永远看不到隧道自身的流量。在断定规则有错之前,先确认属主 UID。

只有当计数器仍然含糊时,日志才值得制造噪音,而且只针对很窄的一段:用 iptables 规则限速并给日志行加前缀,或者用带 meta nftrace set 1 的 nftables 规则配合 nft monitor trace 运行。跟踪会说出接受或丢弃报文的那条链和规则。事后把两者都撤掉,别把载荷记录也留在里面。

传输协议也要一并检查。只针对 TCP 的防火墙服务,对同号端口上的 UDP 监听毫无约束,所以读起来正确的规则照样可能丢光所有报文。

路由与回程

报文被接受了却仍然消失,就要检查它的目的路径。ip route get 会报告针对某个地址选出的路由,而反向路径过滤可能丢掉从主表永远不会选择的接口进来的回包。症状看起来和防火墙丢包一模一样,所以这项检查要放在再加一条 NAT 规则之前。

在网关上,要检查转发和 forward 链,而不是 input 链。然后确认对端知道如何到达源地址,因为出方向通、回程没有,在两个方向上都是静默。

记录必须写清什么

每次改动都要记下验证过的环节、读到的证据,以及它两侧的计数器值。正是这份记录让"现在能用了"在下一次评审时还站得住。

两个捷径能让记录保持诚实。没离开主机的报文,不可能被别处的规则丢弃,无论对端配置看起来多可信。出去又回来的报文,则把问题抬到网络层之上,那里防火墙计数器已经没什么可告诉你的了。

相关文章