VPN MTU 신화: 패킷이 줄어드는 이유와 공간이 어디로 가는가
캡슐화와 PPPoE가 패킷 공간을 잡아먹지만, 낮은 MTU는 진단이 아니다. 숫자를 바꾸기 전에 안쪽과 바깥쪽 크기를 분리하라.
누군가 VPN이 "MTU 때문에 패킷을 잃고 있다"고 말하고, 터널을 1400으로 설정하니 전송이 다시 동작한다. 그 결과는 진단처럼 느껴진다. 보통은 산술적 우연이다 — 한 번도 확인하지 않은 한계 아래에 들어가도록 충분히 작은 숫자를 고른 것뿐이고, 다음 네트워크에서는 다른 예산으로 같은 한계를 다시 만나게 된다.
이 대부분을 두 가지 신화가 만든다. 첫째는 터널 인터페이스의 MTU가 경로의 MTU라는 것이다. 둘째는 캡슐화 비용이 "헤더 하나"이고 PPPoE는 셀 가치도 없다는 것이다. 둘 다, 고른 숫자가 자의적으로 보이지만 실제로는 정해져 있다는 식으로 틀렸다.
신화 하나: 터널의 MTU가 경로의 MTU다
터널 인터페이스에 설정하는 값은 구현이 아래로 넘길 가장 큰 안쪽 패킷에 대한 국소적 약속이다. 경로의 실제 용량은 당신과 먼 쪽 끝 사이의 모든 링크의 속성이며, 경로가 바뀔 때, 모바일 연결이 핸드오버될 때, 트래픽이 다른 피어링을 탈 때 달라질 수 있다. 설정된 1500은 당신의 호스트가 무엇을 만들지 알려줄 뿐, 네트워크가 무엇을 실어 나를지는 알려주지 않는다.
경로 MTU 탐색은 이 둘을 조화시키기 위해 존재하고, 피드백에 의존한다. IPv4에서 전체 크기 패킷을 전달할 수 없는 라우터는 ICMP "fragmentation needed" 메시지를 보내야 하고, 보낸 쪽은 추정치를 낮춘다. IPv6에서는 그에 해당하는 것이 Packet Too Big 메시지이고, 라우터는 전송 중에 전혀 단편화하지 않는다. 그 피드백이 걸러지면 보낸 쪽은 경로가 실을 수 없는 패킷을 계속 만들고, 아무도 이유를 알려주지 않는다.
신화 둘: 캡슐화 비용은 헤더 하나다
바깥 계층을 정직하게 세어 보라. 바깥 IP 헤더는 IPv4에서 20바이트, IPv6에서 40바이트다. NAT 통과를 위한 UDP 캡슐화가 8을 더한다. 터널 프로토콜은 자신의 헤더, 초기화 벡터 또는 nonce, 암호의 블록 또는 정렬 경계까지의 패딩, 트레일러, 무결성 검사 값을 더한다. 프로토콜과 암호에 따라 합계는 안쪽 패킷이 시작되기도 전에 넉넉히 수십 바이트에 이른다.
그다음 안쪽 패킷 자체의 헤더를 다시 빼라. 터널 안의 TCP 세그먼트는 자기 20바이트 IP 헤더와 20바이트 TCP 헤더를 실어 나르고, TCP의 MSS는 터널의 명목 페이로드가 아니라 MTU에서 나온다. 그래서 ping는 작은 페이로드로 성공하는데 파일 전송은 멈춘다 — 도구들이 서로 다른 것을 시험하고 있고, 그중 하나만 전체 크기 TCP 세그먼트를 실제로 쓰기 때문이다.
ip link show tun0
ping -M do -s 1472 192.0.2.10
ping -M do -s 1400 192.0.2.10
첫 명령은 설정된 터널 MTU를 보고한다. 두 프로브는 1472바이트 페이로드를 보내는데, IPv4와 ICMP 헤더 28바이트를 더하면 1500바이트 패킷이 되고, 그다음 더 작은 것을 보낸다. 큰 프로브가 완전히 실패하고 작은 것이 성공한다면, 경로 전체의 문제가 아니라 크기에 의존하는 결함이다.
신화 셋: PPPoE는 여전히 깨끗한 1500을 준다
전통적인 PPPoE 액세스 링크는 1500바이트 IP 패킷을 실어 나르지 않는다. PPPoE 헤더와 PPP 프로토콜 필드가 이더넷 프레임 안에서 8바이트를 차지해 IP 패킷에 1492가 남는다. 이것이 RFC 2516에 설명된 전통적 한계다. 그런 링크 위에서 VPN을 돌리면 터널 오버헤드는 1500이 아니라 그 1492에서 나온다.
RFC 4638은 액세스 집선 장치와 고객 장비가 모두 지원할 때 더 큰 PPP 페이로드를 협상하는 방법을 정의하며, 그래서 "이 연결은 PPPoE를 쓴다"는 것만으로는 특정 숫자를 증명하지 못한다. 국소 설정은 한 번도 구성된 적 없는 패킷을 중간 장비가 받아들이게 강제할 수 없으므로, 유용한 질문은 레이블이 무엇을 말하는지가 아니라 링크가 실제로 무엇을 협상했는지다.
실패가 선택적으로 보이는 이유
작은 요청은 성공하고 큰 전송은 멈추는 것은 경로 MTU 블랙홀의 전형적인 서명이다. 핸드셰이크, DNS 질의, API 호출은 모두 들어가지만, 대량 전송은 한 링크에서 죽는 전체 크기 세그먼트를 만들고, 문제를 알렸어야 할 ICMP 메시지는 끝내 도착하지 않는다. 연결은 멀쩡해 보이고 다운로드는 멈추므로, 사람들은 경로 대신 서버를 들여다보게 된다.
두 번째, 관련된 실수는 세 숫자를 혼동하는 것이다 — 인터페이스 MTU, TCP MSS, 그리고 프로토콜 자체의 단편화나 패딩 설정. 라우터의 MSS 클램핑은 광고되는 MSS를 다시 써서 보낸 쪽이 더 작은 세그먼트를 만들게 할 뿐, 터널 MTU를 바꾸지도 않고 UDP 트래픽을 돕지도 않는다. 관련 있어 보인다고 셋에 같은 숫자를 주는 것이, 선의의 변경이 동작하는 구성을 깨뜨리는 방식이다.
무엇을 어떤 순서로 바꿀까
증거로 시작하라. 위 프로브로 결함이 크기에 의존함을 확인하고, 통과하는 가장 작은 크기와 실패하는 가장 큰 크기를 찾아라. 터널을 탓하기 전에 액세스 링크의 실제 MTU를 확인하라(PPPoE 링크는 VPN이 닿기 전에 예산을 제한한다). 변경을 되돌릴 수 있도록 원래 값을 기록해 두라.
그다음 클라이언트가 문서화한 가장 작은 조정을 적용하라. 많은 클라이언트가 터널 MTU와 MSS 수정 옵션을 제공하고, MSS 옵션은 모든 패킷을 줄이지 않고 보낸 쪽에 닿으므로 TCP에 더 나은 지렛대인 경우가 많다. 같은 목적지와 같은 전송을 다시 시험하고, 정착한 숫자를 기록하라. 한 액세스 네트워크에서 동작하는 터널 값은 보편 상수가 아니며, 다음 현장에는 자기 예산이 있다.