要約

  • 初期の TLS は 16 KiB の上限を置き、その後の max_fragment_length はクライアントが選んだ一つの小さな値を双方向に適用した。しかし、重いメモリ負担は多くの場合、完全な保護レコードを受け取る側にある。
  • RFC 8449 は制限を方向別の受信申告へ変えた。各端点が自分の受信可能量を示し、送信側が相手に向かうレコードを分割する。この値は端点メモリの境界であり、経路やアプリケーションメッセージの寸法ではない。

送れる大きさと、受け止められる大きさ

暗号アクセラレータを備えた小型端末を考える。送信では、入力を少しずつ暗号化して線上へ流せる場合がある。受信は同じではない。保護レコード全体の真正性を確かめる前に途中の平文をアプリケーションへ渡せば、偽造された先頭部分だけで処理が動き、最後の認証失敗では取り消せない。

レコードサイズは単なる形式ではなく、費用の割り当てである。送信者は一つの保護単位へ詰めるデータ量を決め、受信者はそれを保持して認証する原子的なメモリ負担を負う。同じ TLS を話すことは、同じ RAM を持つことを意味しない。

RFC 8449 の歴史的な変更点は、数値を小さくしたことより、その数値を誰の能力として読むかを変えたことにある。

16 KiB は一般上限だった

TLS 1.2 のレコード層は、上位層のデータを 2^14 バイト以下の TLSPlaintext に収める。一つのメッセージを複数レコードへ分けても、同種の複数メッセージを一つへまとめてもよい。したがって TLS レコードは、アプリケーションメッセージでも TCP セグメントでもない。

大きなレコードは、ヘッダーや暗号処理の固定費を薄める。一方、メモリの小さな機器には最悪時の受信バッファを要求する。保護や圧縮による線上の増分もある。別の合意がなければ、普段は小さなレコードしか来なくても、端点はプロトコル上の最大値に備えなければならなかった。

2006 年の拡張仕様を引き継いだ RFC 6066max_fragment_length を定義した。クライアントは 512、1024、2048、4096 バイトの四択から要求し、サーバーが受け入れるなら同じ値を返す。その後はハンドシェイクメッセージを含め、両方向が直ちに同じ上限を守る。値は当時のセッション再開にも引き継がれた。

RFC 7925 が IoT 向けプロファイルでこの仕組みを評価したのは当然だった。クライアントは 16 KiB 級の受信レコードを常時扱う RAM を省ける。実装内部の都合が、相手に伝わるプロトコル条件になった。

対称な値が非対称な機器を隠した

旧方式には導入を妨げる形があった。最大の選択肢が 4096 バイトしかなく、通常上限の 16384 を表せない。制約のないクライアントでも拡張を提示すれば、小さいレコードによるヘッダー増、暗号処理回数、スループット低下を招き得る。

さらに、値を提案できるのはクライアントだけだった。制約の厳しいサーバーが、クライアントより小さな受信限界を返すことはできない。クライアント側の制約も、送信と受信の双方に同じ値を課した。しかしレコード寸法は本来、受信側の制約になりやすい。生成は逐次処理できても、認証付き受信は全体を必要とするからだ。

一つの共通値は公平に見えるが、二台の機器を一つの能力へ丸め、開始側だけに提案権を与えていた。

record_size_limit は申告者へ向く

新しい拡張の値は、申告した端点が受け取る意思のある保護レコード平文の最大長である。相手はその端点へ向かうレコードを値以内にしなければならない。申告側が逆方向へ送るレコードは、相手の申告とバージョン上限を守る限り、より大きくてもよい。

同一接続に二つの値が成立する。小型端末はクラウドから届くレコードだけを小さくし、大容量のクラウドへは比較的大きなレコードを送れる。制約サーバーも、自分の受信限界を初めて独立に示せる。能力に余裕のある端点にも拡張の提示が勧められるのは、相手の申告を可能にし、尊重すると伝えるためである。

宣言を超える保護レコードを TLS が受け取れば、致命的な record_overflow で接続を終える。DTLS は超過レコードを破棄する選択も持つ。64 未満の値は不正だが、64 は推奨性能値ではない。極端に小さいレコードは処理量を増し、スループットを落とし、サービス拒否への露出を強め得る。

上限へ数えるもの

TLS 1.2 以前では、上限は圧縮と暗号化へ入る材料を対象とし、暗号方式が付けるパディングは別に扱う。TLS 1.3 では、内容、内部 ContentType、レコードパディングを含む TLSInnerPlaintext 全体が対象になる。

TLS 1.3 のパディングは通信量の形を隠す助けになるが、受信限界を迂回しない。プライバシーのための余白もアプリケーションデータと同じ受信予算を使う。未保護のハンドシェイクレコードは拡張の対象外であり、再開や旧来の再ネゴシエーションでは、その鍵を作るハンドシェイクごとに限界を改めて決める。

PMTU とは別の事実

小さな単位が増えるため、Path MTU と混同しやすい。だが RFC 8449 は両者を分ける。レコード限界は端点内部の処理制約から決まり、ハンドシェイクで固定される。PMTU は経路が与えるパケット搬送条件で、接続中にも変化する。小さな DTLS レコードを複数、一つの UDP データグラムへ収めることもできる。

HTTP 応答、証明書チェーン、アプリケーションメッセージの長さを制限するものでもない。それらは複数レコードをまたげる。コード量、CPU、帯域、電池、あらゆるメモリ故障を解決する拡張でもない。受信者が一つの保護単位として処理する平文量だけを限定する。

IANA の現行登録では、値 28 の record_size_limit は Recommended、値 1 の max_fragment_length は非推奨である。登録は相互運用上の状態を示すが、製品の実装率や正しさは証明しない。

TLS が修正したのは、プロトコルの両端は同じであるという思い込みだった。共通に必要なのは同一容量ではない。各受信者が自分だけの境界を正直に示し、費用が落ちる方向で相手が従うことである。

根拠と限界

根拠は RFC 4366RFC 5246RFC 6066RFC 7925RFC 8446RFC 8449IANA TLS ExtensionType 登録表である。現時点の普及率、個別機器の RAM、特定処理に最適な値は示さない。