VXLAN over WireGuard:跨机房局域网
VXLAN over WireGuard:跨机房局域网
来源 https://mp.weixin.qq.com/s/L2RDLTATXGP0GNULmTHkVg
既要解决公网加密,又得保住原来的二层网络。听着有点绕,但很多老系统搬家时,缺的就是这样一根虚拟网线。

这种需求压根没人会提前规划。一般都是迁移前一晚,群里炸出来一句:“哎,那台机器搬到新机房,IP 不变行不行?”
说白了就一句话:改不起。许可证跟 IP 绑定,合作方白名单改一轮要审好几天,还有个十年前的老服务靠广播找人。谁都知道三层路由干净,可迁移窗口就几个小时,这时候谁敢顺手把那套还能跑的系统重构了?
服务器能搬,原来的交换机搬不过去。两台虚拟机隔着公网,还想继续待在同一个局域网里,办法不算多。
VXLAN over WireGuard 就是这种场合会被翻出来的方案。
虚拟机迁移最容易碰上这种事。老机房要退租,宿主机已经换到新地点,应用却牵着一串外围系统。改一个地址不难,难的是找出谁还记着这个地址。监控平台、备份脚本、数据库授权、合作方白名单,甚至某个早已离职同事留下的批处理,都可能在迁移以后突然冒出来。先保住原 IP,至少能给排查这些依赖留点时间。
实验室也会遇到。家里有一台虚拟化主机,公司测试区还有几台设备,临时需要验证集群发现、DHCP 或 PXE。它们隔着两条普通宽带,申请专线不现实,逐台改网络又破坏了测试环境。把指定的二层网段延伸过去,测试完再拆,成本反而低。
还有灾备切换。生产节点出了问题,备用虚拟机已经在异地启动,可上游系统只认原来的地址。此时最宝贵的是先恢复服务,不是在事故现场讨论网络架构。VXLAN over WireGuard 可以撑过这段窗口,等业务稳定后再慢慢处理路由和地址改造。
这些情况说到底就一个意思:二层延伸只是临时顶一下,因为现在改应用比拉条临时网线还折腾。如果系统本来就能随便改地址、改路由、做服务发现,那就别碰这套东西,纯粹给自己加活。
WireGuard 已经通了,为什么还不够
很多人的第一反应是先装 WireGuard。配置不算复杂,能加密,穿公网和 NAT 也方便。等两边的 wg0 互相 ping 通,看上去已经差不多了。
但 WireGuard 给的是一条三层通道。它认识 IP 包,不替你转发完整的以太网帧。ARP 广播、某些二层发现协议,以及“我必须继续待在原网段”的虚拟机,都不能直接把 wg0 当成交换机端口使用。
还差一层。VXLAN 把原始以太网帧包进 UDP,送到另一端的 VTEP;这个 UDP 包再交给 WireGuard 加密,从公网发出去。
一帧 ARP 请求离开虚拟机后,大致会变成这样:
[公网 IP][UDP 51820][WireGuard 加密数据:
VTEP IP + UDP 4789 + VXLAN + 原始以太网帧]
公网设备只看见 WireGuard 流量。对端解密、拆掉 VXLAN 头,再把原来的以太网帧送进 Linux Bridge。虚拟机看到的仍是熟悉的 ARP 和 MAC 地址,好像对方就在隔壁机柜。
我自己习惯管它叫“加密网线”:WireGuard 负责把线扯到对面,VXLAN 负责在这根线里跑二层帧。别急着背那两层封装头,先这么想,省脑子。

