0

WireGuard 隧道 MTU 设置不当导致的部分网站无法正常访问的问题

Share
Avatar photo
  • 2025 年 12 月 24 日

背景

近期在配置某专用链路时,通过Wireguard转发三层数据包,遇到了一个较为隐蔽的问题:
从本地路由通过 WireGuard 接入专用链路出网后,部分网站无法访问

问题表现具有明显的迷惑性:

  • 同一条出口链路;
  • 同一台主机;
  • 有些网站完全正常,有些却始终无法打开;
  • 失败的网站以 GitHub、部分海外 HTTPS 站点为主。

初看非常像 DNS、封锁、TLS 或证书问题,但最终发现根因其实非常基础:WireGuard 隧道 MTU 设置不当

本文记录一次完整的排障过程。


一、问题现象

以 GitHub 为例,访问表现如下:

  • 浏览器长时间 loading;
  • 不报明确错误;
  • 命令行工具也无法返回结果。

curl 表现

curl -v https://www.github.com

输出卡在 TLS 握手阶段:

*   Trying 20.27.177.113:443...
* Connected to www.github.com (20.27.177.113) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):

可以明确看到:

  • DNS 解析成功;
  • TCP 443 已连接;
  • ClientHello 已发送;
  • TLS 握手卡死,无任何 ServerHello 返回

二、初步排除:不是 TCP、不是 DNS

为了进一步确认 TLS 层问题,使用 openssl s_client

openssl s_client -connect github.com:443 -servername example.com
CONNECTED(00000003)

以及直接指定 IP:

openssl s_client -connect 20.27.177.113:443
CONNECTED(00000003)

CONNECTED 表示:

  • TCP 连接在内核层面完全正常;
  • 但 TLS 协商无法继续。

至此可以基本排除:

  • DNS 错误;
  • 路由不可达;
  • 防火墙阻断 443;
  • 服务器端口不可用。

三、WireGuard 接口抓包分析

既然业务流量全部经由 WireGuard 隧道出网,问题极有可能发生在隧道层。

于是直接在 WireGuard 接口 wg0 上抓包:

tcpdump -i wg0 | grep 20.27.177.113

1. TCP 三次握手完全正常

10.100.1.10 > 20.27.177.113: SYN
20.27.177.113 > 10.100.1.10: SYN, ACK
10.100.1.10 > 20.27.177.113: ACK

说明隧道双向连通性没有问题

2. TLS ClientHello 成功发送

Flags [P.], seq 1:318, length 317

ClientHello 包体积较小,顺利通过隧道。

3. 服务端返回大包后异常

Flags [P.], seq 2849:3619, length 770

这是服务端返回的第一批 TLS 握手数据(ServerHello + 证书等)。

紧接着客户端行为异常:

Flags [.], sack {2849:3619}
Flags [R.]

表现为:

  • 出现 SACK(选择确认);
  • 连接被异常 reset。

这是 MTU / 分片问题的典型特征

小包能过,大包在隧道或中间链路被丢弃或破坏。


四、为什么“只有部分网站”受影响?

这是该问题最具迷惑性的地方。

原因在于:

  • 不同站点 TLS 握手阶段返回数据大小不同;
  • GitHub 等站点证书链较长、TLS 扩展较多;
  • 返回方向第一批 TLS 数据更容易超过实际可用 MTU;
  • 一旦发生分片,而链路又不支持或错误处理分片,就会直接失败。

因此表象上看是“随机网站异常”,实际上是确定性的 MTU 边界触发问题


五、根因确认:WireGuard MTU 设置不合理

WireGuard 默认 MTU 为 1420,但在以下场景中容易出问题:

  • 专线 / MPLS / GRE / 二次隧道;
  • 运营商或中间设备不支持分片;
  • 额外封装导致有效 MTU 进一步下降。

当前链路实际可用 MTU 明显小于 WireGuard 默认值。


六、解决方案

在 WireGuard 接口中显式设置较小 MTU:

[Interface]
MTU = 1280

重启 WireGuard 后验证:

  • curl 可完整返回 HTTP 响应;
  • openssl s_client 能正确输出证书链;
  • wg0 抓包中 TLS 返回包正常;
  • 不再出现异常 SACK 或 RST。

问题彻底消失。


七、经验总结 / Checklist

当出现以下现象时,应优先怀疑 MTU 问题

  • TCP 能连,TLS 卡死;
  • curl 停在 Client hello
  • 只影响 HTTPS、大站点更容易失败;
  • ICMP 不可达或 PMTU 发现被屏蔽;
  • 使用隧道(WireGuard / IPsec / GRE / VXLAN)。

排查顺序建议:

  1. curl -v 看卡在哪一层
  2. openssl s_client 验证 TLS
  3. 在隧道接口抓包观察包大小
  4. 临时降低 MTU 验证结论