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

遊戲 Lag 白皮書 › TCP 重傳的根本原因

中間設備移除 TCP 選項 Middlebox strips TCP options

原因 ID rt-sack-stripped · 主要負責 基礎設施團隊(網路基礎設施) · 協同 基礎設施團隊(伺服器基礎設施)

在含圖解與實驗的完整版中開啟卡片 →

部分防火牆或加速設備刪除或改寫 TCP 選項時,遺失多個封包後一個往返只能復原一個,或是視窗(一次可送出的量)變小,傳輸因此變慢。

為什麼 防火牆的「TCP 正規化」、老舊的加速設備移除 SACK、時間戳記、視窗縮放選項 → 於是 遺失多個封包時每個往返只能復原一個,視窗被限制在 64KB → 畫面上 每次遺失時定格的時間都長得多(沒有 SACK 就無法使用 RACK-TLP),恢復後快轉。更新檔這類大量傳輸也會變慢

症狀
定格, 快轉
因素
停滯, 延遲
誰會遇到
特定地區/電信業者, 整個伺服器
何時
一直都有
負責單位
主要負責 基礎設施團隊(網路基礎設施) · 協同 基礎設施團隊(伺服器基礎設施)
基礎設施團隊要做的事
網路:關閉該設備的 TCP 正規化設定、也確認防火牆的序號隨機化、以兩端的封包擷取比較 SYN 中的選項。伺服器設備/OS:在 ss -ti 確認缺少 sack、wscale 標示的連線是否集中在特定路徑(Windows 電腦依設定可能不使用 ts,所以只少了 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
    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)的 commit
  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 重傳的根本原因

同一症狀(定格)在其他層的原因

查看含圖解與實驗的完整版卡片