先把两个站点跑通
假设两个机房的公网地址分别是 203.0.113.10 和 203.0.113.20,WireGuard 使用 10.200.0.0/24:
机房 A 的 wg0:10.200.0.1/24
机房 B 的 wg0:10.200.0.2/24
虚拟机 A:192.168.50.11/24
虚拟机 B:192.168.50.12/24
A 端的核心配置如下。密钥权限、防火墙和开机加载暂时略过,先看数据路径。
ip link add wg0 type wireguard
ip addr add 10.200.0.1/24 dev wg0
ip link set wg0 mtu 1420 up
wg set wg0 listen-port 51820 \
private-key /etc/wireguard/a.key \
peer <B的公钥> \
allowed-ips 10.200.0.2/32 \
endpoint 203.0.113.20:51820 \
persistent-keepalive 25
B 端把地址、密钥和 Endpoint 对调。先把两个 wg0 地址 ping 通,再往下建 VXLAN。别反过来折腾,不然底层没通,后面怎么看都像 VXLAN 配错了。
接着在 A 端创建 VNI 100,并把虚拟机的 tap0 接进同一个桥:
ip link add vxlan100 type vxlan id 100 \
local 10.200.0.1 remote 10.200.0.2 \
dstport 4789
ip link add br100 type bridge
ip link set vxlan100 mtu 1370
ip link set vxlan100 master br100
ip link set tap0 master br100
ip link set br100 mtu 1370
ip link set vxlan100 up
ip link set br100 up
B 端照着配一遍,把 local 和 remote 对调。tap0 可以换成容器的 veth,也可以换成确实要接入这个二层域的物理接口。公网出口那块网卡别顺手扔进 br100,省不了多少事,断网时倒是很难收场。
注意命令里写了 dstport 4789,这是 VXLAN 的标准端口。有些老环境还在用 8472。两边如果一边写、一边省略,配置看着差不多,包就是死活对不上。这类坑很隐蔽,干脆两端都写死。
防火墙也别忘了。公网侧放行 WireGuard 的 51820 就行,4789 不用暴露出去。但包被 WireGuard 解密以后,还得从 wg0 进入本机 VTEP。主机的 INPUT 默认是 DROP,就要允许来自 wg0 的 4789/UDP。
AllowedIPs 不要顺手填成业务网段
这一套配下来,最容易顺手写错的反而是 WireGuard 的 AllowedIPs。
A 端发出的 VXLAN 包,外层目标是 B 的 VTEP 地址 10.200.0.2。因此对应 Peer 需要的是:
AllowedIPs = 10.200.0.2/32
虚拟机使用的 192.168.50.0/24 已经藏在 VXLAN 里面。仅为了这条二层隧道,通常不必再把它写进 WireGuard。
如果本机的 br100 已经直连 192.168.50.0/24,配置工具又给 WireGuard 加了一条同网段路由,事情反而麻烦了:部分流量可能还没来得及进入桥,就先被三层路由带走。最后看到的症状常常是“有些地址通,有些地址不通”,排查半天才发现同一个网段走了两条不同的路。
记住一条就行:WireGuard 只管运 VTEP 之间的包,所以 AllowedIPs 先写 VTEP 地址。业务网段要不要加?看它有没有单独做三层路由,别顺手全塞进去,不然后面排错很折磨。
第三个站点一加进来,事情就变了
两个站点很好办,因为每一帧只有一个远端可去。前面的 remote 10.200.0.2 已经把方向写死。
到了三个站点,ARP 广播和未知目的 MAC 需要同时发给 B、C。此时不能继续复制点对点配置,而要重建一个不带固定 remote 的 VXLAN,再为各个 VTEP 添加洪泛项:
ip link add vxlan100 type vxlan id 100 \
local 10.200.0.1 dstport 4789
bridge fdb append 00:00:00:00:00:00 \
dev vxlan100 dst 10.200.0.2
bridge fdb append 00:00:00:00:00:00 \
dev vxlan100 dst 10.200.0.3
WireGuard 那边也不能落下。C 需要自己的 Peer,10.200.0.3/32 要进入对应的 AllowedIPs。三个节点是互相直连,还是都经过中心节点,也要提前决定。前者配置多,后者简单,但中心节点会多吃一份带宽,挂掉时影响也更大。

