MTU & fragmentation — vì sao ping được mà app timeout
MTU, phân mảnh IP, Path MTU Discovery và PMTUD black-hole — khi firewall chặn ICMP khiến gói lớn bị drop âm thầm, ping thông nhưng TLS handshake treo.
TL;DR: MTU (Maximum Transmission Unit) là kích thước tối đa một frame Ethernet có thể mang — thường 1500 byte cho mạng LAN. Gói IP lớn hơn MTU phải bị phân mảnh (fragment) rồi ráp lại ở đích. Path MTU Discovery (PMTUD) tránh phân mảnh bằng cách tìm MTU nhỏ nhất trên toàn tuyến đường — dùng cờ Don't Fragment kết hợp ICMP "Fragmentation Needed". PMTUD black-hole xảy ra khi firewall chặn ICMP đó: sender không biết phải giảm kích thước gói, gói lớn bị drop âm thầm — ping (gói nhỏ) thông nhưng TLS handshake hoặc HTTP response lớn treo không giải thích được.
Bạn đang debug một service có hành vi kỳ lạ: ping tới server thành công, curl HTTP response nhỏ cũng thành công, nhưng khi response lớn hơn (JSON vài KB, file download) thì kết nối treo rồi timeout. Thêm VPN vào thì mọi thứ đều chậm hơn. Không có lỗi rõ ràng trong log.
Đây là dấu hiệu kinh điển của PMTUD black-hole — một trong những vấn đề mạng khó debug nhất vì nó chọn lọc theo kích thước gói, không phải theo protocol hay port.
1. Analogy — Gói hàng qua nhiều hầm đường bộ
Hình dung bạn gửi một thùng hàng lớn từ Hà Nội tới TP.HCM qua xe tải. Tuyến đường đi qua nhiều hầm. Hầm bình thường cao 4.5m, nhưng có một hầm giữa đường chỉ cao 3.2m — xe tải cao quá không vào được.
Hai cách giải quyết:
- Phân mảnh tại chỗ: tháo thùng ra, chia làm nhiều kiện nhỏ vừa hầm, gửi từng kiện, ráp lại ở đích. Phức tạp, dễ mất kiện.
- Biết trước và điều chỉnh: trước khi lên đường, khảo sát chiều cao tất cả hầm, chọn xe tải vừa hầm thấp nhất. Không cần tháo ra.
TCP/IP làm theo cách thứ hai — đó là PMTUD. Vấn đề xảy ra khi hầm không đặt biển báo chiều cao mà chỉ chặn xe lại không báo gì cả — đó là PMTUD black-hole.
| Vận chuyển hàng | Mạng TCP/IP |
|---|---|
| Chiều cao tối đa của hầm | MTU — kích thước frame tối đa |
| Chia thùng thành nhiều kiện | Phân mảnh IP (fragmentation) |
| Khảo sát chiều cao mọi hầm | Path MTU Discovery |
| Hầm chặn xe không báo lý do | PMTUD black-hole (ICMP bị chặn) |
| Xe tải điều chỉnh kích thước tải | TCP MSS clamping |
MTU = giới hạn kích thước gói của một chặng mạng cụ thể. Path MTU = MTU nhỏ nhất trên toàn tuyến. PMTUD = cơ chế tìm Path MTU trước khi gửi. Black-hole = khi cơ chế đó bị phá vỡ do firewall chặn ICMP.
2. MTU — kích thước frame tối đa
MTU (Maximum Transmission Unit) là số byte tối đa của phần dữ liệu (payload) mà một frame ở tầng Link có thể mang, không tính header tầng Link.
Ethernet IEEE 802.3 chuẩn: MTU = 1500 byte. Đây là giá trị được hard-code vào tiêu chuẩn Ethernet từ năm 1980 và vẫn còn phổ biến tới ngày nay. Một số mạng nội bộ data center dùng Jumbo Frame với MTU 9000 byte để tối ưu throughput — nhưng chỉ hoạt động khi toàn bộ đường mạng hỗ trợ.
# Xem MTU cua cac interface
ip link show
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
# 5: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 (WireGuard)
# 4: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 (PPPoE)
Tại sao 1500 byte? Ethernet ban đầu dùng dây đồng trục chung (bus topology), tất cả máy tranh nhau một dây. Gói quá lớn → một máy chiếm dây quá lâu → các máy khác chờ lâu. 1500 byte là điểm cân bằng giữa hiệu quả (header overhead ít) và công bằng (không chiếm kênh quá lâu). Giá trị này được giữ nguyên khi chuyển sang Ethernet hiện đại để đảm bảo tương thích.
Cấu trúc gói trên đường truyền — phần header chiếm không gian của 1500 byte:
20 byte
20 byte
tối đa 1460 byte = MSS
Đây là lý do MSS (Maximum Segment Size) của TCP thường là 1460 byte = 1500 (MTU) − 20 (IP header) − 20 (TCP header). MSS được trao đổi trong gói SYN/SYN-ACK của handshake — xem bài 02 — TCP reliability.
3. Fragmentation — phân mảnh khi gói quá lớn
Khi một gói IP lớn hơn MTU của chặng tiếp theo, router phải phân mảnh (fragment) gói đó thành nhiều mảnh nhỏ hơn. Mỗi mảnh được đóng gói thành frame riêng và gửi đi.
Cơ chế phân mảnh tầng IP:
- Mỗi mảnh mang Fragment Offset (offset trong gói gốc tính bằng đơn vị 8 byte) và cờ More Fragments (MF) cho biết còn mảnh tiếp theo.
- Mảnh cuối có MF = 0.
- Reassembly (ráp lại) xảy ra tại đích cuối cùng — không phải tại router trung gian (khác IPv4 reassembly trong IPv6 — IPv6 không cho phép fragmentation tại router).
sequenceDiagram
participant C as Client
participant R as Router (MTU 1500)
participant S as Server
C->>R: IP packet 2800 byte (qua len MTU)
Note over R: Fragment thanh 2 manh
R->>S: Fragment 1 (1480 byte data, MF=1, offset=0)
R->>S: Fragment 2 (1320 byte data, MF=0, offset=185)
Note over S: Reassemble --> 2800 byte gocVấn đề của fragmentation:
- Hiệu năng kém: router trung gian phải xử lý thêm; đích phải buffer tất cả mảnh trước khi xử lý.
- Mảnh mồ côi: nếu 1 mảnh bị mất, toàn bộ gói phải truyền lại — TCP retransmit cả packet, không phải từng mảnh.
- Firewall stateless: nhiều firewall chỉ inspect mảnh đầu tiên (chứa TCP/UDP header); mảnh sau thiếu header → không lọc được.
- Không thể dùng với IPv6: IPv6 không cho phép router fragment — sender phải tự fragment trước khi gửi.
Đây là lý do TCP hiện đại tránh fragmentation — thay vào đó dùng PMTUD để biết trước MTU và điều chỉnh kích thước segment.
4. Path MTU Discovery — tìm MTU nhỏ nhất trên toàn tuyến
PMTUD (Path MTU Discovery) là cơ chế cho phép TCP sender tự động tìm ra MTU nhỏ nhất trên toàn tuyến đường từ sender tới receiver, mà không cần phân mảnh.
Cơ chế (RFC 1191):
- TCP sender đặt cờ Don't Fragment (DF) trong header IP — báo router "đừng phân mảnh gói này".
- Sender gửi gói với kích thước lớn nhất có thể (thường = MTU của interface đầu ra).
- Nếu một router trên đường thấy gói lớn hơn MTU của chặng tiếp theo, nó không thể fragment (do DF=1) → gửi lại ICMP type 3 code 4: "Fragmentation Needed and DF Set", kèm MTU của chặng đó.
- Sender nhận ICMP, cập nhật PMTU cache, giảm kích thước gói và thử lại.
- Lặp cho đến khi tìm ra MTU nhỏ nhất.
sequenceDiagram
participant C as Client (MTU 1500)
participant R as Router (MTU 1400)
participant S as Server
C->>R: IP 1500 byte, DF=1
Note over R: MTU 1400 < 1500, khong the fragment (DF=1)
R-->>C: ICMP Type 3 Code 4: "Frag Needed, MTU=1400"
Note over C: Cap nhat PMTU cache: 1400
C->>R: IP 1400 byte, DF=1
R->>S: IP 1400 byte (vua MTU)
S-->>C: ACKTest PMTU thủ công:
# Test MTU toi destination (goi 1472 byte data + 28 byte IP/ICMP header = 1500)
ping -M do -s 1472 8.8.8.8
# PING 8.8.8.8 (8.8.8.8) 1472(1500) bytes of data.
# 1472 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=15.2 ms
# Neu MTU thap hon:
ping -M do -s 1472 vpn-server
# ping: local error: message too long, mtu=1420
# -> MTU toi vpn-server chi 1420
# Xem PMTU cache
ip route get 8.8.8.8
# 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.100
# (cache co the co them: cache mtu 1420)
5. PMTUD black-hole — khi ICMP bị chặn
PMTUD black-hole là tình trạng PMTUD bị phá vỡ vì firewall hoặc security group chặn gói ICMP type 3 code 4 ("Fragmentation Needed").
Cơ chế gây ra black-hole:
sequenceDiagram
participant C as Client
participant F as Firewall (chặn ICMP)
participant R as Router (MTU 1400)
participant S as Server
C->>R: IP 1500 byte, DF=1
R-->>F: ICMP: "Frag Needed, MTU=1400"
Note over F: DROP ICMP (firewall rule)
Note over C: Khong nhan duoc ICMP, van giu MTU 1500
C->>R: IP 1500 byte, DF=1 (retry)
R-->>F: ICMP (bi drop lai)
Note over C: TCP retransmit... -> ETIMEDOUTTại sao ping vẫn thông? ping gửi gói ICMP nhỏ — mặc định 56 byte data (84 byte tổng). Gói này nhỏ hơn MTU của mọi chặng → không cần fragmentation → PMTUD không kích hoạt → không cần ICMP type 3 → ping thành công.
Nhưng TLS handshake hoặc HTTP response lớn thất bại:
- TLS
ClientHellothường 300-500 byte — qua được. - TLS
Certificatetừ server thường 2-4 KB — bị router muốn fragment nhưng DF=1 → gửi ICMP → firewall chặn → client không nhận → treo. - HTTP response lớn (JSON, HTML) tương tự.
Các môi trường hay gặp PMTUD black-hole:
- VPN (WireGuard, IPsec, OpenVPN): thêm header VPN vào mỗi gói → MTU hiệu dụng giảm. WireGuard giảm 60 byte (header 40 byte + overhead), IPsec giảm 50-85 byte. Interface MTU thường đặt 1420 hoặc 1280 nhưng nếu không config đúng → black-hole.
- PPPoE (ADSL/FTTH nhiều ISP Việt Nam): thêm 8 byte header PPPoE → MTU giảm từ 1500 xuống 1492.
- GRE tunnel, VXLAN: thêm header → giảm MTU.
- Firewall corporate block "all ICMP": quản trị viên chặn hết ICMP vì sợ ICMP flood, vô tình chặn cả type 3 code 4 cần thiết cho PMTUD.
6. Chẩn đoán và fix PMTUD black-hole
Bước 1: Xác nhận là black-hole bằng ping DF bit:
# Test voi payload tang dan cho den khi that bai
ping -M do -s 1400 target-server # OK?
ping -M do -s 1450 target-server # OK?
ping -M do -s 1472 target-server # Fail? -> MTU nam o dau do
# Ket qua:
# s=1400 OK, s=1450 FAIL -> MTU khoang 1428 (1450 + 28 header = 1478 > MTU)
Bước 2: Tìm MTU của interface và tunnel:
ip link show
# eth0: mtu 1500
# wg0: mtu 1420
# Voi Docker
ip link show docker0
# docker0: mtu 1500 (nhung container co the khac)
Bước 3: Fix — ba cách tiếp cận:
a) MSS Clamping (khuyến nghị cho router/firewall): Thay vì phụ thuộc vào PMTUD, router rewrite trường MSS trong SYN/SYN-ACK để TCP tự giới hạn segment size:
# iptables MSS clamping (Linux router/VPN server)
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
# Hoac set manual (vi du voi WireGuard MTU 1420):
# MSS = 1420 - 40 (IP+TCP header) = 1380
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1380
b) Giảm MTU của interface:
# Set MTU cho interface
ip link set dev wg0 mtu 1380
# Permanent (systemd-networkd)
# /etc/systemd/network/wg0.network
# [Link]
# MTUBytes=1380
c) Allow ICMP type 3 qua firewall:
# iptables: allow ICMP fragmentation-needed
iptables -A INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type fragmentation-needed -j ACCEPT
# AWS Security Group: add inbound rule
# Type: Custom ICMP - IPv4, Protocol: Destination Unreachable (3)
WireGuard mặc định MTU 1420 byte; OpenVPN thường 1500 nhưng cần tính lại với overhead. Docker và Kubernetes tạo virtual interface với MTU bằng interface host — nếu host là VM trong cloud với MTU 9000 (jumbo) nhưng external network chỉ 1500, container gửi gói 9000 byte ra ngoài → black-hole. Khi deploy service mới và thấy "ping OK nhưng response lớn fail", kiểm tra MTU của tất cả interface trên đường đi trước.
7. Pitfall — nhầm lẫn thường gặp
❌ Nhầm 1: "Ping được là network ổn, lỗi do code."
✅ Ping dùng ICMP gói nhỏ — không đụng fragmentation, không đụng PMTUD. Hoàn toàn có thể ping thông mà TCP data lớn vẫn timeout. Test bằng ping -M do -s 1472 hoặc nc -zv để kiểm tra TCP thật sự.
❌ Nhầm 2: "Tôi đã cấu hình VPN với MTU 1420, nên ổn rồi." ✅ MTU 1420 trên interface WireGuard là đúng, nhưng MSS clamping có được cấu hình chưa? Nếu TCP hai đầu thương lượng MSS dựa trên interface đầu ra (không phải WireGuard), segment có thể vẫn lớn hơn 1420 − 40 = 1380. Cần cả MSS clamping và MTU đúng.
❌ Nhầm 3: "Fragmentation giải quyết được hết, không cần lo MTU." ✅ Fragmentation là cơ chế fallback tệ: hiệu năng kém, không dùng được với IPv6, firewall stateless không inspect được. TCP hiện đại cố tránh fragmentation bằng PMTUD. Firewall chặn ICMP type 3 code 4 phá vỡ cơ chế đó — đây là root cause của black-hole.
❌ Nhầm 4: "Chặn tất cả ICMP để an toàn." ✅ ICMP type 3 code 4 ("Fragmentation Needed") là cần thiết cho PMTUD — chặn nó phá vỡ TCP cho gói lớn. Chặn hết ICMP là over-blocking. Rule đúng: block ICMP echo (ping) nếu muốn ẩn host, nhưng allow ICMP type 3 và type 11 (TTL exceeded — cần cho traceroute).
8. Liên hệ các bài khác
- Bài 02 — TCP reliability: MSS được trao đổi trong SYN/SYN-ACK của handshake — đây là cơ chế TCP tự giới hạn segment size dựa trên MTU, trước khi cần PMTUD.
- Bài 07 — Lỗi mạng thường gặp: PMTUD black-hole biểu hiện như
ETIMEDOUT— gói bị drop âm thầm giống firewall DROP. Bài 07 cung cấp bảng tra để phân biệt các loại timeout. - Khoá Foundations — Mô hình TCP/IP 4 tầng: MTU là khái niệm tầng Link (Layer 2), nhưng phân mảnh xảy ra ở tầng Internet (Layer 3). Hiểu phân tầng giúp định vị đúng nơi MTU áp dụng.
9. 📚 Deep Dive — RFC và tài liệu gốc
Đọc khi muốn đi tới tận gốc:
- RFC 1191 — Path MTU Discovery — đặc tả gốc của PMTUD cho IPv4, mô tả cơ chế DF bit + ICMP Fragmentation Needed.
- RFC 8899 — Packetization Layer Path MTU Discovery for Datagram Transports (PLPMTUD) — phiên bản hiện đại hơn, không phụ thuộc ICMP, dùng cho QUIC và SCTP.
- RFC 4821 — Packetization Layer Path MTU Discovery — PLPMTUD cho TCP, probe bằng cách thay đổi kích thước segment thay vì dựa vào ICMP.
Ghi chú: RFC 1191 là nền tảng cần đọc để hiểu cơ chế gốc. RFC 8899 giải thích tại sao QUIC (HTTP/3) tránh được vấn đề PMTUD black-hole — QUIC thực hiện PLPMTUD trong tầng ứng dụng, không phụ thuộc ICMP tầng mạng.
10. Tóm tắt
- MTU là kích thước frame tối đa một chặng mạng có thể mang. Ethernet thường 1500 byte; VPN/tunnel giảm xuống 1420 hoặc ít hơn do thêm header.
- MSS = MTU − 40 byte (IP + TCP header) = thường 1460 byte — kích thước tối đa của một TCP segment. Được thương lượng trong SYN/SYN-ACK.
- Fragmentation xảy ra khi gói lớn hơn MTU của chặng tiếp theo. Tốn kém, không dùng được với IPv6 — TCP hiện đại tránh bằng cách dùng PMTUD.
- PMTUD đặt cờ DF=1 và dựa vào ICMP type 3 code 4 từ router để tìm MTU nhỏ nhất trên toàn tuyến.
- PMTUD black-hole xảy ra khi firewall chặn ICMP type 3 code 4: gói lớn bị drop im lặng, sender không biết giảm kích thước. Biểu hiện: ping thông, gói nhỏ thông, gói lớn (TLS certificate, HTTP response lớn) treo.
- Hay gặp với VPN: WireGuard, IPsec, PPPoE đều thêm overhead, giảm MTU hiệu dụng. Cần cấu hình MSS clamping và MTU đúng trên interface tunnel.
- Fix: MSS clamping tại router/VPN (
--clamp-mss-to-pmtu), giảm MTU interface, hoặc allow ICMP type 3 qua firewall. - Test:
ping -M do -s 1472 <host>để xác nhận MTU có vấn đề không.
11. Tự kiểm tra
Q1Vì sao MTU Ethernet là 1500 byte và giá trị này còn tồn tại đến ngày nay?▸
Q2Tại sao TCP MSS thường là 1460 byte, không phải 1500 byte?▸
Q3Bạn cài WireGuard VPN với MTU mặc định 1420 trên interface wg0. Kết nối qua VPN hoạt động nhưng các trang web nặng load chậm hoặc treo. Nghi ngờ gì và kiểm tra thế nào?▸
ping -M do -s 1372 vpn-server (1372 + 28 header = 1400 < 1420). Fix: cấu hình MSS clamping với --clamp-mss-to-pmtu hoặc set MSS thủ công 1380.Q4Vì sao IPv6 không cho phép router fragment gói tin, trong khi IPv4 thì cho phép?▸
Q5Ping tới server thành công nhưng TLS handshake bị treo. Giải thích cơ chế PMTUD black-hole gây ra điều này.▸
Q6So sánh hai cách fix PMTUD black-hole: MSS clamping và giảm MTU interface. Khi nào dùng cái nào?▸
- Giảm MTU interface: cấu hình trực tiếp trên interface VPN/tunnel (ví dụ
ip link set wg0 mtu 1380). Đơn giản, hiệu quả khi bạn kiểm soát được endpoint. Nhưng cần cấu hình đúng trên cả hai đầu và persist qua reboot. - MSS clamping (
--clamp-mss-to-pmtu): router rewrite trường MSS trong SYN/SYN-ACK để TCP tự giới hạn. Hoạt động ngay cả khi sender và receiver không biết MTU thấp — router lo hết. Ưu tiên cho VPN gateway hoặc firewall phải handle nhiều client.
Trong thực tế: dùng cả hai — giảm MTU interface để đúng về mặt nguyên lý, thêm MSS clamping làm backstop. Cho phép ICMP type 3 qua firewall là fix căn gốc nếu có thể.
Bài tiếp theo: Module 1 — Tổng kết & cheat sheet
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên