要約

  • ソケットのEOFは接続が切れた事実しか示さない。close_notify は、送信者がその方向ではもうTLSメッセージを送らないという保護された証拠を加えた。
  • TLS 1.3は終了を全二重接続の一括停止から切り離した。ただし、HTTP応答やストリームが完全かどうかは、長さ、チャンク終端、END_STREAM など上位層の境界が決める。

正しい断片と、完全な答えは同じではない

最後に届いたTLSレコードの認証は成功し、その直後にソケットがEOFを返す。この観測だけなら、受信済みの断片が途中で改ざんされていないことは言える。しかし、相手がその後に送るつもりだったレコードまで届いたとは言えない。

上位プロトコルに独自の終端があれば、不足は見つけやすい。Content-Lengthが示す値に届かなければ短い。チャンク転送の終端であるゼロ長チャンクがなければ未完了だ。ところが接続を閉じること自体が応答の区切りなら、正常な終わりと末尾の消失は、通信断だけでは同じ姿になる。

TLS 1.0 は、この切り詰めの危険を終了手順の問題として扱った。送信側は close_notify をTLS内部の警報として送り、その接続方向ではこれ以上メッセージを送らないと表明する。警報も保護されたレコード列に置かれるため、裸のEOFにはない意味を持つ。

ただし、TLSが保証するのは文書や取引の完成ではない。保証の範囲は「この送信者からのTLSメッセージはここで終わる」までである。受信した内容が一つのHTTP応答やファイルとして完全かどうかは、依然としてアプリケーションの構文に委ねられる。

TLS 1.0は不完全な終了を次の接続にも持ち越した

初期の仕様は終了証拠を厳格に扱った。適切な終了警報なしにTLS 1.0接続が終われば、そのセッションは再開できない。閉じ方が確認できなかった暗号関係を、次の接続の近道として利用させない設計だった。

実装の現場はその結び付きを維持しなかった。TLS 1.2 の記録によれば、TLS 1.1では広く行われていた実装慣行に合わせ、正しい終了を欠いただけでセッションを再開不能にする規定が削除された。close_notify を送る義務は残ったが、終了の証拠と再開資格は別の判断になった。

これは単なる緩和ではない。守るべき意味論を残しつつ、運用で定着しなかった罰則を外した変更である。プロトコルの境界と、将来の接続に適用するポリシーは、関連していても同一ではない。

一方が書き終えても、他方はまだ書ける

TLS 1.3より前は、close_notify を受けた側が直ちに自分の警報を返し、接続を閉じ、保留中の書き込みを捨てるよう求められていた。終了を対称な握手として扱う規則である。

しかし、アプリケーションの会話はいつも対称ではない。要求を送り終えたクライアントが、応答を待ち続けることは普通にある。最初の警報を受けた側が未送信の応答まで廃棄すれば、切り詰めを防ぐための手順が逆方向を切り詰めかねない。

TLS 1.3 は close_notify を片方向の秩序ある終了として定義し直した。送信は自分の書き込み側を閉じるが、読み取り側を閉じない。受信側は直ちに応答警報を返す必要がなく、逆方向の保留データを捨てる必要もない。二つの方向は、それぞれを使うアプリケーションが終わった時点で閉じられる。

同仕様は不確実性の位置も明確にした。警報より先にトランスポートが閉じれば、受信者には相手が送った全データを受け取ったか分からない。すでに認証済みのレコードが無効になるのではない。見えない末尾が存在した可能性だけが残る。

HTTPはTLSに見えない完全性を判断する

HTTP over TLS は、受信済みデータの安全性と、後続データが失われた可能性を区別した。TLS自身にはHTTPの要求や応答の境界が見えないため、クライアントはHTTPのフレーミングを調べなければならない。

現在の HTTP/1.1仕様 でも役割分担は同じだ。宣言された長さ、最後のゼロ長チャンクなどがメッセージの完全性を示す。接続終了だけで区切る応答は、TLSの有効な終了警報が届いて初めて完全と扱える。警報がなければ、途中までの応答を完成品として採用することが攻撃面になる。

HTTP/2では層の違いがさらに見やすい。RFC 9113 の END_STREAM は、一つのHTTPストリームの片方向を閉じる。同じTLS接続上の別ストリームは続けられる。ストリームの完了とTLS接続の完了は、別々の証拠である。

警報が言うことは一つだけ

close_notify は利用者を認証せず、取引を承認せず、アプリケーションが処理を終えたとも宣言しない。それが示すのは、この送信者がこの方向にこれ以上TLSメッセージを送らないという一点である。

EOFは出来事、終了警報は送信意図の証拠、長さや終端マーカーはアプリケーション構造の証拠だ。堅牢な実装は三者を一つの「正常終了」に丸めず、それぞれの範囲を保ったまま組み合わせる。

出典と限界

本稿は RFC 2246、RFC 2818、RFC 5246、RFC 8446、RFC 9112、RFC 9113 に基づく。これらは仕様とその変遷を示すもので、現在のライブラリ既定値、普及率、個別障害で警報が欠けた原因までは示さない。