主题
WireGuard:一次完整的排查实录
先说结论
本环境里没能把 WireGuard 跑通。 配置全部被接受、握手报文在链路上流动, 但 peer 的邻接始终为空,数据面以 Peer error 丢包。
这一篇不假装它成功了。它记录的是一次完整的排查过程 —— 用前面章节教的工具(trace、错误计数、feature arc、逐层对照) 一步步缩小范围,最后确定问题边界。
对读者的价值有两层:一是如果你也要在类似环境试 WireGuard, 这里能省掉你重复走一遍;二是这套排查方法本身, 比任何一个"配置成功"的例子都更接近真实工作。
为什么想试 WireGuard
上一篇结尾说了 GRE 的硬伤:明文,无认证。 跑在互联网上必须叠加加密。
传统方案是 IPsec,但配置复杂(IKE 协商、SA、各种算法套件)。 WireGuard 用一套极简的设计做同样的事:
text
· 只有一种加密套件,没得选,也就没法配错
· 密钥就是一对公私钥,像 SSH 一样直观
· "加密路由"(cryptokey routing)—— 每个 peer 声明自己负责哪些网段
· 跑在 UDP 上,能穿 NAT
· 代码量比 IPsec 小两个数量级VPP 26.06 带 wireguard 插件,看起来是个理想的组合。
配置过程
命令族本身很干净:
bash
wireguard create listen-port <port> private-key <key> src <IP> [generate-key]
wireguard peer add <wg_int> public-key <对端公钥> endpoint <对端IP> \
allowed-ip <网段> dst-port <端口> [persistent-keepalive <秒>]
show wireguard interface / peer / mode一、建接口,让 VPP 自己生成密钥
bash
vppctl wireguard create listen-port 51820 src 198.51.100.1 generate-key # nat1
vppctl wireguard create listen-port 51820 src 198.51.100.2 generate-key # nat2
vppctl show wireguard interfacetext
[0] wg0 src:198.51.100.1 port:51820
private-key:AJDQGgL3mIU+qCneKWZRwMgRrz9utXQx2lSlm5P0sWM=
public-key:0SWBMhZ7GcDdM5oZWDkZ9c9fq6MAGUi7DRthQ94i3wg=公钥私钥都生成了,格式和标准 WireGuard 一致(base64 编码的 32 字节)。
二、互相添加 peer
bash
# nat1 上添加 nat2 作为 peer
vppctl wireguard peer add wg0 \
public-key fW8DQqZP9KiLBXLVBJnDE/X+W9yNkx6PSfJ5hghLuVM= \
endpoint 198.51.100.2 allowed-ip 10.2.0.0/24 \
dst-port 51820 persistent-keepalive 10allowed-ip 就是加密路由的核心:这个 peer 负责 10.2.0.0/24。 发往这个网段的包用它的公钥加密,从它那儿收到的包也只接受这个网段的源地址。
三、起接口、配地址、指路由
bash
vppctl set interface state wg0 up
vppctl set interface ip address wg0 10.99.2.1/30
vppctl ip route add 10.2.0.0/24 via 10.99.2.2到这里所有命令都成功了,没有任何报错。
排查过程
但 hA 到 hB 不通,100% 丢包。下面是完整的诊断链条。
第 1 步:看错误计数
bash
vppctl show errors | grep -i wgtext
4 wg4-output-tun Peer error errorPeer error —— 发包时 peer 处于不可用状态。这告诉我们问题在 发送侧的 peer 状态,不是在收包或加密上。
第 2 步:看包走到哪一步
bash
vppctl clear trace && vppctl trace add af-packet-input 6
# ...制造流量...
vppctl show tracetext
→ ip4-input
→ ip4-lookup
→ ip4-load-balance
→ ip4-midchain
[@1]: dpo-drop ip4 ← 关键
→ wg4-output-tun
→ error-drop
→ dropip4-midchain 的转发链解析成了 dpo-drop。
对比上一篇 GRE 正常工作时的 trace,那里是:
text
→ ip4-midchain
→ tunnel-output ← 正常时走这里
→ ip4-rewrite所以问题很明确:隧道的转发链没有建立起来。
第 3 步:看 peer 的详细状态
bash
vppctl show wireguard peertext
[0] endpoint:[198.51.100.1:51820->198.51.100.2:51820] wg0
keep-alive:10 flags: 2, api-clients count: 0
adj: ← 空的
public key:fW8DQqZP9KiLBXLVBJnDE/X+W9yNkx6PSfJ5hghLuVM=
allowed-ips: 10.2.0.0/24adj: 是空的。 邻接没有被填充,这正好解释了上一步的 dpo-drop。
第 4 步:握手包到底有没有在走
怀疑是握手没完成。在对端抓包:
bash
# 在 nat2 上
vppctl clear trace && vppctl trace add af-packet-input 10text
收到 nat1 的 UDP 包数: 9
UDP: 198.51.100.1 -> 198.51.100.2
00:05:59:937378: wg4-input ← WireGuard 的输入节点确实处理了握手报文在流动,而且被 wg4-input 节点正常接收了。 所以不是网络不通,也不是端口没监听。
第 5 步:排除周边因素
逐个排除:
text
ARP 解析 show ip neighbors 里 198.51.100.2 已解析 ✓ 不是这个
路由写法 改成 ip route add ... via wg0(接口路由) ✗ 仍然 dpo-drop
加密引擎 show crypto engines 有 4 个可用引擎 ✓ 不是这个
异步模式 set wireguard async mode on ✗ 无变化
allowed-ip 放宽到 0.0.0.0/0 ✗ 无变化五种尝试之后,adj: 依然是空的。
结论
问题定位在:peer 的邻接从未被填充。握手报文能收发, 但 peer 没有进入可用状态,导致隧道的转发链解析为丢弃。
这是环境问题还是版本问题?
我无法从这里判断。可能的因素包括:
- VPP 26.06 的 wireguard 实现在这个配置下的问题
- 容器 + AF_PACKET 环境下的某种交互
- 某个我没找到的必需配置步骤
诚实的说法是:在本教程的实验环境里,用 CLI 配置的 WireGuard 没能建立数据面。 不能据此断言"VPP 的 WireGuard 不能用"。
这次排查用到的方法
回头看,整个过程就是第 7 章那套流程的应用:
text
1. show errors → Peer error,锁定在发送侧的 peer 状态
2. show trace → dpo-drop 出现在 ip4-midchain
3. 和正常案例对照 → GRE 的 trace 里是 tunnel-output,差异明确
4. show wireguard peer → adj 为空,和第 2 步的现象对上了
5. 对端抓包 → 握手包在走,排除网络层问题
6. 逐个排除周边因素 → ARP / 路由写法 / 加密引擎 / 异步模式 / allowed-ip第 3 步"和正常案例对照"是效率最高的一步。 因为 GRE 已经跑通了, 两份 trace 一比,差异立刻收敛到 midchain 那一跳 —— 不然光看 dpo-drop 很难知道它本该是什么。
这也是为什么本教程坚持"每个特性都跑通一个可对照的正常案例"。
什么时候该停
排查到第 5 步时,已经能确定:不是网络问题、不是配置语法问题、 不是加密引擎问题。剩下的可能性需要读 VPP 源码或者查上游 issue, 超出了"配置和运维"的范畴。
在工程上,能把问题边界划清楚就已经完成了大部分价值 —— 知道"不是我的配置错了"和知道"具体是哪一行代码的 bug", 对决策的意义是一样的:换方案,或者去上游提 issue。
那加密隧道怎么办
如果需要在公网上跑加密隧道,VPP 26.06 里的现实选择:
text
✓ IPsec / IKEv2 插件齐全,是 VPP 上最成熟的加密隧道方案
代价是配置复杂度高得多
✓ GRE over IPsec 先 GRE 打通,再用 IPsec 保护外层
路由灵活性和加密兼得,是传统企业组网的常见做法
? WireGuard 本环境未能跑通(本篇)本教程没有覆盖 IPsec —— 它值得单独一章,而且需要更细致的 算法套件、SA 生命周期、NAT 穿越等内容。
小结
| 想解决 | GRE 的明文问题,用比 IPsec 简单的方式做加密隧道 |
| 配置 | wireguard create + wireguard peer add + 路由,命令很干净 |
| 实测结果 | 未能跑通:配置成功、握手包在流动,但 peer adj: 为空 |
| 故障签名 | wg4-output-tun: Peer error + trace 里 ip4-midchain → dpo-drop |
| 排除过的 | ARP、路由写法、加密引擎、异步模式、allowed-ip 范围 |
| 最有效的诊断手段 | 和跑通的 GRE 做 trace 对照,差异立刻收敛到 midchain |
| 替代方案 | IPsec / IKEv2,或 GRE over IPsec |
第 10 章到此结束:
text
GRE 打通两个私网,简单可靠,但明文
MTU 与 MSS 隧道最高频的故障来源,clamping 是标准解法
WireGuard 一次完整排查实录 —— 以及知道何时该停