到这里就能看出来,这东西适合两三个站点临时顶一下,真不适合手工扩到几十个站点。每加一个地方,都要同时维护 WireGuard Peer 和 VXLAN FDB。虚拟机再迁一次,旧 MAC 什么时候过期、广播该往哪里复制,全会变成运维的活。
两点之间,它确实像根网线。站点一多,这就是一张正经网络,别再拿临时脚本糊弄。
最折磨人的故障,通常叫 MTU
VXLAN over WireGuard 跑起来后,经常会出现一种很别扭的状态:ping 正常,SSH 能登录,一传大文件就卡;网页有的能开,有的加载到一半停住。
小包让人误以为链路没问题。实际上,每套一层头部,留给业务的空间就少一点。
在常见的 1500 字节公网链路上,WireGuard 通常把 wg0 设为 1420。这个值兼顾了 IPv6 外层,是一个偏保守的默认值。VXLAN 还要再放入 IP、UDP、VXLAN 头和内层以太网头,使用 IPv4 VTEP 时,可以先按下面这组数测试:
物理链路 MTU 1500
WireGuard 接口 MTU 1420
VXLAN 与业务端 MTU 1370
最容易漏的是最后一行。把 vxlan100 和 br100 改成 1370,虚拟机里的网卡不会自己跟着变。它还用 1500 发包,大包照样卡。虚拟机里面也得改:
ip link set eth0 mtu 1370
机器多时可以通过 DHCP Option 26 下发。1370 也不是所有环境的固定答案;公网和 VTEP 使用 IPv4 还是 IPv6、内层有没有 VLAN 标签,都会改变可用值。它只是这套示例的起点。
排查时别只用默认大小的 ping。业务端 MTU 为 1370 时,可以试试:
ping -M do -s 1342 192.168.50.12
然后再传个大文件。能回一个 ICMP 小包,跟能稳定搬完几十 GB 数据,压根不是一回事。

出问题时,从外往里看
双层隧道看着绕,排错时别乱跳,老老实实从外往里看。
先执行 wg show。没有最近握手,就去查公网端口、密钥、Endpoint 和 NAT,暂时别碰桥和 FDB。
WireGuard 有收发字节后,再到 wg0 看解密后的 VXLAN:
tcpdump -ni wg0 udp port 4789
这里有包,WireGuard 这层就算交差了。再用 bridge fdb show dev vxlan100 看远端 MAC 学到了哪里,最后去 br100 上看 ARP 和 ICMP:
tcpdump -eni br100 arp or icmp
包在哪层没了,就查哪层。这样至少不会对着两个隧道来回猜。
上线前最好再做一次不像演示的测试。让虚拟机重新获取地址,看 DHCP 广播能不能回来;清掉 ARP 和 FDB 后重新访问,确认网络不是靠旧缓存碰巧连通;传一份足够大的文件,同时看两端 CPU 和丢包。条件允许的话,再主动停掉一端 WireGuard,观察恢复以后 MAC 表能否重新学回来。
这些动作没什么技术含量,却最容易被一句“已经 ping 通了”省掉。等旧机房断电以后才发现只有小包能走,那就只能加班补课。
这根网线,最好有拆掉的日期
VXLAN over WireGuard 很适合两地实验室、少量虚拟机迁移、临时灾备,以及短期内改不了地址和发现机制的旧系统。它用普通公网解决了一段原本需要专线的二层连接,WireGuard 也避免了把明文 VXLAN 直接暴露出去。
代价也很实在。两个机房的广播和二层故障从此绑一块了;WireGuard 只管认证隧道 Peer,内层有人发伪造 ARP、乱放 DHCP、搞广播风暴,它一概不管。CPU 还得同时扛 VXLAN 封装和 WireGuard 加密,小机器经常网口还没跑满,一个核心先干到 100%。
如果应用本来就能通过三层地址访问,直接在 WireGuard 上做路由会省心很多。只有那些“IP 暂时不能改、广播暂时不能丢、系统暂时不能重构”的场合,才值得把二层一路延伸过去。
麻烦就在“暂时”两个字,它很容易一拖就是几年。真要上这套方案,除了记下 Peer、FDB 和 MTU,顺手把退出条件也写上:白名单改完、旧服务下线,能切回路由的就赶紧切,别等所有人都忘了当初为什么这么配。
那台老虚拟机根本不知道自己搬过家。记得这事的,只有半夜起来修隧道的人。
================ End

浙公网安备 33010602011771号