MTU 블랙홀: 작은 요청은 되는데 업로드가 멈추는 이유
작은 요청은 끝나는데 큰 업로드는 영원히 멈춰 있고, 보낸 쪽은 경로가 더 좁다는 사실을 결코 알지 못한다. 끊어지는 정확한 크기를 측정하라.
페이지가 로드되고, 작은 API 호출이 돌아오고, 그다음 파일 업로드가 클라이언트가 포기할 때까지 멈춰 있다. 서버 로그에는 이를 설명하는 것이 없다, 패킷이 경로 중간에서 쓸모 있는 응답도 없이 버려졌기 때문이다. 이 패턴이 MTU 블랙홀이다, 보낸 쪽이 가정한 것보다 좁은 링크에 그 사실을 말하지 않는 침묵의 거부가 더해진 것이다. 실패하는 크기는 반복 가능하며, 그래서 진단할 수 있다.
구멍을 검게 만드는 것
모든 링크에는 최대 전송 단위가 있고, 다음 홉의 한도보다 큰 패킷은 단편화되거나 그 사실을 알리는 ICMP 메시지로 거부되어야 한다. 경로 MTU 탐색은 그 메시지가 도착하고 존중되는지에 달려 있다. 그것을 필터링하거나 무시하면 보낸 쪽은 절대 들어가지 않을 패킷을 계속 다시 보낸다.
캡슐화는 VPN 주변에서 이것을 흔하게 만든다, 터널이 이미 물리 링크에 맞춰진 패킷에 바깥 헤더를 붙이기 때문이다. 안쪽 패킷은 1500바이트에서 합법이지만 캡슐화된 패킷은 아니어서 경계에서 죽고, 작은 패킷들은 통과한다. 완료된 핸드셰이크와 작동하는 로그인 페이지는 작은 패킷이 작동한다는 것만 증명한다. 애플리케이션이 보내려는 가장 큰 패킷이 중요한 것이다.
끊어지는 크기를 찾아라
단편화하지 않는 테스트로 페이로드 크기를 이진 탐색하라, 터널 한쪽 호스트에서 다른 쪽 호스트까지. 통과하는 가장 큰 페이로드가 사용 가능한 경로 MTU에서 헤더 오버헤드를 뺀 값이다.
ping -M do -s 1400 -c 2 192.0.2.20
ping -M do -s 1200 -c 2 192.0.2.20
ping -f -l 1372 192.0.2.20
1472바이트 페이로드는 IPv4와 ICMP 헤더 28바이트를 더하면 깨끗한 1500바이트 Ethernet 경로를 통과한다. 터널을 올린 뒤 같은 테스트가 더 작은 페이로드에서만 통과한다면, 그 차이가 캡슐화 오버헤드이고 터널 경계가 거부 메시지가 생성되었어야 할 곳이다. 연결 전과 후의 두 숫자를 모두 기록하라, 그 쌍이 증거다. 애플리케이션이 IPv6를 쓸 때는 같은 테스트를 반복하라, 헤더가 더 크고 실패 임계값이 움직이기 때문이다.
터널을 탓하기 전에 증거를 읽어라
원격 애플리케이션 오류, 혼잡, 일반적인 손실도 업로드를 멈춘다, 그래서 한 번의 실패한 전송으로 블랙홀을 식별할 수 없다. 이들을 구분하는 것은 크기 관계로, 1200바이트에서 반복되는 성공과 1400바이트에서 반복되는 정지, 같은 방향, 같은 종단점을 통해서다.
양쪽 끝에서 캡처하면 큰 패킷이 나가서 도착하지 않고 그 사이에 거부도 없음을 보여 준다. 그때 서버가 아니라 경계 장비를 봐야 한다, 서버는 실제로 받은 모든 요청에 응답하고 있기 때문이다. 혼잡도 멈추게 하지만 서로 다른 크기를 서로 다른 시각에 멈추게 하며, 그것은 다른 서명이다.
두 전송 방식 모두에서 수리를 확인하라
지원되는 수리는 경계가 실제 한도를 보고하게 하거나, 거기서 TCP의 최대 세그먼트 크기를 조여 너무 큰 세그먼트를 시도하지 않게 하는 것이다. 네트워크의 모든 MTU를 낮추거나 방화벽을 끄면 증상을 숨기고 나중에 아무도 따질 수 없는 구성을 남긴다.
ip link show dev tun0
sudo nft list ruleset | grep -i -E 'mtu|mss'
sysctl net.ipv4.tcp_mtu_probing
ping -M do -s 1400 -c 2 192.0.2.20
같은 크기 테스트로 확인하고, 다음으로 실패한 애플리케이션으로 확인하고, 두 번째 프로토콜도 점검하라, UDP 애플리케이션은 TCP의 세그먼트 크기 보정을 결코 받지 않기 때문이다. 티켓에 원래 값을 남겨라, 되돌릴 수 없는 수리는 일어나기를 기다리는 두 번째 문제다. 크기 테스트가 통과하는데 업로드가 여전히 멈춘다면 블랙홀이 원인이 아니었으므로, 변경을 넓히지 말고 조사를 계속해야 한다.