複数レコードタイプを一度に引く仕様『DNS Multiple QTYPEs』

DNS Multiple QTYPEs』という提案仕様がIETFで議論されています。

これは、"A", "AAAA", "HTTPS"など複数のレコードタイプを一度に問い合わせする仕組みを定義しています。

背景: 複数Questionセクションは使えない

もともと、一つのパケットに複数のQuestionセクションを含めることは可能ですが、下記の理由により使用されていません

  • QNAME フィールドが複数あるので、一貫性のあるレスポンスが生成できない
  • RFC1035 などで 多くのケースで Questionセクションが単一であることを暗に述べている
  • 実装がサポートしていない

DNS Multiple QTYPEs

DNS Multiple QTYPEs』では、EDNSオプションを使います。


  • QTD: リクエストでは0, レスポンスでは1。(エコーするサーバを検知するのに使用)
  • QTCOUNT: QT フィールドの数
  • QTn: DNS リソースレコードタイプを指定します


クライアントは

  • EDNSオプションで、QTnに問い合わせしたいレコードタイプを羅列して送信します

サーバはこのリクエストを受信した際

  • [QNAME, QTn, QCLASS]に一致するQuestionに、Answerセクションで回答します
  • サーバもAnswerセクションで回答したものを、EDNSオプションで同様にQTnを指定して応答します (これによりnegative answerを示します)

感想

Happy Eyeball v3みたいなシチュエーションで良さそうだなとは思ったが、DNSサーバ側のキャッシュ状況などによってはすべての回答を準備するのに待ちがあると思うと、準備できたものから回答してほしいかもしれないなあ

QUICのNATトラバーサル用 拡張仕様

IETFに「Using QUIC to traverse NATs」という提案仕様が提出されています。

このDraftでは「WebRTC over QUIC」や「P2P QUIC」のユースケースを想定しています。

大まかな流れとしては

  • 『Proxying Listener UDP in HTTP』といったProxy経由でクライアントはサーバに接続する
  • そのコネクション上でIPアドレスを交換してICE相当の処理を行う
  • QUICのPath validationの仕組みを用いてホールパンチングする
  • コネクションマイグレーションを行う

IETF 118の発表スライドがわかりやすいので、それをもって流れを説明していく

Address Discovery

QUICがProxyを経由してコネクションが確立したあと、サーバから ADD_ADDRESSフレームで候補となるIPアドレス及びポートをクライアントに送信する


Address Matching

ICEと同様にアドレスのマッチングを行う


Traversing the NAT

クライアントはPUNCH_ME_NOW フレームを使用して候補ペアをサーバに送信し、QUICのPath Validationの仕組みでパスプローブを送りホールパンチングします。
Path Validationがうまくいくと、コネクションマイグレーションの仕組みで直通信に切り替えます

QUIC通信を優先する Happy Eyeballs Version 3 の提案

IPv4IPv6デュアルスタック環境において、早く通信確立できた方を使用する『Happy Eyeballs』という仕組みがあります。

RFC 8305 Happy Eyeballs Version 2: Better Connectivity Using Concurrency」においては、次のようにAAAAレコードとAレコードの名前解決を行い早く通信確立できたものを使用するようになっています。

今回、そのVersion 3となる『Happy Eyeballs Version 3: Better Connectivity Using Concurrency』という提案仕様が提出されています。著者はAppleGoogleの方々で、QUIC WGやTLS WGで精力的に活動されている方々です。

Happy Eyeballs Version 3

『Happy Eyeballs Version 3』の大きな特徴は、DNSHTTPSレコードも考慮に入れて接続試行順を決めるというものです。

HTTPSレコード

まずは今回の大きなコンセプトである、HTTPSレコードの説明です。RFCにはなっていませんが「Service binding and parameter specification via the DNS (DNS SVCB and HTTPS RRs)」で定義されており、すでにブラウザやCDNで利用が開始されています。

HTTPSレコードにはHTTPSで接続するときに有用な情報が含まれています

たとえば、cloudflare.com のHTTPSレコードは次のようなデータが入っています。

"1 . alpn=h3,h2 ipv4hint=104.16.132.229,104.16.133.229 ipv6hint=2606:4700::6810:84e5,2606:4700::6810:85e5"
  • alpn: HTTP3対応情報など
  • ipv4hint: ipv4の接続先情報
  • ipv6hint: ipv6の接続先情報
  • ech: TLS Encrypted Client Helloの仕様で要求されるコンフィグ情報
大まかな流れ

Happy Eyeballsは次のような流れで行われます

  • 非同期 DNS クエリの開始
  • 解決された宛先アドレスのソート
  • 非同期接続試行の開始
  • 1 つの接続を確立し、他のすべての試行をキャンセルする
非同期 DNS クエリの開始

HTTPSレコード (SVCB / ) を送信するケースでは、次の順番で送信します

いずれかのDNSレスポンスを受け取った場合、「AAAAとHTTPS両方うけとる」「ipv6hintをもつHTTPSを受け取る」まで一定時間待ち、次のステップに進みます

解決された宛先アドレスのソート

試行する順番として、HTTPSレコードから得られた ECHやQUICサポート情報を優先的に並べることが推奨(SHOULD)されています。

その後、IPファミリとプロトコルをインタリーブさせて、リストを作成します。

接続の試行

リストに従って、順番に接続を試行していきます。(それぞれ「接続試行遅延」は通常250msecですが、最小でも100msecにするように書かれている)

コネクションの確立とは次のタイミングを指す

  • TCPであれば、TCPハンドシェイクの完了
    • なお、TLSハンドシェイク完了までをコネクション確立としてもよい
  • QUICであれば、QUICハンドシェイク完了

その他

今回のdraftには「Supporting IPv6-Only Networks with NAT64 and DNS64」といった項目も書かれているが、、、詳しい人に解説を譲ります、、、

また、個人的には「QUIC IPv6」「QUIC IPv4」の順番のがよさそうだけど、どういう順番でTCP/QUICをソートするのが良いんだろう....

今回はまだdraftが出てきたところで来月のIETF118で議論されることを楽しみにしてます。

HTTP/2 Rapid Reset攻撃に対する仕様上の対策案

HTTP/2のDDoS攻撃手法として『HTTP/2 Rapid Reset』(CVE-2023-44487)が世間を賑わせています。

各ベンダーから情報が出ています

このDDoS攻撃はストリームのオープン(HTTPリクエスト)とストリームのキャンセルを繰り返すことで行われます。HTTP/2では、ピアが同時に開くストリーム数を制限する事ができますが、それではオープン/クローズを繰り返す行為を制限することはできません。


(実際にはストリームのオープン/クローズは瞬時に行われる)

このHTTP/2 Rapid Reset攻撃に対して、仕様上制限することができないか?という議論がIETFのHTTP WGで開始しています。すでに「Using HTTP/3 Stream Limits in HTTP/2」がひとつの案として投げかけられています。

来月行われる IETF 118でサイドミーティングが行われるようですが、ひとまずこの提案に目を通しておく。

Using HTTP/3 Stream Limits in HTTP/2

Using HTTP/3 Stream Limits in HTTP/2」はHTTP/3で行われるストリームオープン制限方式をHTTP/2に適応することを提案しています。

HTTP/3が使うQUICでは、"同時にストリームがオープンしてる数"で制限をするのではなく、"ストリームをオープンする回数"で制限をかけます。

実際にはストリームIDの上限値をピアに通達します。MAX_STREAMSフレームを送ることで、上限値をあげることができます。通常の利用では次のようになると思います。

ストリームIDは再利用できないので、消費された分必要に応じてMAX_STREAMSフレームを送信し、ピアが利用できるストリーム上限を上げていきますわ


ピアが高速でストリームオープン/クローズされたとしても、上限に達した場合はピアはMAX_STREAMSフレームを受け取るまでストリームをオープンすることができなくなります。

この仕組みをHTTP/2に組み込みます

MAX_STREAMSフレーム

HTTP/2のMAX_STREAMSフレームは次の形式です。

Maximum Stream Identifierによって、上限となるストリームID値を指定します。このフレームをストリーム0で送信します。

有効性について

もちろん、実世界ではこの拡張仕様 (MAX_STREAMSフレーム)をサポートしてない実装も引き続き利用されつづけるでしょう。そのような実装は変わらず 同時オープン数(SETTINGS_MAX_CONCURRENT_STREAMS) に従って振る舞うことができます。

MAX_STREAMSフレームを解釈できるピアと、できないピアにたいしてヒューリスティックに異なる制約を実装上かけることはできるかもしれない。という形にはなるのかなと思っています。ストリームの並列数はパフォーマンスにも関わるのでそちらとの兼ね合いもトレードオフが有ると思います。

DDoSは正規の処理を大量に行う行為なため制限は悩ましいですね...

なんにせよこれから議論がされていくと思うので、全く別の手法も提案されるかもしれません。引き続き議論を追っていこうと思います

