MTU 设置多少合适?大包黑洞导致 HTTPS 卡住与 API 超时的排查方法
MTU 设置多少合适,答案取决于你这台机器到目标之间最窄的那一段:普通以太网和 Wi-Fi 局域网是 1500,PPPoE 拨号线路一般是 1492,再套一层 VPN、隧道或容器网络,就要在此基础上减掉封装开销。大多数时候不需要手动改 MTU。只有出现“小请求正常、大包卡死”这类症状,并且用下文的二分法确认路径 MTU 比网卡 MTU 小时,才需要动它。
什么症状说明可能是 MTU 黑洞?
MTU 问题很少表现为“完全不通”,更常见的是“通一半”:
ping能通,DNS 能解析,TCP 三次握手也能完成,但 HTTPS 停在 TLS 握手阶段,过一会儿超时。- 网页能打开框架,图片或大的 JS 文件一直转圈;有些站点正常,有些站点打不开。
git clone、npm install下到一半停住,没有报错。- 调 AI API 时,短请求正常返回;请求体带长上下文或文件时一直等不到响应。
- SSH 能登录,执行
cat一个大文件或ls -la一个大目录时终端卡住。
这些现象的共同点是:小包能过,满尺寸的大包过不去,而且没人告诉发送方“包太大了”。
为什么大包会悄无声息地消失?
每条链路都有自己能承载的最大 IP 包长度,就是 MTU。一条路径上最小的那个 MTU 叫路径 MTU(PMTU)。
正常情况下,发送方给 TCP 包打上 DF(不允许分片)标记,某一跳发现包太大,会丢掉它并回一条 ICMP 消息:IPv4 是 “Fragmentation Needed”(类型 3 代码 4),IPv6 是 “Packet Too Big”。发送方收到后调小包长重发,这个过程叫路径 MTU 发现(PMTUD)。
问题出在中间某台防火墙、云安全组或运营商设备把这类 ICMP 丢掉了。发送方收不到提示,就一直重传同样大小的包,结果一直被丢,这就是“MTU 黑洞”。
TLS 握手容易中招,是因为客户端的 ClientHello 通常不大,能顺利发出去;服务器回来的 ServerHello 加证书链往往有好几 KB,会被切成满尺寸的 TCP 段,正好撞上黑洞。用 curl -v 看,就是停在 TLSv1.3 (OUT), TLS handshake, Client hello 之后再没有下文。另外,新版浏览器和部分 TLS 库启用了后量子密钥交换,ClientHello 本身就可能超过一个包,上行方向也会受影响。
如果你想先把“连不上”这类问题按层分清楚,可以对照 Claude Code 连接超时和报错怎么排查:四层网络检查清单,MTU 属于其中“TCP 能通、TLS 不通”的那一类。
常见场景下 MTU 应该是多少?
下表的 MSS 指 IPv4 下 TCP 每段能携带的最大数据量,等于 MTU 减去 IP 头 20 字节和 TCP 头 20 字节(IPv6 要减 60)。
| 场景 | 典型 MTU | 对应 IPv4 MSS | 说明 |
|---|---|---|---|
| 普通以太网、Wi-Fi 局域网 | 1500 | 1460 | 默认值,一般不用改;上游是 PPPoE 时,出网路径仍是 1492 |
| PPPoE 拨号接口(光猫桥接、路由器拨号) | 1492 | 1452 | PPPoE 头占 8 字节 |
| GRE 隧道 | 1476 | 1436 | GRE 封装占 24 字节 |
| WireGuard(wg-quick 默认) | 1420 | 1380 | 按外层 IPv6 留了余量 |
| VXLAN 等 overlay 容器网络 | 1450 | 1410 | 封装占 50 字节 |
| IPv6 规定的最小值 | 1280 | — | 任何 IPv6 链路都不能低于它 |
这些数会叠加。例如,假设你在 PPPoE 线路上跑 WireGuard,WireGuard 里又跑 Docker 的 overlay 网络,每一层都要从上一层的 MTU 里扣开销。叠到第三层时,如果某一层还按 1500 配置,就会出现黑洞。
怎么测出自己的路径 MTU?三平台命令对照
思路是发带 DF 标记的 ping,逐步调整数据长度,找到“刚好能通”的最大值,再加上 28 字节(IPv4 头 20 + ICMP 头 8)就是路径 MTU。IPv6 要加 48。
第一步:选一个回应 ping 的目标
很多网站的服务器不回 ICMP,所有尺寸都会超时,测不出结果。先用默认大小 ping 一次,确认目标会回包。可以选公共 DNS 的地址,或者你实际出问题的那台 API 服务器(前提是它回 ping)。如果对 ICMP 和 TCP 探测的区别还不熟,可以先看 ping 不通但网站能打开?ICMP ping 与 tcping 的区别和正确用法。
第二步:用 1472 测试 1500 是否完整可用
| 系统 | 命令 | 包太大时的典型输出 |
|---|---|---|
| Windows | ping -f -l 1472 1.1.1.1 | 需要拆分数据包但是设置 DF。 / Packet needs to be fragmented but DF set. |
| Linux | ping -M do -s 1472 -c 3 1.1.1.1 | Frag needed and DF set (mtu = 1492) 或 message too long |
| macOS | ping -D -s 1472 -c 3 1.1.1.1 | sendto: Message too long 或直接超时 |
-f(Windows)、-M do(Linux)、-D(macOS)都是设置 DF 标记;-l 和 -s 指定 ICMP 数据长度。
1472 能通,说明到这个目标的路径支持 1500,MTU 大概率不是问题所在,可以直接跳到最后一节。
第三步:不通就二分
在 1200 和 1472 之间二分。例如:
- 测 1336,通了,说明上限在 1336 到 1472 之间。
- 测 1404,不通,上限在 1336 到 1404 之间。
- 测 1370,通了;再测 1387……
- 直到相差 1 字节,取能通的最大值 N,路径 MTU = N + 28。
有个容易误判的情况要注意:如果“包太大”时既没有报错也没有回包,只是超时,这本身就是黑洞的证据,说明中间设备在丢包却不回 ICMP。
Linux 可以直接用 tracepath
tracepath -n api.example.com
# 输出末尾类似:Resume: pmtu 1420 hops 12 back 12
tracepath 会逐跳报告 pmtu 变化,能看出是哪一跳开始变小。逐跳输出的读法可以参考 traceroute 和 mtr 结果怎么看。
用 curl 确认是不是卡在 TLS
curl -v --max-time 15 -o /dev/null https://api.example.com/
如果停在 Client hello 之后超时,而把本机 MTU 临时调小后立刻正常,基本可以确认是 MTU 黑洞。
测出来之后怎么改?
先看当前 MTU
# Windows(管理员 PowerShell 或 CMD)
netsh interface ipv4 show subinterfaces
# Linux
ip link show
# macOS
networksetup -getMTU en0
临时改小,验证效果
# Windows:接口名以上一步输出为准,store=active 重启后失效
netsh interface ipv4 set subinterface "以太网" mtu=1400 store=active
# Linux:重启后失效
sudo ip link set dev eth0 mtu 1400
# macOS
sudo networksetup -setMTU en0 1400
先用比测量值再小一点的数(比如测出 1420 就先设 1400)验证问题是否消失,确认后再改成测量值,并写进持久配置:Windows 用 store=persistent,Linux 写到 NetworkManager、netplan 或 systemd-networkd 的配置里。
隧道和容器单独设置
- WireGuard:在
[Interface]里写MTU = 1380这类值,按外层路径 MTU 减 60(外层 IPv4)或 80(外层 IPv6)计算。 - Docker:在
/etc/docker/daemon.json里设置"mtu": 1400,重启 Docker。宿主机走 VPN 时,容器内默认的 1500 是常见的黑洞来源。 - Kubernetes:在 CNI 插件的配置里设置,不同插件字段不同,以对应文档为准。
MSS clamping 是什么,什么时候用?
改 MTU 只对本机发出的包有效。如果你管理的是路由器、网关或 VPN 服务器,后面有很多设备,逐台改不现实,这时用 MSS clamping:在 TCP 握手的 SYN 包经过时,把里面声明的 MSS 改小,让两端从一开始就不发超过路径 MTU 的段。它不依赖 ICMP,所以能绕开被丢弃的 PMTUD 消息。
# iptables
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
# nftables
nft add rule inet filter forward tcp flags syn tcp option maxseg size set rt mtu
--clamp-mss-to-pmtu 按出接口的 MTU 自动计算。如果出接口 MTU 本身配置得没错,但更远处还有一段更窄的链路,就要用 --set-mss 1360 这样的固定值。不少家用路由器在 PPPoE 模式下默认开启了这项设置,自建的 VPN 网关则容易漏配。
只有 Linux 客户端、又没法改网络设备时,可以打开 TCP 层的 MTU 探测作为兜底:
sudo sysctl -w net.ipv4.tcp_mtu_probing=1
它会在检测到黑洞后自动降低段长,代价是第一次卡住时要等一次重传超时才会降下来。注意它只作用于 TCP,对 QUIC/UDP 没有作用。
什么时候不该改 MTU?
- 1472 能通。路径支持 1500 时把 MTU 调小,只会增加头部开销的占比,问题应该在别处。
- 所有尺寸都超时。很可能是目标不回 ICMP,或者根本不通,先查 DNS 和路由。解析层面的问题可以先看 开发者网络自检清单(2026 版)。
- 流式输出在固定时长后中断。例如每次都在大约同一个秒数断开,更像是代理或负载均衡的空闲超时,与包大小无关。
- 只有 IPv6 有问题。先确认是不是 IPv6 出口和 IPv4 出口走了不同路径,参见 IPv6 代理不生效:双栈网络下出口不一致的原因与排查。另外 IPv6 的 MTU 不要设到 1280 以下。
- 改了网卡 MTU 但走的是代理软件。部分代理以 TUN 虚拟网卡工作,要改的是那块虚拟网卡或代理软件里的 MTU 设置,而不是物理网卡。
用 cdnping 交叉验证
改完以后可以打开 cdnping 在线测速,看各家 AI API 的“首次连接”能否正常完成。这一项包含 DNS 和 TLS 握手,MTU 黑洞通常会让它超时或明显变长,而“往返”这一项在连接复用后测量,受影响较小。两个数字的含义在 AI API 延迟拆解:连接建立、网关往返与首 token 时间 里有详细说明。
如果只有某一家打不开,先到 API 状态 看它的官方入口在 cdnping 边缘探测里是否正常,排除对方故障。如果你在用 VPN 或分流,也可以到 IP 与环境检测 确认实际出口和分流结果,判断大包走的是哪条路径。
一页检查表
- 症状是否是“小请求通、大响应卡”,
curl -v是否停在 TLS 握手。 - 用带 DF 的 ping 测 1472;不通就二分,路径 MTU = 最大通过值 + 28。
- 数一数路径上叠了几层封装:PPPoE、VPN、隧道、容器网络。
- 临时调小本机或虚拟网卡 MTU,确认问题消失后再持久化。
- 管理网关时用 MSS clamping,不要让每台设备各自改。
- 1472 能通、或问题与包大小无关时,不要动 MTU。