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

ゲームラグ白書 › TCP再送の根本原因

中間機器によるTCPオプションの除去 Middlebox strips TCP options

原因ID rt-sack-stripped · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ

図と実験のあるメインページでこのカードを開く →

一部のファイアウォール・高速化装置がTCPオプションを消したり書き換えたりすると、複数のパケットを失ったときに1往復に1つずつしか回復できなくなったり、ウィンドウ(一度に送れる量)が小さくなったりして遅くなります。

なぜ ファイアウォールの「TCP正規化」、古い高速化装置がSACK・タイムスタンプ・ウィンドウスケールのオプションを除去 → すると 失ったパケットが複数あると1往復ごとに1つずつ回復、ウィンドウは64KBに制限される → 画面では パケットロスのたびに止まる時間がずっと長くなり(SACKがないとRACK-TLPも使えない)、解消すると早送り。アップデートデータのダウンロードのような大容量の転送も遅い

症状
フリーズ, 早送り
要因
ストール, 遅延
誰に起きるか
特定の地域・ISP, サーバー全体
いつ
常に
担当
主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ
インフラチームの対応
ネットワーク:該当機器のTCP正規化の設定を無効にする、ファイアウォールのシーケンス番号ランダム化も確認、両端のパケットキャプチャでSYNのオプションを比較。サーバー機器・OS:ss -tiでsack・wscaleの表示がない接続が特定の経路に偏っていないか確認(tsはWindows 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だけでは、1往復ごとに失ったパケットを1つしか把握できない
  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
    Linuxの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再送の根本原因

同じ症状(フリーズ)を起こすほかの層の原因

図と実験のあるメインページでこのカードを見る