要約

  • ゼロウィンドウ探査は、データを持たないACKが失われても、受信側に現在のウィンドウをもう一度報告させる。
  • persist状態は通信再開の可能性を守るが、資源をいつまで保持するかはOSとアプリケーションが決める。

行き違いは、双方が規則どおりに動いていても起きる。受信側のアプリケーションがデータを読むのを止めると、受信バッファが埋まり、TCPは受信ウィンドウをゼロと通知する。送信側はフロー制御に従って通常のデータ送信を止める。やがてアプリケーションがバッファを空け、受信側はウィンドウを広げたACKを送る。ところが、その一通だけがネットワークで失われたらどうなるか。

受信側は、空きが戻ったことを伝えたつもりでいる。送信側には古い「ゼロ」の情報しかない。データを載せないACKは、それ自体が確実に再送されるわけではない。受信側は次のデータを待ち、送信側は次の送信枠を待つ。接続は切れていないのに、フロー制御に関する認識だけが二つに分かれる。

この食い違いを解くのがゼロウィンドウ探査である。ウィンドウがゼロと通知されたままでも、送信側は間隔を置いて少量を送信または再送し、受信側から応答を引き出す。受信側は、次に期待するシーケンス番号と現在のウィンドウをACKで返す。すでに空きがあれば、送信側はそこで再開を知る。まだゼロなら、最新のゼロを確認するだけであり、探査を口実に受信側の制限を破ることはできない。

この仕組みの骨格は、1981年のRFC 793にすでに記されていた。送信TCPはウィンドウがゼロでも定期的に再送し、受信TCPはセグメントが届けば次の期待番号と現在のウィンドウを示すACKを返す。目的は、閉じていたウィンドウが開いたとき、その変化を相手へ確実に伝えることだった。初期仕様にあった時間間隔の勧告よりも、「失われ得る状態通知を再び語らせる」という制御の形が後代まで残った。

1989年のRFC 1122は、ゼロウィンドウ探査のサポートを必須とした。理由も具体的である。ウィンドウを再び開くACKが失われ、探査もなければ、接続は永久に停止しかねない。同文書は、ゼロウィンドウが再送タイムアウト一回分続いた後に最初の探査を送り、その後の間隔は指数的に延ばすよう勧告した。

最初の問いかけをRTO一回分の後に行えば、単発のACK損失を長く放置せずに済む。一方で間隔を次第に広げれば、正当な長時間停止に対して一定の頻度で問い続けることを避けられる。探査は新しい受信枠を作らない。受信側が決めた枠を尊重したまま、その値が今も同じかを聞き直す。

RFC 1122には、もう一つ重要な線引きがある。受信TCPは、提供するウィンドウを無期限に閉じてよい。探査に対するACKが返り続ける限り、送信側は接続を開いたままにできなければならない。ただし、アプリケーションのユーザータイムアウト方針は別に残る。例として挙げられたのは、用紙切れでデータを受け取らなくなったプリンターデーモンだった。TCPには紙切れも補充時刻も見えない。外部の一時停止を、トランスポートの死亡と決めつける材料はない。

このとき送信側が置かれる状態は、一般にpersist conditionと呼ばれる。2011年のRFC 6429がこの状態を改めて扱ったのは、プロトコル上の忍耐と計算機資源の負担が同じではないからだ。相手がゼロウィンドウを広告し続け、探査には毎回答えるなら、接続はTCP上は生き続ける。その間、送信キューのデータやバッファ、接続状態は送信側に残る。多くの接続が同じ状態に入れば、正当な接続へ回すべき資源が不足し得る。

RFC 6429は、persist状態に一律の終了時刻を追加したわけではなく、ゼロウィンドウをすべて攻撃と扱ったわけでもない。明確にしたのは権限の所在である。TCPがpersist状態だけを理由に接続を閉じるべきではない一方、OSやアプリケーションは通常の方針に従って接続を終了し、資源を回収できる。プロトコルが継続可能性を保つことと、資源の所有者が無制限の負担を引き受けることは別である。

現在の統合TCP仕様であるRFC 9293も、この構造を引き継いでいる。ゼロウィンドウ探査は必須であり、受信側は現在のウィンドウと次の期待シーケンス番号を返す。最初の探査はRTO一回分の後、その後の間隔は指数的に延ばすべきとされる。資源管理上の考慮も残った。守られているのは「常に永久に待つ」という約束ではなく、「接続を保持すると決めた間は、ウィンドウ状態を再取得できる」という性質である。

したがって、探査へのACKはトランスポート層の証拠にとどまる。相手TCPがシーケンス空間とウィンドウを報告していることは分かるが、受信アプリケーションが前進していること、近くデータを受け入れること、接続を保つ価値があることまでは示さない。探査は失われた通知を補う。将来を保証する仕組みではない。