WireGuard PersistentKeepalive:让 NAT 映射保持存活
如果反向连接只在对等端发送流量后立刻可用,说明映射正在过期。把 keepalive 设在路由器后面,然后读出真正的超时时间。
家里的盒子打开隧道并顺利到达云服务器。云服务器能在家里盒子最后一次发送东西后的一两分钟内访问家庭应用,然后就停止了。WireGuard 日志里什么也没有,没有任何握手错误,重启隧道只能短暂修好。这种模式说明映射正在过期,而不是隧道坏了;下面的步骤会在做任何改动之前确认这一点。
确认这是空闲导致的映射过期
关键的区分点在于时间。如果反向连接在家庭对等端发送流量后立刻可用,安静一段时间后就失败,那路径是好的,中间的状态不是。如果它从来没有成功过,即使刚发完流量也不行,那就是错误的诊断。
sudo wg show wg0 latest-handshakes
sudo wg show wg0 endpoints
sudo wg show wg0 transfer
在家庭对等端发送东西后立刻运行前两条命令,等五分钟再运行一次。握手时间戳按计划刷新且没有出现新端点,说明隧道是活的。变化的是外部未请求的数据包能否到达,这属于路径而不是隧道的性质。
然后做一次反向尝试,观察传输计数器。如果云端发出了字节,家庭端却一个都没收到,说明数据包离开了云端,死在了途中有状态的设备里。这正是你要找的特征。如果两个计数器都在走,说明隧道送达了数据包,可疑的是应用。
把 keepalive 放在路由器后面的对等端上
持久 keepalive 通过按计划发送一个小的认证数据包,让 NAT 映射和任何防火墙状态保持存活。这个设置属于路由器后面的机器,写在它针对远端对等端的条目里,因为是这一侧发出的数据包创建了状态。
[Peer]
PublicKey = <cloud peer public key>
AllowedIPs = 10.71.0.1/32
PersistentKeepalive = 25
把它合并进现有的对等端段落。用同一个公钥再加一个块并不是添加选项的有效方式,wg-quick 也不会替你合并。文档里的 25 秒只是一个示例,选它是为了落在常见 UDP 超时之下,并没有特殊含义。
在云端加同一条指令对这个问题没有帮助。那个对等端的数据包本来就从公网地址过来,所以在重要的方向上没有需要保住的映射。它只会增加流量,什么也改变不了。
读计时器,而不是猜一个间隔
keepalive 之所以有效,是因为它到达的频率高于状态过期。所以真正需要的数字是超时时间,在 Linux 上可以在做转换的设备上读到:
sysctl net.netfilter.nf_conntrack_udp_timeout
sysctl net.netfilter.nf_conntrack_udp_timeout_stream
sudo conntrack -L -p udp --dport 51820
第一个值是只在一个方向上观察到的 UDP 流的超时,第二个值在观察到回应后生效。两者通常都很短,安静下来的映射会遵循适用于你的流的那个值。
把这个数字和你的间隔比较一下。25 秒的 keepalive 在 30 秒超时下有效;同样的 keepalive 在 15 秒超时下无效。再怎么重试也改变不了这个算术。一些家用路由器和移动运营商使用的值比 Linux 默认值短得多,这就是为什么在一个网络上可行的配置在另一个网络上会失败。
| Observation | What it means | Reasonable response |
|---|---|---|
| Works after traffic, dies when idle | Mapping or firewall state expiring | Lower the keepalive interval |
| Never works, even immediately | No return route, listener or firewall | Stop tuning keepalive |
| Works for hours, then dies once | Carrier-side translation or address change | Check the endpoint and logs together |
分别检查监听器和防火墙
活的映射是必要条件,不是充分条件。家庭盒子上的应用必须监听正确的地址,主机防火墙必须在解密之后放行数据包。
sudo ss -lntup | grep 8080
sudo wg show wg0 allowed-ips
curl -sS -m 5 http://10.71.0.2:8080/health
如果套接字只绑定到物理接口地址而不是隧道地址,到达隧道的数据包会在询问防火墙之前就被丢弃。这种故障从云端看和映射问题一模一样,而且任何 keepalive 调整都救不了它。
允许列表的检查在另一个方向上同样重要。云端对等端如果要回应,就必须允许家庭隧道地址作为源;家庭对等端也必须允许云端地址作为目的。keepalive 数据包是经过认证的流量,走的是同一套规则,所以看起来有效的 keepalive 可以和不能工作的应用共存。
推出改动,并了解它的边界
应用这个设置,如果这是你的更新方式就重启接口,然后重复空闲测试而不是立即测试。等待时间要长于你刚才读到的超时,做一次反向请求,确认两端的计数器都在走。
把间隔和测得的超时写在旁边。将来路由器固件更新,或者换成移动网络,都可能改变超时。有了这条备注,别人才能重新推导这个值,而不是照抄。一行两个数字,往后能省掉一整次排查。
持久 keepalive 保护的是状态。它不会打开端口,不会往允许列表里加条目,也不会让监听器出现。当反向连接完全不通时,问题就在这三者之一,而 WireGuard 快速入门 也是用同样狭窄的说法描述 keepalive 设置。