TLS 1.2への新機能追加を停止する議論

IETFに『TLS 1.2 is in Feature Freeze』という提案が出されています。

これは、標準化作業上、TLS1.2に新しい機能追加を停止しようという提案です(ただしセキュリティ対応は除く)。TLS1.2やTLS1.3にはエクステンションや、新しい暗号アルゴリズム、Supported Groupsなどを追加できるようになっていますが、それらの追加をTLS1.2では承認しないという話しです。

アプリケーションプロトコルがTLS1.2を利用することを禁止するものではありません。

議論

2023年 3月に行われた IETF 116 TLS WGのミーティングで『TLS 1.2 Deprecation (PDF)』という話しがありました。そこでは、標準化上 TLS 1.2をDeprecation する議論が行われました。

議論は、標準化上の話しと実利用の話しが色々議論されましたが、ブラウザベンダーからはTLS1.2が実際にはまだ利用されているなどのフィードバックが行われました。

その後、標準化の観点にしぼりTLS1.2への新機能停止の提案が2023年5月に提出されています。

TLS 1.2 is in Feature Freeze

TLS 1.2 is in Feature Freeze』では先述の通り、今後TLS1.2へ新しい機能の追加を承認しないという提案です。

  • RFC8447で登録されているTLSパラメータについて、今後追加するものはTLS1.3を対象とする
    • ただし、TLS Exporter LabelsとALPNの識別子はTLS1.2でも使える
  • DTLS1.2は対象外とする

New Protocols Must Require TLS 1.3

また、あわせて「New Protocols Must Require TLS 1.3」という提案も行われています。

これは、新しいアプリケーションプロトコルはTLS1.3をサポートするよう要求する提案です。もちろん、TLS1.2の利用を禁止するものではありません。

今後

引き続き、提出された提案をもとに議論が続けられます。来月行われるIETF118のミーティング改めてWGの意見が集められるものと思います。

UDP Optionsパケットのインターネット疎通性の考察

IETFでは「Transport Options for UDP」という仕様の標準化が議論されています。このUDP Optionsの仕様では"Maximum Datagram Size", "Timestamps " などのデータをオプション領域に格納して送信できるようになります。

新しいプロトコル機能の利用については、過去にもTLS1.3やTCP Fast Openといった新しいプロトコルがインターネット上で正しく処理されない(Ossification)問題が知られています (参考リンク)

UDP Optionsは特に変わったパケットになるため、インターネット越しで問題なく疎通するのか確認するというのが今回の目的です。

ちょっと面白い振る舞いも観測されたため書いていきます。

目次

UDP Optionsパケット

まず、UDP Optionsを持つパケットのフォーマットについて補足します。

UDPヘッダは固定長ですのでそこにオプションを配置することはできず、UDPペイロードの後ろにsurplus areaを確保しそこにオプションを格納します。surplus areaは、UDPヘッダで指定されるLengthよりもIPヘッダで指定されるLengthを大きく設定することで設けることができます。

(引用: Overcoming the limitations of UDP Options | APNIC Blog )

通常の実装であれば surplus area 領域はそのまま無視するため、UDPとしての通信は問題なく行われるはずです。

UDP Optionsの詳細は以前書いたとおりです。
asnokaze.hatenablog.com

実験

surplus areaをもつUDP パケットを 自宅からインターネット上の公開サーバに送信し返信が返ってくるか確認する。

利用したパブリックサーバは次のプロトコルを喋るものを幾つか選定。

  • DNS
  • NTP
  • QUIC (HTTP/3)

手順としては、各公開サーバに対して以下の2つを試す。送るパケットは、それぞれのプロトコルに合わせて適切なパケットを送るものとする。

  • 1. surplus areaのないUDPパケットを送信し、返信があることを確認する
  • 2. surplus areaのあるUDPパケットを送信し、返信があることを確認する
パケットの例

パケットキャプチャすると、このようにDNSパケットとして正しく解釈されるものです (この例はDNSクエリのUDPパケットにsurplus areaを追加)
surplus areaに『this is surplus area』という文字列が格納されています。

結果

データ

  • DNS: 21公開サーバに送信した。surplus areaがあると6サーバが返信しなくなった
  • NTP: 10公開サーバに送信した。surplus areaがあると2サーバが返信しなくなった
  • QUIC: 6公開サーバに送信した。surplus areaがあると2サーバが返信しなくなった

