핑은 되고 작은 API 요청도 잘 되는데, 큰 응답이나 파일 업로드·VPN 너머 통신만 멈춥니다. SSH 접속은 되는데 ls 긴 출력에서 멈추는 식의 증상도 같은 부류입니다. 이렇게 "작은 건 되고 큰 건 안 되는" 패턴은 거의 항상 MTU와 단편화 문제입니다.
왜 생기나
경로 어딘가의 링크 MTU(보통 1500)가 더 작은데(터널·VXLAN·PPPoE는 1400대), DF(Don't Fragment) 비트가 붙은 큰 패킷이 그 구간을 못 지나갑니다. 정상이라면 라우터가 "더 잘게 쪼개라"는 ICMP를 돌려보내지만(Path MTU Discovery), 방화벽이 그 ICMP를 막으면 패킷은 조용히 버려지고 연결이 멈춥니다. 이걸 PMTUD 블랙홀이라 합니다.
DF 비트로 경로 MTU 측정
패킷 크기를 키워가며 "쪼개지 말고" 보냅니다. 어디서부터 깨지는지가 경로 MTU입니다.
# 리눅스: -M do = DF 비트 ON, -s = 페이로드 크기
ping -M do -s 1472 8.8.8.8 # 1472+28(헤더)=1500
ping -M do -s 1473 8.8.8.8
# 1472는 성공, 1473부터 실패하면 경로 MTU=1500 (정상)
1473 bytes ... Message too long # 로컬에서 거부 → 더 줄여 테스트
... 100% packet loss # 응답 없음 → 중간 구간이 드롭(블랙홀)
성공하는 가장 큰 -s 값 + 28이 경로 MTU입니다. 가령 -s 1372까지만 되면 경로 MTU는 1400입니다.
증상별 해석과 해결
| 증상 | 원인 | 해결 |
|---|---|---|
Message too long | 로컬 인터페이스 MTU가 작음 | NIC MTU 확인·조정 |
| 특정 크기 이상 100% loss | 경로 중간 MTU 작음 + ICMP 차단 | MSS 클램핑 또는 MTU 낮추기 |
| 큰 응답만 행(hang) | TCP가 PMTUD 블랙홀 | MSS 클램핑 |
MSS 클램핑 — 단편화 자체를 피하도록 TCP가 협상하는 세그먼트 크기를 경로 MTU에 맞춰 깎습니다. 게이트웨이·라우터에서 가장 안정적인 해결책입니다.
# MTU 1400 경로면 MSS = 1400 - 40 = 1360
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1360
# 또는 경로에 자동 맞춤
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
인터페이스 MTU를 직접 낮추는 것(ip link set dev eth0 mtu 1400)도 방법이지만, 통신 양단 모두에 영향을 줘 MSS 클램핑이 더 국소적입니다.
진단 체크리스트
ip link show eth0 | grep mtu # 로컬 MTU 확인
ping -M do -s 1472 <대상> # DF로 1500 통과 여부
ping -M do -s 1372 <대상> # 1400 경로 의심 시
ip route get <대상> # 경로·게이트웨이
# 작은 패킷 OK + 큰 패킷만 loss → MTU/단편화 확정
"작은 건 되는데 큰 건 안 된다"가 보이면 앱이 아니라 경로 MTU를 먼저 의심하세요.
DF 비트 핑으로 경로 MTU를 직접 측정하고 MSS 클램핑을 적용하는 실습은 네트워크 트랙에서 회원가입 없이 무료로 할 수 있습니다.