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。