DNS名前解決エラーもネガティブキャッシュする提案 (RFC 9520)

2023/12/23 追記: RFC 9520 になりました
==

Negative Caching of DNS Resolution Failures」という提案が、Verisignの方らによって提案されています。

DNSの名前解決の結果はつぎのいずれかです。

  • 1) 要求されたデータを含む応答
  • 2) 要求されたデータが存在しないことを示す応答
  • 3) ネットワークエラーや、データ不整合などの、有用な情報が得られない(失敗)

今回の提案では、(3)のエラーについても最低5秒間ネガティブキャッシュするよう要求します(5分以上キャッシュしてはいけない)。

RFC2308 「Negative Caching of DNS Queries」では、サーバが落ちていたり接続できない場合に、オプショナルでキャッシュする事が記述されてはいます。

モチベーション

提案仕様のなかで、DNSのエラーが起こり、再帰サーバのトラフィックが増大したことを説明しています。幾つかを紹介すると

  • 2018年のDNSSECのKSK Rolloverにおいて、古いトラストアンカーを使用しDNSKEYをリトライする再起リゾルバーがいて、トラフィックが増大した (参考)
  • 2021年、Verisignの研究により、REFUSEDやSERVFAILを返す権威サーバのクエリトラフィックが多いということを示した
  • 2021年 10月、Facebookの障害で権威サーバにアクセスできなくなったとき、再帰サーバでタイムアウトが発生した。.comや.netへのクエリが、7000 query/sec から 900,000 query/secに増大した (参考)

失敗の種類

この提案仕様では、失敗の種類として、以下のものについて言及しています

  • SERVFAILの応答
  • REFUSEDの応答
  • 要求のタイムアウト
  • 委譲のループ (NSレコードの指定先がループしている)
  • エイリアスのループ (CNAMEレコードの指定先がループしている)
  • DNSSECの検証失敗

Twitchの動画配信プロトコルWarpのデモを動かしてみる

TwitchはWebTransport over HTTP/3 で単方向のライブストリーミングを可能にするWarpというプロトコル開発してます。
古い記事ですが、以前紹介した通りで、現在IETFで議論が進められています。
asnokaze.hatenablog.com

その Warpのデモコードが公開されたので動かすところまでやる。
github.com

とはいえ書いてある通りやるだけ。僕は、サーバとブラウザを別環境で動かす都合でちょっと弄っている。先に結果だけ書くと

結果

ブラウザで動画が流れる事を確認しました

また、serverを改造してkeylogfileを出力させ、パケットを復号させると

  • SETTINGSフレームで次の値を投げている
    • SETTINGS_WEBTRANS_DRAFT00 = 0x2b603742,
    • SETTINGS_H3_DATAGRAM_DRAFT04 = 0xffd277,
  • サーバからの単方向ストリーム (WebTransport stream=0x54)でデータを転送していることがわかります
    • データの最初にwarp用のjsonが格納されてます