surplus areaがあると返信が返ってこなくなるサーバがいくつか観測された。幾つかは返ってくるためミドルウェア実装は問題なく処理できているのではないかとおもう。想像するに、返信がないケースはWAFなどにより不正なパケットとして遮断されているケースかなと思われる。

実際に、Google Cloud Platform (GCP)にVMインスタンスを起動しsurplus areaのあるパケットを送ってみると、VM側までパケットが到達してないことが確認できた(通常のUDPパケットは届く)。

また、次に示すように一部アプライアンス製品では、surplus areaがあるとパケット処理が特殊なケースも有るかもしれない。

奇妙な振る舞い

奇妙なことに、サーバ側 surplus area をそのまま送り返してくるケースが確認された。

NTPサーバ側からsurplus areaに『this is surplus area』という文字列入っているパケットが返ってきている。

調べたところサーバはNTP専用のアプライアンス製品であるもよう。想像するに、受け取ったパケットを格納しているバッファ領域を再利用してる感じなんだろうか?

このようなことが有ると、相手が送ってきたUDP Optionsが信頼できないので、コピーされてないことを保証する仕組みが必要になりそう
(例えば、追加のUDP Optionsとして"client bit", "server bit" みたいな送信方向を示すoptionsなどを定義するなど)

まとめ

今回はパブリックなサーバに対しsurplus areaを含むUDPパケットを送信した。

実験結果として以下のことがわかった

  • surplus areaがあると疎通しないケースが有る
  • surplus areaをそのまま送り返してくるサーバが居る

UDP Optionsは対応してない相手には無視されることが期待されるが、疎通しないケースが存在すると、UDP Optionsをつけずに再送しなおす必要が出てくる。

自分たちがサーバ側もクライアント側もコントロール出来るケースにおいてはUDP Optionsは気にせず利用できるが、そうではない場合は常に疎通しないケースを考慮する必要がでてくる。

終わりに

この実験結果をもってしてなにか改善にとりくめるか、一緒に議論できる方がおりましたら是非よろしくお願いします

HTTPレイヤで追加のサーバ証明書を送信する Secondary Certificate の仕様について

HTTP/2やHTTP/3のレイヤで追加のサーバ証明書を送信可能にする『Secondary Certificate Authentication of HTTP Servers』という仕様がHTTP WGで議論されています。著者はAppleの方とAkamaiの方の共著になっています。

以前にも、共著に入っているMike Bishop氏から2016年~2018年に同様の提案が出ておりましたが改めて提案されています。前回はクライアント側からのクライアント証明書の追加送信サポートしていましたが、今回はサーバからの追加の証明書を送信するユースケースに絞った提案になっています。

モチベーション

HTTPレイヤで追加のサーバ証明書を送信するモチベーションについて説明します。

HTTP/2ではTCPコネクション、HTTP/3ではQUICコネクション上でHTTPリクエストを送信します。極力そのコネクションを使い回すことが出来たほうが、コネクションを確立する手間も少ないですし、輻輳制御上もメリットがあります。

HTTP/2およびHTTP/3において、コネクションを再利用できる条件は次のとおりです

  • リクエストを送るドメインのIPが同一なこと
  • コネクションを確立した際の証明書が、リクエストを送るドメインとマッチしていること

具体的には *.example.com の証明書で接続したコネクション上では、下記のドメインへのリクエストを送信しても良いことになります

このように証明書がカバーするドメインが多ければコネクションを再利用できる機会が増えます。

今回の提案仕様により、追加のサーバ証明書を送ることができれば、コネクションを再利用できる機会を増やすことが出来ます。

Secondary Certificate Authentication of HTTP Servers

CERTIFICATEフレーム

この仕様では、サーバ側からHTTPレイヤで証明書を送信するために CERTIFICATEフレームを新しく定義しています。

HTTP/2およびHTTP/3でCERTIFICATEフレームを定義していますが、例えばHTTP/3では次のようなメッセージです。

Authenticatorフィールドは証明書と紐づく秘密鍵の所持の証明をするデータです。具体的には『RFC 9261 Exported Authenticators in TLS』を介してえられるデータです

通信の流れ

この拡張仕様を使うためには、SETTINGS_HTTP_SERVER_CERT_AUTHパラメータを交換する必要があります。
その後、CERTIFICATEフレームフレームをh2ではstream 0 、h3ではcontrol streamで送信します。

その他

セキュリティ上の考慮事項についても『Secondary Certificate Authentication of HTTP Servers』にかかれておりますので、気になる方はそちらをご覧頂くのが良いと思います。