GRO Hid My TLS Handshake's Real Packet Split, Even Over a Real Network
GRO가 가린 TLS 핸드셰이크의 실제 패킷 분할
양자내성 TLS ClientHello가 실제 인터넷 경로에서 TCP 세그먼트 두 개로 나뉘는지 확인한 실험입니다. 수신 측 GRO가 패킷을 합쳐 tcpdump에 한 개로 보이게 했으며, GRO를 끈 뒤 1448바이트와 42바이트 세그먼트로 나뉜 기록을 얻었습니다.
- 주제
AI 요약
글쓴이는 Caddy의 기본 양자내성 TLS 핸드셰이크를 측정한 이전 글에서 ClientHello가 318바이트에서 약 1490바이트로 커진다고 보고했습니다. 일반적인 경로의 MSS를 넘는 크기라 TCP 세그먼트가 둘로 나뉘어야 한다는 계산이 나왔지만, 실제 외부 네트워크에서도 분할되는지 패킷 캡처로 확인한 것은 아니었습니다. 이번 글은 클라우드 VM을 마련해 실제 인터넷 경로에서 이를 검증합니다.
Docker 실험과 외부 서버
앞선 실험은 한 컴퓨터의 Docker 브리지에서 Caddy와 클라이언트를 실행했습니다. 이 환경에서는 Generic Segmentation Offload(GSO)가 큰 버퍼를 가상 인터페이스로 넘기고, 실제 분할을 나중으로 미룰 수 있습니다. 두 컨테이너 사이에 MTU 제한이 있는 물리적 링크가 없으므로 tcpdump가 실제 전송 단위와 다른 패킷을 보여줄 수 있습니다.
글쓴이는 DigitalOcean의 작은 Ubuntu VM을 만들고 Caddy를 Docker의 host 네트워크 모드로 실행했습니다. 노트북에서 OpenSSL 클라이언트를 연결해 tcpdump로 확인하자, MSS가 1460인 연결에서 ClientHello 1490바이트가 한 패킷으로 기록됐습니다. 실제 외부 서버를 썼는데도 기대한 두 세그먼트가 보이지 않았습니다.
수신 오프로딩이 패킷을 합쳤습니다
원인은 서버 NIC의 Generic Receive Offload(GRO)였습니다. GRO는 연속해서 도착한 TCP 세그먼트들을 커널 네트워크 스택에 전달하기 전에 하나의 버퍼로 합칩니다. 기본 설정에서는 패킷 캡처 지점이 이 재조립 뒤에 있으므로 tcpdump가 여러 세그먼트 대신 합쳐진 데이터를 기록할 수 있습니다.
글쓴이의 노트북 NIC는 실제 이더넷 프레임 두 개를 보냈고, 중간 라우터들도 두 패킷을 전달했습니다. 하지만 서버 커널이 tcpdump보다 먼저 이를 하나로 합쳤습니다. 인터넷을 가로질러 별도 서버에 연결하는 것만으로는 실제 세그먼트 수를 확인하기에 충분하지 않았습니다.
GRO를 끈 뒤 두 세그먼트를 확인했습니다
서버에서 ethtool -K eth0 gro off gso off tso off를 실행해 오프로딩을 끄고 같은 연결을 다시 캡처했습니다. 이번에는 첫 세그먼트가 1448바이트, 두 번째가 42바이트로 기록됐습니다. 합계는 앞서 확인한 ClientHello 크기와 같은 1490바이트입니다. 두 패킷은 마이크로초 단위로 거의 동시에 도착했지만, 서로 다른 TCP 시퀀스 범위를 가졌습니다.
비교를 위해 고전적인 X25519 그룹을 사용한 ClientHello도 같은 방식으로 캡처했습니다. 이 요청은 오프로딩을 켜거나 끈 상태 모두 312바이트짜리 단일 패킷으로 남았습니다. 따라서 양자내성 그룹 X25519MLKEM768을 사용한 ClientHello가 실제 외부 경로에서 두 TCP 세그먼트로 나뉜다는 점을 확인했습니다.
확인한 범위와 재현 방법
이번 실험은 양자내성 ClientHello가 두 세그먼트로 전송된다는 전제만 검증합니다. 글에서 다룬 패킷 손실에 따른 지연을 같은 실험에서 재현하지는 않았습니다. 두 번째 세그먼트를 잃으면 빠른 재전송이 일어나지 않고 타임아웃으로 이어지는 동작은 별도 로컬 링크에서 tc netem으로 측정한 결과라고 설명합니다. 이번 캡처는 두 세그먼트라는 조건이 로컬 네트워크의 인공물이 아니라 실제 인터넷 경로에서도 성립함을 보완합니다.
글쓴이는 DigitalOcean 명령을 예시로 들지만, 별도 커널을 쓰는 외부 호스트라면 다른 클라우드 제공업체도 사용할 수 있다고 안내합니다. 전체 시험은 약 10분 걸렸고 VM을 바로 삭제해 비용은 1센트 미만이었습니다. 네트워크에서 세그먼트 분할 여부를 측정할 때는 캡처 결과를 신뢰하기 전에 ethtool -k로 GRO, GSO, TSO 설정을 확인하라고 권합니다.
원문: dev.to / 번역·요약: Trawling