( パケロス時に再送不要なDATAGRAMフレームも仕様上使えるが、まだ使ってなさそう

以下は手順

前準備

今回はUbuntuで動かしたが、ffmpegやnodejsはaptで降ってくるバージョンだと動かないので適宜新しいものを入れる (ffmpegはsnapでいれて、nodejsはv16を入れた)

コードの取得

$ git clone https://github.com/kixelated/warp-demo.git
$ cd ./warp-demo

流す動画ファイルの取得、変換

$ wget http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 -O media/combined.mp4
$ ffmpeg -i media/combined.mp4 -f dash -use_timeline 0 -r:v 24 -g:v 48 -keyint_min:v 48 -sc_threshold:v 0 -tune zerolatency -streaming 1 -ldash 1 -seg_duration 2 -frag_duration 0.01 -frag_type duration media/fragmented.mpd

証明書の準備

$ ./cert/generate
$ ./cert/fingerprint
sB8TJSHn195H3GJm/6WoibD/OGN5M+w4x7a7RpirLo4=

フィンガープリントは後で使う

/ect/hostsの設定

echo '127.0.0.1 localhost.warp.demo' | sudo tee -a /etc/hosts

サーバの起動

Webサーバ、https://localhost.warp.demo:4444/ で動作する。アクセスすると動画プレーヤーが表示される
( 127.0.0.1でLISTENするので、外からアクセスする場合は ./player/package.json で起動を 0.0.0.0 に指定すれば良い

$ cd player
$ yarn install
$ yarn serve

warpサーバ、https://localhost.warp.demo:4443/ で動作する

$ cd server
$ go run ./warp-server

Chromeでアクセスする

先述の通り、warpサーバを起動したとは別のPCからアクセスするので
localhost.warp.demo を該当サーバのIPに向ける必要がある。/etc/hostsで指定してやれば良い

なお、現状はChrome Canaryを使う必要がある。
で、Chromeを起動時に次のオプションを渡す (起動コマンドは chrome://version で確認できる)

--origin-to-force-quic-on="localhost.warp.demo:4443" --ignore-certificate-errors-spki-list="sB8TJSHn195H3GJm/6WoibD/OGN5M+w4x7a7RpirLo4=" https://localhost.warp.demo:4444

https://localhost.warp.demo:4444/にアクセスする

HTTPのやり取りの最中に付帯情報を送れるMETADATAフレーム

METADATA frame for HTTP/2 and HTTP/3」という提案仕様がIETFに提出されている。

これは、HTTPリクエストやレスポンスをやるとりする際に、HTTPメッセージ(ヘッダやコンテンツ)とは別に追加情報を送れるようにします。追加の情報を送るのに、HTTP/2及びHTTP/3の拡張フレームとしてMETADATAフレームを定義します。METADATAフレームはストリーム上で任意のタイミングで送れるため、HTTPリクエストを送受信してる途中, HTTPレスポンスを送受信してる途中に何度も送信できます。

追加の情報の例としては、「CPUコスト」「負荷分散情報」「統計情報」などを送ることが述べられています。他にも、デバッグ情報など送るのに良さそうだなと思います。これらはHTTPセマンティクスではないので、ヘッダとして解釈されるとかはないです。

この機能はenvoyに組み込まれているしくみで、他にもGoogle QUCHEなどすでに実装しています。(具体的にどう使うのか知ってる方が居たら教えてください...)
github.com

HTTP/2の場合

SETTINGSパラーメタのSETTINGS_ENABLE_METADATAを有効にした場合に使えます。

HTTP/2ではメタデータを付加したいHTTPメッセージのストリームIDを指定します。また、メタデータはキーバリュー形式のデータであり、HPACKのフォーマットで格納します。


HTTP/3の場合

SETTINGSパラーメタのSETTINGS_ENABLE_METADATAを有効にした場合に使えます。

HTTP/3ではメタデータを付加したいHTTPメッセージと同じQUICストリーム上で送信します。また、メタデータはキーバリュー形式のデータであり、QPACKのフォーマットで格納します。

HTTP/3のCONNECT-UDPを利用したWebRTC通信

Proxying Listener UDP in HTTP」という提案仕様がIETFに提出されている。

これは、HTTP/3のCONNECT-UDPを介してWebRTC通信を可能にするための提案である。まだ議論の呼び水と鳴るdraftであるため、ここから仕様は大きく変わると思うが、ざっと眺めていく。

HTTP/3のCONNECT-UDP

本論に入る前に、まずCONNECT-UDPについて説明します。

IETFではすでに「Proxying UDP in HTTP」という仕様が議論されている。これが通称CONNECT-UDPと呼ばれているものである。実は、AppleのPrivate Relayでもすでに使用されているものである。

これは、Proxyと確立したHTTP/3コネクションをトンネリングしてUDPパケットを中継させる機能です。

この通信は第三者からはただのHTTP/3通信としてか観測できないという特徴があります。確立した通信路を通して自由なUDPパケットを中継させることが出来ます。

このCONNECT-UDPでは、H3-Datagramという仕様でUDPパケットを扱います。詳しくは以前書いた記事を参照ください。
asnokaze.hatenablog.com

Proxying Listener UDP in HTTP

通常のCONNECT-UDPではProxyを中継して通信する相手は1つでしたが、WebRTCはSTUNと通信した上で、通信相手のブラウザからもパケットを受け付ける必要があります。そこで、既存のCONNECT-UDP拡張機能として「Proxying Listener UDP in HTTP」が登場しました。

(提案者はユースケースとしてWebRTCをあげていますが、それに限定されるものでは有りません)

主な通信の流れ

上記の図に沿って通信の流れを説明します。

CONNECTリクエストとレスポンス

まずは、ブラウザAと中継サーバとでHTTP/3のコネクションを確立したのち、中継の要望を出す。

通常のCONNECT-UDPのように、拡張CONNECTメソッドを用いる(:protocolにconnect-udpが指定される)。

connect-udp-listenヘッダを付けることで、Proxying Listener UDP in HTTP の通信であることを明示する。ヘッダの値は使用するH3-DatagramのContext-IDを指定する。

HEADERS
  :method = CONNECT
  :protocol = connect-udp
  :scheme = https
  :path = /.well-known/masque/udp/*/*/
  :authority = proxy.example.org
  connect-udp-listen = 2
  capsule-protocol = ?1
|<<

中継サーバは、200番のレスポンスを返し、CONNECTリクエストの受け入れる意志を示す。

>||
HEADERS
  :status = 200
  capsule-protocol = ?1
STUNサーバへのUDPパケットの中継

ブラウザA側は、H3-DatagramUDPパケットを中継サーバに送信する。このとき、中継先となるターゲットのIPとポートを付加して送る。

 DATAGRAM
   Quarter Stream ID = 11
   Context ID = 2
   IP Version = 4
   IP Address = 192.0.2.42
   UDP Port = 1234
   UDP Payload = Encapsulated UDP Payload

中継サーバは、指定されたIP宛にUDPパケットを中継する。

中継サーバはSTUNサーバから応答となるUDPパケットを受け取ると、ブラウザA側に中継する。このときもH3-DatagramでUDPパケットを中継することになる。

このときのH3-Datagramでは、どこからきたUDPパケットなのかが付加されている。

DATAGRAM
  Quarter Stream ID = 11
  Context ID = 2
  IP Version = 4
  IP Address = 192.0.2.42
  UDP Port = 1234
  UDP Payload = Encapsulated UDP Payload

ブラウザBからのUDPパケットの中継

STUNとのやり取りが終わって、ブラウザAとブラウザBがやりとりを開始します。ブラウザBから送られるUDPパケットも、中継サーバがブラウザAに中継を行います。このときもH3-DatagramでUDPパケットを中継することになる。

DATAGRAM
  Quarter Stream ID = 11
  Context ID = 2
  IP Version = 4
  IP Address = 203.0.113.33
  UDP Port = 4321
  UDP Payload = Encapsulated UDP Payload

一般ユーザに払い出すと危険なサブドメインやメールアドレス

ユーザに対して、そのユーザ名のサブドメインやメールアドレスを払い出すWebサービスがあります。

しかし、特定のサブドメインやメールアドレスは特別な用途で使われているものもあります。そのようなサブドメインやメールアドレスを一般ユーザに払い出してしまうと危険です。

現在、IETFでは仕様上利用用途が決められている、それらのラベルをとりまとめる「Dangerous Labels in DNS and E-mail」というdraftが提出されています。

今回はそれを眺めていきます。

(あくまでIETFの取り組みであり、仕様上定義されているものをとりまとめています。クラウドサービスや特定ベンダーで特別利用しているものは現在含まれていません。)

サブドメイン

ここでとりあげるサブドメインは、利用用途が決まってるため一般ユーザに払い出すべきではありません。(例: mta-sts.example.com)

(なお、_example のように、アンダースコアで始まるものはRFC 8552ですでにまとめられています。ここでは紹介はしません。)

  • mta-sts: RFC8461で定義される、SMTP MTA Strict Transport Securityポリシーファイルの設置に利用
  • openpgpkey: 「OpenPGP Web Key Directory」でOpenPGP certificateの参照と検証に利用
  • root-key-sentinel-is-ta-(key-tag): RFC8509で、信頼するDNSSECルートキーを示すのに利用
  • root-key-sentinel-not-ta-(key-tag): RFC8509で、信頼しないDNSSECルートキーを示すのに利用
  • www: ブラウザがWebサイトが動作していると想定して利用する

メールアドレス

ここでとりあげる文字列は、利用用途が決まってるため、メールアドレスのローカルパートとして一般ユーザに払い出すべきではありません。(例: webmaster@example.com)
(なお、大文字小文字は区別しません)

  • abuse: RFC2142で、不正利用時の連絡先として指定
  • administrator: 証明書の発行用途で利用 (CA/B Forum)
  • admin: 証明書の発行用途で利用 (CA/B Forum)
  • hostmaster: RFC2142及び、証明書の発行用途で利用 (CA/B Forum)
  • info: 証明書の発行用途で利用 (参考)
  • is: 証明書の発行用途で利用 (参考)
  • it: 証明書の発行用途で利用 (参考)
  • noc: RFC2142で、ネットワークに関する連絡先として指定
  • postmaster: RFC2142及び、証明書の発行用途で利用 (CA/B Forum)
  • root: システムの問い合わせや、証明書の発行に利用?
  • security: RFC2142で、セキュリティ関係の連絡先として指定
  • ssladministrator: 証明書の発行用途で利用(参考)
  • ssladmin: 証明書の発行用途で利用 (参考)
  • sslwebmaster: 証明書の発行用途で利用(参考)
  • sysadmin: 証明書の発行用途で利用(参考)
  • webmaster: Web関連の問い合わせ先及び、証明書の発行用途で利用 (CA/B Forum)
  • www: webmasterのエイリアスとして使用

CA Browser ForumのBaseline Requirementsは、証明書発行に関するガイドラインです。CAやクラウドサービスでも、メールアドレスベースの検証ではこれらに準拠しており、これらのメールアドレスを検証に用いてますね。

おわり

もちろん今回は仕様で利用用途が定義されているものにフォーカスしています。

他にも危険なものとかありそうだけど、まとまってるのかな?

デフォルトでCookieをオリジンに紐づける、ChromeのOrigin-Bound Cookies

Blinkの開発者メーリングリストで「Intent to Prototype: Origin-Bound Cookies」という議論が行われています。

Cookieをより安全にするために、デフォルトでCookieをオリジンに紐づけるようにする提案です。Cookieをset-cookieしたオリジン以外からは、そのCookieにアクセスできないようになります。

詳しい背景や仕組みについては次のページから確認できます。
github.com

かんたんに、Origin-Bound Cookiesの動作をみていきましょう。

オリジンは、スキーム、ホスト名、ポートの組です。それらのうち一つでも異なれば、オリジンが異なることになります。

例えば、次のようになります。

オプトアウト

議論されているOrigin-Bound Cookiesでは、デフォルトの動作を変更します。オリジンを超えてcookieを共有するために、オプトアウトする仕組みが提供されています。

domain属性を付与することで、オプトアウトできます。オプトアウトすることで、異なるホスト名、ポートとcookieを共有することが出来ます。ただし、異なるスキームに共有することは出来ません。

例えば、https://example.comからセットされたcookieでも「Domain=example.com」が設定されていてれば、https://example.com:1234https://sub.example.comにはcookieが送信されます。ただし、スキームが異なるhttp://example.comには共有されません。

Webサイトのバグの報告先を示す contributing.txt

Webサイトのバグを見つけたとしても、その報告先を知る統一的な方法は現状ありません。

たとえば、脆弱性についてはsecurity.txt があります。https://www.facebook.com/security.txt などで使われています。
asnokaze.hatenablog.com

同様の仕組みで、contributing.txt という形式でバグの報告先を示せるようにする仕組みが提案されています。提案仕様は「a simple way to provide informations for contributors」としてIETFに提出されています。

contributing.txtをWebページの最上位階層に配置します (例: https://example.com/contributing.txt )

そのファイルは次の情報を含めることが出来ます。

Admin: Valentin Binotto
Bugs: bugs@vauly.net
Open Source: github.com/valentinbino
License: Creative Commons Attribution 4.0 Int. Public License
Guidelines: github.com/valentinbinotto/v434/guidelines.txt
# Valentin Binotto
# Hello, world!
  • Admin: Webサイトの管理者
  • Bugs: バグレポートを出せるメールアドレスまたはURL
  • Open Source: GithubやGitlabなどより議論するのに適切なURL
  • License: ウェブサイトのコンテンツに適応されるライセンス
  • Guidelines: このWebサイトにコントリビューションするためのガイドラインのURL
  • #~~ : コメント