如何搭建一个只验证一条路径的双对端 WireGuard 测试
一条隧道、一对地址、一项被允许的资源。最小化的 WireGuard 基线让之后的每次转发、NAT 或 DNS 改动都暴露出来。
一条 WireGuard 测试若同时带着默认路由、LAN 前缀、DNS 和防火墙例外,就说不清是哪一部分坏了。把它削减到两个对端、一对地址和一项被允许的服务,故障便无处可藏。乏味的基线本身就是诊断。先把它搭起来;这花十五分钟,却省下你本来要用来猜的一下午。
基线能证明的东西比多数人以为的更窄。它只证明两个身份彼此认可、UDP 能到达监听端口、以及一个被允许的目的地能承载一次请求。转发、NAT、LAN 路由和 DNS 都是之后逐个添加的独立功能。
密钥、地址与唯一的端点
在每台系统上生成一对密钥,只在两者之间传递公钥那一半。wg genkey | tee privatekey | wg pubkey > publickey是官方文档里的一行命令,它把私钥留在文件中,随后你可以保护这个文件。从你其他任何配置里都不出现的网段中挑选隧道地址,比如 10.99.0.1/24 和 10.99.0.2/24。写下哪个地址属于哪台机器,因为之后每一次检查都依赖这份对应关系。
私钥永不外传。如果一次测试需要把私钥复制到另一端,这次测试已经做错了。当两台系统都位于 NAT 之后时,至少有一台需要可到达的 UDP 端口,另一台则携带指向它的 Endpoint,而公网地址和端口应当写进笔记,而不是停留在你对 51820 的假设里。
映射到另一个外部端口的端口转发,只要 Endpoint 与之匹配就能正常工作。这里的错配只会带来沉默而不是报错,所以值得先在纸上核对,再去线上调试。
属于 wg 的字段,以及不属于它的字段
核心字段很少:Interface 下的 PrivateKey 和 ListenPort,Peer 下的 PublicKey、AllowedIPs 和 Endpoint。Address 和 DNS 属于 wg-quick 而非 wg 本身,一旦同一份配置搬到别的工具里,这个区别就会咬人。
[Interface]
PrivateKey = <peer-a-private>
Address = 10.99.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <peer-b-public>
AllowedIPs = 10.99.0.2/32
Endpoint = 203.0.113.10:51820
AllowedIPs 同时承担两件事。它选择哪些目的地进入隧道,并且授权对端在到达时使用那些源地址。正因如此,另一侧的镜像条目必须准确写出你的隧道地址;给错对端的 /32 会被读成路由问题,表现得却像授权问题。WireGuard 快速入门用标准写法展示了同样的双对端形态,方便你对照字段名。
读握手,而不是看图标
用管理它的方式把接口拉起来,然后读状态而不是看指示灯。wg show会打印每个对端最近的握手和字节计数,最近几分钟内有握手就意味着密钥、端点和 UDP 路径都在工作。只往一个方向增长的计数本身就是答案,它与从未发生的握手不是同一种故障。
两种故障指向不同的排查方向。完全没有握手,指向密钥不匹配、Endpoint 错误、UDP 被阻断,或防火墙丢弃了握手本身。握手成功而数据不通,指向 AllowedIPs、没有在隧道地址上监听的服务,或只对 LAN 放行该端口、对隧道接口不放行的主机防火墙。这是系统的两半,基线会在你动手改规则之前把它们分开。
先证明一项被允许的服务,再证明反方向
向另一对端的隧道地址、在一个本应应答的服务上发一次请求,别用 ping。ICMP 没有回音可能只是主机过滤,而不是隧道故障,所以沉默的 ping 两边都证明不了。连到你知道已开放的端口的 TCP 连接,或一次返回数据的请求,才会给你能解读的答案。
把反方向当成一次独立测试单独跑,有自己的结果,因为两个方向各有独立的防火墙和 AllowedIPs 条目,可能各自失败。如果握手正常而请求不通,问题在数据路径而不是隧道:AllowedIPs、正在监听的服务,或主机防火墙。先修好它,再加转发、NAT 或 DNS,否则你会花一下午去调试一个从来不是元凶的功能。
把基线留作参照
把可用的拓扑和配置源保存到能恢复的地方,并让它远离任何会同步到公共服务的目录。然后一次只加一项功能,每加一项就重跑最初那次请求:转发、NAT、一条 LAN 路由,最后才是 DNS。此时每一项弄坏测试的增补都能被指认出来,因为其他东西没动。
只让图标变绿的基线,并没有告诉你下一次故障是哪项增补造成的。让唯一被允许的路径持续可用作为参照,之后每一次改动都拿它来衡量。