干运维这些年,跨机房组网这件事上我见过最多的翻车现场,从来不是加密被破解,也不是带宽买小了,而是"能 ping 通就以为万事大吉"。前阵子一个客户的工单很典型:两台分布在两个机房的服务器之间拉了 WireGuard 隧道,ping 通、SSH 能登、curl 个小接口也正常,但 scp 传一个两百多兆的包必定卡在某个百分比不动,数据库主从同步断断续续,rsync 跑一半就超时。他第一反应是"机房之间的网络有问题",让机房查链路,查了两天没结果。
我登上去第一行命令就是 wg show,latest handshake 有时间戳、transfer 收发的字节数也都在涨,看着一切正常。再跑一句 ping -M do -s 1472,直接不通,逐档往下调到 1392 才通。MTU 没算对,典型的路径 MTU 黑洞。改一行配置,两分钟解决。
说白了,WireGuard 这东西本身极难配错——它没有算法协商、没有证书体系、配置文件就那么十几行。真正让人掉坑的,全是配置之外的三件小事:MTU 算错、保活没配、AllowedIPs 写重叠。这篇就把这三件事连同它们的排查手法一次讲透,顺便说清楚多机房互联到底该怎么选机器。
先给五条能直接抄走的结论:
先说清楚 WireGuard 到底是个什么东西,后面所有奇怪的行为都跟它的设计选择有关。WireGuard 用的是 Noise 协议框架里的一个具体握手模式 Noise_IKpsk2,密钥交换固定 Curve25519,对称加密固定 ChaCha20-Poly1305,哈希固定 BLAKE2s。注意"固定"这两个字——它没有任何算法协商环节,不会出现两端因为配置不一致而降级到某个弱算法的情况。作者把这种设计叫 cryptographic opinionatedness,说白了就是:我不给你选,我替你选好,你只用管密钥和地址。
带来的直接好处是代码量极小,内核模块在数千行的量级(以官方代码库为准),一台机器上跑起来资源占用很轻,审计和定位问题都容易。对运维来说这意味着一件事:你几乎不可能把"加密"这部分配错,能配错的全是加密之外的地方。
WireGuard 工作在三层,也就是 IP 层。它没有 MAC 地址、不学 ARP、不做二层 bridging,接口起来之后表现得像一块点对多点的三层网卡。如果你的业务真要传二层帧(比如某些老集群的心跳、某些需要广播发现的中间件),那就得在 WireGuard 之上再套一层 VXLAN 或者 GRE。提醒一句:每多套一层封装,MTU 就要再往下压,这是很多人第二次踩坑的地方。
它跑在 UDP 上,一个 ListenPort(默认常用 51820)收所有 Peer 的流量。而且它是无连接的——没有"已连接/已断开"的状态机,只有握手计时器。这跟 IPsec、OpenVPN 那种"隧道起来就是起来"的手感完全不同:WireGuard 的接口可以 up 着、路由也在表里,但对端其实根本没握手成功,你看到的现象就是"配好了但不通"。
所以排障的抓手必须是状态而不是接口:wg show 里的 latest handshake 有没有时间戳、transfer 收发字节有没有在涨、endpoint 是不是你预期的那个公网地址。这三个不看,等于闭着眼睛查。
加密是要吃 CPU 的,这点绕不过去。ChaCha20 是纯软件实现友好的算法,在没有 AES-NI 指令集的老 CPU 上,它反而比 AES-GCM 跑得快;而现代 CPU 普遍带 AES-NI,走 IPsec 的那套硬件加速在纯吞吐上可能更占优(具体差距以实测为准,别信任何拍脑袋的百分比)。
这个结论对租服务器有实际意义:如果你手里是一批 E5 时代的老机器做跨机房互联,上 WireGuard 完全不必担心加密拖后腿;反过来,新机器上也别指望它比内核态 IPsec 更快。选型时真正该关心的不是"哪个加密更快",而是"这台机器有没有足够的单核性能扛住你那条链路的峰值小包速率"——UDP 小包转发吃的是单核软中断,核太弱就是瓶颈。
WireGuard 干的活是:把你原来的那个完整 IP 包(IP 头 + 载荷)整个加密,再在外面套上 WireGuard 自己的头,最后再套一层外层 IP 头 + UDP 头发出去。所以经过隧道的包一定比原包大,多出来的这部分就是开销。官方论文与白皮书给出的数字是:IPv4 承载时开销约 32 字节,IPv6 承载时约 80 字节(外层 IPv6 头本身就比 IPv4 头长不少)。
那么 WireGuard 接口的 MTU 该怎么定?工程上的算法是:接口 MTU = 物理口 MTU − 封装开销 − 安全余量。物理口 1500 的标准以太网场景下,IPv4 承载按 32 字节算理论上限能到 1468,但实际工程里统一取 1420——这也是 WireGuard 不指定 MTU 时的默认值,它留了几十字节余量,兼容 IPv6 承载、兼容你后面可能再加的封装。IPv6 承载时开销更大,一般把接口 MTU 压到 1380,保守起见直接用 1280(IPv6 规定的最小 MTU)也完全能跑,代价是分片多一点。以上数值请以你自己环境的实测为准。
配置就一行,写在 [Interface] 段里:
MTU = 1420
| 承载场景 | 封装构成 | 封装开销 | 建议接口 MTU | 配错的症状 | 验证命令 |
|---|---|---|---|---|---|
| IPv4 承载,物理口 1500 | 外层 IPv4 头 + UDP 头 + WireGuard 头与认证标签 | 约 32 字节(论文口径) | 1420(默认值,留余量) | ping 通、大文件传输卡死 | ping -M do -s 1392 |
| IPv6 承载,物理口 1500 | 外层 IPv6 头 + UDP 头 + WireGuard 头与认证标签 | 约 80 字节(论文口径) | 1380,保守取 1280 | IPv6 站点间歇性超时 | tracepath -6 目标地址 |
| WireGuard 之上再套 VXLAN/GRE | 再加一层隧道头,开销叠加 | 在 32/80 基础上再加数十字节 | 1280 起试,逐档上调 | 二层心跳丢、集群脑裂 | ping -M do -s 逐档二分 |
| 物理口本身不是 1500(PPPoE、云网卡、巨帧) | 先确认物理口真实 MTU 再减 | 以 ip link 查到的值为准 | 物理口 MTU − 80 起试 | 照抄 1420 仍不通 | ip link show 物理口 |
| 未指定 MTU | WireGuard 不做路径 MTU 探测 | 取默认 1420 | 标准以太网够用,其余场景要手改 | 换个机房就不通 | wg showconf wg0 |
第一,物理口 MTU 不一定就是 1500。拨号链路常见 1492,部分云主机的网卡是 1450 或者开了巨帧的 9000,机房内部如果走了某些封装,物理口有效 MTU 还会更小。上来就写 1420,等于假设了物理口 1500 这一个前提,前提不成立,配置就是错的。查真实值用 ip link show 看物理口那一行。
第二,WireGuard 不会帮你探测。它不像 TCP 那样有 MSS 协商兜底,也不会自动做 PMTU 发现并把结果写回接口。你写多少就是多少,写大了就等着出黑洞。这个"不智能"是设计选择,代价转嫁给了配置的人。
路径 MTU 发现(PMTUD)的机制本身很朴素:发送方把 IP 包的不分片标志(DF 位)置上,中间任何一台设备发现这个包比自己出口的 MTU 大,就丢掉它,同时回一个 ICMP"需要分片"的差错报文,告诉发送方"你下次发小点"。发送方收到后降低自己的包长,重传,链路就自适应了。
问题出在那个 ICMP 上。很多机房的边界防火墙、很多主机的安全组、很多运维自己写的 iptables 规则,为了省事或者为了防攻击,把 ICMP 一刀切全丢了。ICMP 一丢,发送方永远等不到"你发小点"这句话,只能不停重传那个永远过不去的大包,直到超时。这就是 PMTU 黑洞——链路是通的,大包死在里面,而且从业务日志上看不出任何原因。
ping -s 1400 立刻不通,这就是实锤。正解是把 MTU 配对:接口 MTU 压到真实路径能承载的值,让包在进入隧道前就被分片或者被 TCP 按更小的 MSS 发出去。改完立刻用带 DF 位的大包验证,别只看 ping 通不通。
临时兜底还有一招,就是 TCP MSS clamp——在防火墙上把经过隧道的 TCP 握手的 MSS 值强行改小,让两端协商出一个更小的数据段。这是治标,改完大文件能传了,但 UDP 业务照样死,而且会掩盖真正的问题。我一般只在客户急着恢复业务时临时用一次,回头还是要把 MTU 改对。
排查 PMTU 最直接的办法,就是自己发带 DF 位、指定大小的包,看它在哪一档断掉。Linux 上的写法是:
ping -M do -s 1472 对端内网地址
这里的 1472 是 ICMP 载荷长度,加上 8 字节 ICMP 头、20 字节 IP 头,正好 1500。-M do 就是"禁止分片",等价于把 DF 位置 1。通了说明这个尺寸过得去,不通(或者报 "Frag needed and DF set")说明超了。
别从 1472 一格一格往下减,太慢。直接二分:1472 不通就试 1200,通了试 1350,再试 1420……三四次就能锁到边界。测出来的 PMTU 减去 WireGuard 的封装开销(IPv4 场景按 32 字节、IPv6 按 80 字节算,再加一点余量),就是你该填的接口 MTU。
还有一种更省事的工具:tracepath 目标地址,它会自己逐跳把路径 MTU 报出来,IPv6 用 tracepath -6。注意 tracepath 走的是 UDP,如果你的防火墙把 UDP 也拦了,它的结果会偏乐观,还是以 ping 的结果为准。
第一,测的目标地址要用 WireGuard 内网地址,不是对端的公网地址——你要测的是隧道内部这条路径,不是隧道外的公网路径。第二,两端都要测一遍,因为路径是非对称的,去程和回程的 MTU 不一定相同。第三,Windows 上的写法不一样,是 ping -f -l 1472 目标,-f 对应 DF,-l 对应载荷长度,别照抄 Linux 的参数。
测完之后把结果写进配置文件,重启接口,然后再跑一遍大包确认。多机房场景下,我建议每拉通一条新链路就做一次这个测试,把结果记到你们的拓扑文档里——否则半年后加机器,谁也不记得当初为什么是 1380。
先把这件事说死:WireGuard 本身不做任何打洞协商,没有 STUN、没有 TURN、没有信令服务器。它的模型极简——两端各自写一段 [Peer],谁先发包谁就去握手。所谓"穿透",完全是蹭 NAT 设备自己的行为:内网机器主动往外发一个 UDP 包,NAT 就在自己的会话表里记一条映射,外面回来的包才能顺着这条映射进来。这条映射是有老化时间的,几十秒到几分钟不等,各家设备不一样(以实测为准),一段时间没流量就被清掉。
映射一清,对端再发包过来就进不来了。而 WireGuard 是无连接的,它不会主动去维持这条映射——除非你告诉它要维持。
告诉它的方式就是在 [Peer] 段里加一行:
PersistentKeepalive = 25
意思是:每 25 秒给这个 Peer 发一个保活包,不管有没有业务流量。包极小,就是一个握手包或者一个空载荷的数据包,开销可以忽略(每分钟一两个包这个量级,具体以实测为准)。但它足够让 NAT 会话表一直续着,洞一直在,对端随时能连进来。
为什么是 25 秒?因为它要小于绝大多数 NAT 设备的会话老化时间,常见的老化在 30 秒到几分钟这个量级,取 25 是保守但通用的做法。如果你确定对方的 NAT 老化时间更长,调到 60 也行,但没必要去赌——保活包的成本远低于排查一次"为什么连不上"的成本。真要省这点流量,也别省在关键链路上。
规则很简单:被 NAT 挡在后面的那一侧配,有固定公网地址的那一侧可以不配。公网侧配了也不出错,只是多一点点无谓的心跳。两侧都在 NAT 后面呢?那一侧都配上,谁先起谁先握手,洞就开了。
不配的后果非常有辨识度,就是"单向可达":站在 NAT 后面的机器主动连公网那台,一握手就通;但公网那台想主动连回来,永远超时。更迷惑的是,只要内网那台刚连过一次、NAT 映射还没老化,公网侧就能连上,过一会儿又断了。这种"时好时坏"的现象,十次有九次是保活没配。判断方法也简单:wg show 里看 latest handshake 的时间戳,如果它长时间不更新,而你对端明明在线,那就是握手包根本发不出去或者收不到。
另外提醒一句移动场景和按流量计费的场景:保活包是持续产生的,量很小但从不停止。按月租的机房服务器完全不用在意,按流量计费的边缘节点心里要有个数。
Endpoint 字段的语义是"我该往哪个公网地址:端口发包"。所以逻辑很直接:谁有固定公网地址,谁就不用填 Endpoint(它等着别人来连就行),对端在 [Peer] 里把它的公网地址和 ListenPort 写死。
写法是 Endpoint = 203.0.113.10:51820 这样,IP 或者域名都行。这一侧的 ListenPort 要在防火墙、安全组、机房的 ACL 里放行 UDP——注意是 UDP,很多人习惯性只放了 TCP,然后对着一个"永远握手不成功"的状态查半天。机房侧如果线路本身对 UDP 有限制策略,下单前就要问清楚,别等上架了才发现。
如果两个节点都没有公网可达的 UDP 地址,WireGuard 自己解决不了这个问题——它没有任何第三方帮你做打洞和转发。这时候只有一条路:找一台有公网地址的机器当中转(hub),两侧都跟它建隧道,流量走它转发。这也是为什么跨机房组网里,"机房有没有公网 IP、给不给单独公网地址"会直接决定你的拓扑能不能落地,租机器的时候这是要提前确认的硬指标。
中转点的位置也有讲究。它应该在网络位置上离两端都不远,最好本身就在骨干节点上,否则你只是把延迟从一个地方挪到另一个地方。对延迟敏感的业务,先把候选机房的测试 IP 要过来,自己跑几天 ping 和 mtr 再定,别看宣传词下单。
WireGuard 有个很实用的特性叫 cryptokey routing 的漫游(roaming):只要收到对端一个合法的数据包,它就会把该 Peer 的 endpoint 更新成这个包的来源地址。所以对端是动态 IP、或者发生了主备切换,只要对端能主动发包过来,你这边的 endpoint 会自动跟着变,不需要人工干预。wg show 里显示的 endpoint 就是当前实际生效的那个地址,跟配置文件里写的不一样是完全正常的。
但要记住一个坑:Endpoint 填域名时,解析只发生在配置加载那一刻(wg set 或 wg-quick up)。之后域名指向的 IP 变了,WireGuard 不会自己去重新解析。所以动态 IP 环境要么靠对端主动握手来触发 roaming,要么自己写个定时任务配合 DDNS 重新解析并 wg set 更新,别指望它自动跟踪域名。
AllowedIPs 是 WireGuard 里最反直觉的一个字段,因为它在本机和对端上表达的是完全不同的意思。
在本机的 [Peer] 段里,它是路由表:意思是"目的地址属于这些网段的包,交给这个 Peer 发"。wg-quick up 时会把这些网段写进系统路由表(除非你关掉)。
在对端的 [Peer] 段里(对端配置里指向你的那一段),它是ACL:意思是"从这个 Peer 进来的包,只有源地址落在这些网段里我才收,否则直接丢"。这一层是校验,不写就不通。
所以两边必须对称写。举个最常见的错:你这侧写了 AllowedIPs = 10.0.0.0/8,表示去 10 段都走这条隧道;对端那侧却只写了 AllowedIPs = 10.7.0.2/32,只认你一个地址。那么你从本机另一个地址(比如 10.7.0.3)发出的包到了对端会被直接丢弃,而且本机这侧看不出任何异常——包发出去了,transfer 的 tx 也在涨,但对端 rx 不动,或者干脆不计。这种"发出去没回音"的故障,一半以上出在这里。
把 AllowedIPs 写成 0.0.0.0/0 表示"所有流量都走这个 Peer",也就是拿 WireGuard 当默认网关用。这在把服务器流量全收到某个出口节点的场景下很合理,但副作用不小:wg-quick 会检测到你用了 0.0.0.0/0,为了防止路由环路,它会额外加路由规则(走单独的路由表 + fwmark),结果是你的其他路由策略可能被绕过,多 Peer 时更容易互相打架。
如果你只想借 WireGuard 打通内网、不想让它接管默认路由,就在 [Interface] 里加一行 Table = off。加了之后 wg-quick 不再自动写任何路由,路由完全你自己用 ip route add 或者路由守护进程管。多机房、多 Peer、还要跑 BGP 或 OSPF 的场景,我基本都建议开 Table = off——控制权留在自己手里,出问题好查。
改 Peer 配置时,很多人习惯 wg-quick down && wg-quick up,这会短暂中断所有经过这条隧道的业务。更稳的做法是写好新配置后用 wg syncconf wg0 <(wg-quick strip wg0),它只做增量更新,已有的会话不受影响。看当前实际生效的配置用 wg showconf wg0——注意它输出的是运行态配置,和你配置文件里的写法可能有细微差异(比如域名被解析成了 IP),这是正常的。
一台机器上可以同时有多个 Peer,但 WireGuard 选 Peer 的方式是最长前缀匹配:一个包的目的地址同时命中多个 Peer 的 AllowedIPs 时,掩码最长的那个胜出,其他的不参与。如果两个 Peer 的 AllowedIPs 完全一样或者包含关系写反了,那么只有一个 Peer 能拿到流量,另一个 Peer 的配置看着完整、握手也正常、但永远不会有业务流量走它——这就是"配了通不了"和"通了但走错路"的根源。
举个实际例子:Peer A 的 AllowedIPs 是 10.0.0.0/8(覆盖 A 机房整个内网),Peer B 是 10.10.0.0/16(B 机房某一段)。那么去 10.10.1.5 的包会走 Peer B,去 10.20.1.5 的走 Peer A,没问题。但如果你后来把 Peer B 也写成了 10.0.0.0/8,两个 Peer 等长,结果就取决于实现的挑选顺序,你的 B 机房可能整段失联,而且现象是"时通时不通",极其难查。
这问题没有配置技巧可以绕,只能靠规划。多机房互联的第一件事不是装软件,而是画一张网段分配表:每个机房(或者每个节点)拿一段独立的、不重叠的地址,WireGuard 隧道本身再拿一段独立的 /24 或者更长前缀的地址专门给接口用。表画完,所有机器的 AllowedIPs 都按这张表写,之后加机器就照表续。
现实里最麻烦的是"先有服务器、后有组网"——各个机房的内网网段当初是各配各的,早就撞车了。这种情况下要么做一次地址重规划(痛苦但一劳永逸),要么在网关层做地址转换,把重叠段映射成不重叠的段再进隧道。后者能应急,但排障复杂度上一个台阶,我一般只在没法改地址的时候用。
真遇到"同一个目的段,不同来源要走不同 Peer"这种需求(比如按业务分流),AllowedIPs 这层就管不了了,得往下沉到策略路由:用 Table = off 关掉自动路由,然后自己配 ip rule + 多张路由表,按源地址或者 fwmark 分流。这一步已经超出 WireGuard 本身的范畴,是 Linux 路由的基本功,配之前先把 ip rule 的输出看明白。
wg show(或者 wg show wg0)的输出里,每个 Peer 有几行,真正决定成败的只有三行。
另外两行顺手也看:allowed ips 确认生效的网段是不是你写的那些(改配置后有没有真的应用),persistent keepalive 确认保活是不是配上了(显示 "off" 就是没配)。
握手通了、流量也涨了,业务还是不通,那问题多半在路由或者 MTU 上。路由这层用 ip route get 目标地址,它会直接告诉你这个包会走哪个接口、从哪个地址出去——比肉眼看 ip route 那张表直观得多。期望走 wg0 却走了 eth0,那就是 AllowedIPs 或者路由优先级的问题。
再往下就是抓包:tcpdump -ni eth0 udp port 51820 看物理口上有没有 UDP 包进出,tcpdump -ni wg0 看隧道内部有没有明文业务包。两边对照着看,能立刻区分"包根本没发出去"、"发出去没加密"、"加密了但没到"这几种情况。抓包时注意:wg0 上看到的是解密后的明文,如果 wg0 上能看到请求但看不到响应,问题在对端回程;两边都没有,问题在发出侧。
我自己用的顺序是这样的,从下往上走,每一步都能排除一大片可能:先 ip link 确认接口起来了、物理口 MTU 是多少;再 wg show 看握手和流量;握手不通就 tcpdump 物理口看 UDP 有没有进出,同时确认防火墙和安全组;握手通了业务不通就 ip route get 验路由;路由对了还不行,就用 DF 位 ping 测 MTU。五步走完,WireGuard 的故障基本都能定位到具体那一行配置。
跨机房组网里,中转节点(hub)是最吃资源的那台机器——所有跨机房流量都要过它,加密解密、小包转发、可能还要跑路由守护进程。这种位置我一般不建议用云主机凑合,核数不够就是瓶颈,而且共享型的机器在持续高负载下表现不稳定。
一万网络的裸金属 E5-2698v4×2,官网明示档 ¥3999 起(以官网实时价为准),双路 E5 的核心数是够用的,拿来当 hub 节点正合适:核多,UDP 小包转发的软中断能分散到多个核上;内存插槽多,跑路由表和连接跟踪不吃力;物理机独占,不会因为邻居抢资源导致你排查时看到莫名其妙的抖动。一万网络深耕 IDC 19 年(成立于 2007 年),深圳南山总部,自营机柜最快 1 分钟上架,机器是全新超微、DELL 品牌机,硬件故障 10 分钟自动迁移——对组网这种"一台挂了全网受影响"的角色,迁移速度比什么都实在。
星型拓扑里,spoke 那一端往往不需要多强的性能——它就是把自己机房的流量收上来,往 hub 一丢。这种节点铺得越多,越该控制成本。一万云 ¥25 起(A 类官网明示档,以官网实时价为准)就适合放在这类位置:轻量、开得快、按月走,后面业务增长再升配或者换成裸金属,不用一上来就押重注。
网络这块是我更看重的:一万网络走 BGP 多线 + CN2 GIA 回国,华南、华东、华北、中国香港及海外多节点可选。跨机房互联的体验,很大程度上取决于你选的那几个机房之间的链路质量,而不是你在服务器上怎么调优。所以真要拉跨地域的隧道,先在候选节点各开一台最低配,自己跑几天 ping 和 mtr,看晚高峰的抖动,再决定 hub 放哪。
服务上也有几条对运维友好的:7×24 中文工单,平均 5 分钟响应;免费 5-20G DDoS 防护;免费系统盘快照(每日 3 份 / 30 秒回滚);免费网站备案协助;工程师可 1 对 1 协助部署环境。隧道配崩了、系统改坏了,有快照能回滚,有工单能问,这两条在半夜出事的时候价值最高。资质方面持增值电信业务经营许可证、国家高新技术企业、专精特新,涉及合规架构的可以提供咨询与协助。产品优势统一口径为 T3+ 安全数据中心、BGP 线路、顶级网络 99.9% 在线保证。
全互联(full mesh)的意思是任意两台机器之间都直接建隧道,任意两点一跳可达,延迟最优、没有单点。听着很美,代价是隧道条数按 N×(N-1)/2 增长:5 台机器是 10 条,10 台是 45 条,20 台就是 190 条。每台机器上还要维护 N-1 个 Peer 段,加一台机器就得改所有机器的配置。规模一上来,配置量和出错概率都是爆炸的——而且这种错误特别隐蔽,改错一台就是一个机房失联。
我的经验线是:七八台以内、且拓扑长期稳定,全互联可以手动维护;超过这个规模,就别硬扛了。
星型(hub-spoke)是所有 spoke 只跟 hub 建隧道,spoke 之间走 hub 转发。隧道条数变成 N-1,加机器只改两台的配置,管理成本低一个数量级。代价也清楚:hub 挂了全网瘫,跨 spoke 的流量多一跳。
所以 hub 要高可用。最简做法是两个 hub,spoke 上配两个 Peer,但 AllowedIPs 相同会造成前面说的重叠问题——正确做法是两条隧道用不同的网段,spoke 侧分别写两段 AllowedIPs,再靠路由优先级或者路由协议选路。跑 BGP 或者 OSPF over WireGuard 是完全可行的,因为它是三层隧道,组播受限但点对点的单播路由协议能跑起来(静态邻居要手动配)。这一步已经算正经的网络工程了,做之前把路由协议的邻居状态机搞明白。
如果机器数量已经到了"手动改配置"不可接受的程度,就别再跟配置文件较劲了,去用别人的控制面。业界有一类方案是在 WireGuard 之上加一层控制平面,自动分发密钥和 Peer 配置、自动处理 NAT 穿透和节点发现,运维只管在页面上加机器。这类方案 worth 一提的包括 Tailscale、Netmaker 这类(具体选型和是否付费以各自官网为准)。
它们的底层还是 WireGuard,所以这篇讲的三件事一个都没少——MTU 照样要算,保活照样要有,AllowedIPs 照样不能重叠,只是这些由控制面替你维护了。但反过来,一旦出问题,你排查的还是 wg show 那几行。底层原理懂了,用任何封装都不会抓瞎。
为什么坑:1420 是"物理口 1500 + IPv4 承载 + 留余量"这个前提下的值。云主机网卡、PPPoE、开了巨帧的内网、套了别的封装的链路,物理口有效 MTU 都可能不是 1500。前提不成立,抄来的数字就是错的,而且症状是"小包通大包死"这种最不好查的样子。
怎么避:配之前先 ip link show 看物理口真实 MTU,再按"物理口 MTU − 开销 − 余量"算。写完立刻用 ping -M do -s 二分验证,把测出来的值记进拓扑文档,别记在脑子里。
为什么坑:WireGuard 不做打洞,NAT 映射靠流量维持。没保活,映射老化之后对端就打不进来,现象是"内网那台连得出去,外面连不进来",而且刚连过时还能连、过一会儿就不行,极易误判成网络抖动。
怎么避:凡是 Peer 在 NAT 后面(包括云主机的内网地址、机房做了地址转换的场景),一律在那一侧加 PersistentKeepalive = 25。别管它跑不跑业务流量,这一行的成本可以忽略。
为什么坑:一个 Peer 写了 0.0.0.0/0,wg-quick 会为此加特殊路由规则接管默认路由;多个 Peer 都这么写,路由就彻底打架,你的默认出口可能被悄悄换掉,表现为"隧道一起来,某些外部访问就断了"。
怎么避:只在真的要把它当默认出口时才写 0.0.0.0/0,且全篇只写一次。其他场景老老实实写具体网段;需要自己管路由就加 Table = off,然后手动 ip route 或者跑路由协议。
为什么坑:WireGuard 只跑 UDP。安全组、iptables、机房边界 ACL 任何一层只放行 TCP,结果就是握手永远不成功,而接口看着是 up 的、路由也在,很容易让人怀疑人生。另外把 ICMP 全丢了会直接制造 PMTU 黑洞。
怎么避:三层检查:云平台安全组、系统防火墙、机房侧 ACL。放 UDP 的 ListenPort,同时不要一刀切丢掉 ICMP 的"需要分片"差错报文——至少对互联的网段放行。下单前也要确认该机房线路对 UDP 没有限制策略。
为什么坑:WireGuard 的包头带时间戳(TAI64N 格式),用来防重放攻击。接收方会拒绝时间戳落在窗口之外的包。两台机器时钟差太多,会出现握手时好时坏、间歇性不通的现象,而且日志里不一定有明显报错。
怎么避:所有组网节点统一上 NTP,timedatectl 确认同步状态,时钟源指向同一组上游。这条在跨地域、跨运营商的机房之间尤其要检查,新机器上架第一时间配好。
主要是内核和模块。Linux 5.6 及以后内核自带 WireGuard,直接 modprobe wireguard 就能用;老内核需要装 DKMS 版本的 wireguard-dkms 或者用用户态实现,用户态转发性能会差一些(具体差距以实测为准)。另外要确认宿主机的虚拟化方式和内核是否允许加载模块——部分云主机用的是裁剪过的内核,装不了 DKMS,这种机器上就得换镜像或者改用用户态方案。CPU 方面没有门槛,前面说过 ChaCha20 在老 CPU 上也不吃亏,真正吃紧的是小包速率和高核数。租机器时把"能否加载内核模块 / 内核版本多少"问清楚,比问配置更重要。
九成是 MTU。ping 默认发的包只有几十字节,再大的封装开销也扛得住,所以 ping 通只能证明链路通、密钥对、路由对,证明不了大包能过。而网页的资源、TLS 记录、scp 的数据块都是大包,一旦超过路径 MTU 且 ICMP 不可达被丢,就形成黑洞,表现就是卡住不动直到超时。验证方法是用 ping -M do -s 1472 逐档往下试,找到能过的最大尺寸,再按封装开销反推接口 MTU。改完之后要重新用大包验证一遍,不要只看 ping 通不通。另外顺手确认防火墙没有把 ICMP 的差错报文全丢掉。
常用 25 秒,这是个保守值,比绝大多数 NAT 设备的会话老化时间都短,基本不会踩空。如果你明确知道对端 NAT 老化时间更长(比如某些企业网关是几分钟),设 60 秒也能省点心跳流量,但收益很小,不值得为此做调研。反过来说,别设成 0 或者干脆不写——那就是没有保活。需要注意的是这一行要写在被 NAT 挡住的那一侧的 [Peer] 段里,写在公网侧没用。配完用 wg show 确认 persistent keepalive 那一行显示的不是 off。
WireGuard 自己解决不了,它没有任何打洞和转发的第三方机制。可行的做法只有一条:找一台有公网可达 UDP 地址的机器当中转,两侧都跟它建隧道,流量由它转发。所以做多机房规划时,第一件事是确认每个节点能不能拿到公网地址——这直接决定了你的拓扑是什么样的。中转节点的选址要实测:向候选机房要测试 IP,跑几天 ping 和 mtr,重点看晚高峰的延迟和抖动,别只看机房宣传。同时中转点本身要按关键节点对待,做好高可用。
不能,或者更准确地说,写了一定会出问题。0.0.0.0/0 会让 wg-quick 为该 Peer 添加接管默认路由的规则,多个 Peer 都这么写,这些规则就互相覆盖,你的默认出口变得不可预测,常见症状是隧道一起来,服务器访问某些外部地址就断了。正确做法是:只在确实要把它当默认出口的那个 Peer 上写一次;其他 Peer 写具体网段;需要完全自己掌控路由就在 [Interface] 加 Table = off,然后手动写路由或者跑路由协议。改完用 ip route get 逐个验。
没有统一答案,取决于 CPU。ChaCha20 是纯软件友好的算法,在没有 AES-NI 指令集的老 CPU 上通常比 AES-GCM 快;而现代 CPU 带 AES-NI 硬件加速,内核态 IPsec 在纯吞吐上可能占优(差距以实测为准,别信任何拍脑袋的百分比)。但选型时我更看重另外两点:一是代码量,WireGuard 内核模块数千行量级,审计和定位都容易;二是无连接带来的运维手感,节点 IP 变了能自动漫游,不用等隧道重建。真要在你的场景里分高下,就拿你的实际业务流量在两端各压一轮,那才是能写进报告的数字。
适合,但别再用手工配置硬扛。全互联的隧道条数是 N×(N-1)/2,二十台就是一百九十条,加一台机器要改二十台的配置,这个复杂度下出错是必然的。做法是分两层:拓扑上改星型,每个机房出一到两台汇聚节点,hub 做高可用;管理上引入控制面,让密钥分发、Peer 下发、节点发现自动完成。底层依然是 WireGuard,所以 MTU、保活、AllowedIPs 这三件事一件都没少,只是由控制面统一维护。出问题时你排查的仍然是 wg show 那几行输出,底层原理掌握住就不慌。
跨机房组网这件事,WireGuard 把最难的部分——加密、密钥交换、防重放、防 DoS——全都替你做完了,而且做得没什么可配的。剩下交给你管的,恰恰是三个看起来最不起眼的小参数:MTU、PersistentKeepalive、AllowedIPs。这三处出问题的概率,比加密出问题的概率高两个数量级,而且症状全都长成一个样子——"配好了,但就是不通"。
所以别一上来就纠结吞吐能跑多少、延迟能压到几毫秒。先把这三件事做对:接口 MTU 按物理口实际值算并用 DF 位 ping 验证,NAT 后面的 Peer 一律加 25 秒保活,AllowedIPs 按一张提前画好的网段表对称着写、绝不重叠。做完这些再谈性能调优,否则你测出来的所有数字都是在一个坏地基上测的。
机器选型上我的建议也很直接:汇聚节点用核数足的物理机,别让加密和转发卡在 CPU 上;分支节点按需铺,控制成本;机房之间先实测链路再定 hub 放哪。一万网络深耕 IDC 19 年(成立于 2007 年),BGP 多线 + CN2 GIA 回国,华南、华东、华北、中国香港及海外多节点可选,裸金属 E5-2698v4×2 ¥3999 起、一万云 ¥25 起(均为官网明示档,以官网实时价为准),从汇聚到分支能一套配齐,7×24 中文工单平均 5 分钟响应,硬件故障 10 分钟自动迁移,出问题有人接。把这三件小事做对,剩下的就是把业务跑起来。
本文涉及的 WireGuard 机制说明(三层 UDP 承载、Noise_IKpsk2 握手与固定密码套件、封装开销与默认 MTU、PersistentKeepalive 保活行为、AllowedIPs 的路由与 ACL 双重语义、最长前缀匹配选路、roaming 与握手计时器)均来自 WireGuard 官方白皮书与公开文档,属公开技术机制;涉及具体数值的部分(封装开销 32/80 字节、默认 MTU 1420、保活间隔 25 秒、NAT 会话老化时间、性能对比)以你自己环境的实测为准,本文不作任何吞吐、延迟、丢包率的承诺与 benchmark 结论。
一万网络相关报价与资质锚点来自官网公示信息:一万云 ¥25 起、裸金属 E5-2698v4×2 ¥3999 起,均为官网明示档,以官网实时价为准;文中若出现推算或行业参考性质的价格,均为预估价格,以咨询为准。完整产品、报价与最新活动请以官网为准:https://www.idc10000.net/。具体以签约时最新报价与合同为准。
本文所述组网方案仅适用于服务器之间的合规互联场景,包括多机房内网打通、业务内网互联、运维管理通道等,需遵守所在地区法律法规与机房管理规定。
Copyright © 2013-2020 idc10000.net. All Rights Reserved. 一万网络 科技有限公司 版权所有 深圳市科技有限公司 粤ICP备07026347号
本网站的域名注册业务代理北京新网数码信息技术有限公司的产品