한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

게임 렉 백서 › TCP 재전송의 근본 원인

중간 장비의 TCP 옵션 제거 Middlebox strips TCP options

원인 ID rt-sack-stripped · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라

그림과 실험이 있는 원본 카드로 열기 →

일부 방화벽·가속 장비가 TCP 옵션을 지우거나 고치면, 여러 개를 잃었을 때 한 왕복에 하나씩만 복구하거나 윈도우(한 번에 보낼 수 있는 양)가 작아져 느려집니다.

왜 방화벽의 “TCP 정규화”, 오래된 가속 장비가 SACK·타임스탬프·윈도우 스케일 옵션을 제거 → 그러면 잃은 패킷이 여러 개면 왕복마다 하나씩 복구, 윈도우가 64KB로 제한됨 → 화면에서는 손실마다 멈춤이 훨씬 길어지고(SACK이 없으면 RACK-TLP도 못 씀) 풀리면 몰아치기. 패치 같은 대용량 전송도 느림

증상
멈춤, 몰아치기
요인
정체, 지연
누가 겪나
특정 지역·통신사, 서버 전체
언제
항상
담당
주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라
인프라팀 할 일
네트워크: 해당 장비의 TCP 정규화 설정 끄기, 방화벽의 시퀀스 번호 무작위화도 확인, 양쪽 끝 패킷 캡처로 SYN의 옵션 비교. 서버 장비·OS: ss -ti에서 sack·wscale 표시가 빠진 연결이 특정 경로에 몰리는지 확인(ts는 윈도우 PC가 설정에 따라 쓰지 않으므로 ts만 빠진 것은 정상일 수 있음), 서버의 net.ipv4.tcp_sack이 1인지 확인.
그래프에서는
처음부터 늘 높음 · SACK 없이 시작한 복구 수(TcpExtTCPRenoRecovery)
확인할 곳
ss -ti에서 연결마다 sack·wscale 표시가 있는지 보고 nstat의 TcpExtTCPRenoRecovery(SACK 없이 시작한 복구)와 TcpExtTCPSackRecovery의 비율, TcpExtTCPSACKDiscard(앞뒤가 맞지 않아 버린 SACK 블록 수)를 봄. 의심 경로는 양쪽 끝에서 SYN을 캡처해 옵션(Wireshark의 tcp.options.sack_perm 등)을 비교함
이러면 맞음
특정 경로·장비를 지나는 연결만 sack·wscale이 빠져 있고 TcpExtTCPRenoRecovery 비중이 높음. 보낸 쪽 SYN에 있던 SACK 허용 옵션이 받은 쪽 SYN에는 없음. 시퀀스 번호 무작위화가 원인이면 옵션은 남아 있는데 TcpExtTCPSACKDiscard가 늘어남
이러면 아님
모든 연결에서 sack이 빠져 있으면 서버의 net.ipv4.tcp_sack 값부터 확인. 옵션이 온전하고 TcpExtTCPSACKDiscard도 그대로면 복구가 느린 이유는 다른 곳(“thin stream의 느린 복구”)
확인 수단
인프라 도구로 확인(게임 코드 불필요)
더 알아보기
옵션이 남아 있어도 SACK이 망가질 수 있습니다. 방화벽의 시퀀스 번호 무작위화(sequence randomization)가 헤더의 시퀀스 번호만 바꾸고 SACK 안의 번호는 그대로 두면, 보내는 쪽은 앞뒤가 맞지 않는 SACK을 버립니다. 2019년 SACK 보안 문제 때 서버에서 tcp_sack=0으로 꺼 두고 잊은 경우도 결과가 같습니다.

출처

  1. RFC 2018: TCP Selective Acknowledgment Options IETF
    SACK 없이 누적 ACK만으로는 왕복마다 잃은 패킷 하나만 알 수 있음
  2. RFC 7323: TCP Extensions for High Performance IETF
    윈도우 스케일 옵션이 없으면 윈도우는 최대 2^16 = 64KiB
  3. RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP IETF
    RACK-TLP는 SACK 사용이 필수
  4. net/ipv4/tcp_output.c Linux kernel
    리눅스 TLP는 SACK을 쓰는 연결에서만 예약됨
  5. IP Sysctl Linux kernel
    tcp_sack 기본 1(켜짐)
  6. misc/ss.c iproute2
    ss -ti는 연결이 쓰는 옵션에 따라 ts, sack, wscale:송신,수신을 표시
  7. tcp: limit payload size of sacked skbs Linux kernel
    2019년 SACK 처리 취약점(CVE-2019-11477) 수정 커밋
  8. Linux and FreeBSD Kernel: Multiple TCP-based remote denial of service vulnerabilities (NFLX-2019-001) Netflix
    당시 임시 대책으로 tcp_sack=0(SACK 처리 끄기)이 안내됨
  9. SNMP counter Linux kernel
    TcpExtTCPRenoRecovery(SACK 없이 복구 시작)·TcpExtTCPSackRecovery(SACK으로 복구 시작), TcpExtTCPSACKDiscard(유효하지 않은 SACK 블록 수)
  10. Display Filter Reference: Transmission Control Protocol Wireshark
    tcp.options.sack_perm(SYN의 SACK 허용 옵션) 표시 필터

함께 보면 좋은 원인

같은 층: TCP 재전송의 근본 원인

같은 증상(멈춤)의 다른 층 원인

그림과 실험이 있는 원본 카드 보기