世界を動かす技術を、日本語で。

RFC 9849. TLS暗号化クライアントハロー

2026年3月4日原文(rfc-editor.org)

概要

  • RFC 9849は TLSClientHello メッセージ暗号化方式を定義
  • Encrypted Client Hello (ECH) 拡張でクライアント情報の秘匿性向上
  • SNIやALPNなど 機密情報の漏洩を防止
  • Shared ModeSplit Mode の2つの運用形態に対応
  • HPKE を用いた公開鍵暗号と詳細な構成仕様を記述

TLS Encrypted Client Hello(ECH)概要

  • TLS 1.3 ではハンドシェイクの大部分が暗号化されるが、 ClientHelloのSNI (Server Name Indication)など一部は平文で送信され、プライバシーリスクが残存
  • 本RFCで定義される Encrypted Client Hello (ECH) は、 ClientHello全体をサーバ公開鍵で暗号化 する新しいTLS拡張方式
  • ECHにより、 SNIやALPNリスト などの機密情報がネットワーク経路上で秘匿される
  • ECHは TLS 1.3DTLS 1.3 およびそれ以降のバージョンでサポート
  • IETF による標準化、広範なレビューと合意を経て策定

ECHの運用モード

  • Shared Mode
    • サービスプロバイダが全てのドメインのオリジンサーバとして機能
    • TLS接続の終端もサービスプロバイダが担当
  • Split Mode
    • サービスプロバイダはプライベートドメインのオリジンサーバではない
    • DNSレコードはサービスプロバイダを指し、TLS接続はプロバイダ経由でオリジンサーバに中継
    • サービスプロバイダはハンドシェイクの平文部分以外の通信内容にアクセス不可
  • client-facing server (クライアント向けサーバ)と backend server (バックエンドサーバ)という役割分担
    • Shared Modeでは同一、Split Modeでは物理的に分離

ECHの動作概要

  • サーバは ECH構成情報 (公開鍵とメタデータ)を公開
    • DNS経由やプリセットなど複数の配布方法に対応
  • クライアントは ClientHelloInner (機密情報入り)と ClientHelloOuter (外部公開用)を生成
    • ClientHelloOuterに encrypted_client_hello拡張 を付与し、ClientHelloInnerを暗号化して格納
  • サーバは受信時に
    • ECH非対応または復号失敗時はClientHelloOuterでハンドシェイク継続(ECH拒否)
    • 復号成功時はClientHelloInnerをbackend serverに転送しハンドシェイク(ECH受理)
  • クライアントはサーバ応答から ECHが受理されたか判定 し、失敗時は再試行可能

ECHのセキュリティ・プライバシー目標

  • 同一匿名性セット 内のサーバへの接続が識別不能となることが主目的
  • 既存TLS 1.3のセキュリティ特性を損なわない設計
  • DNSやIPアドレスなど他経路からの情報漏洩は、 DNS over HTTPSDNS over TLS/QUIC 等の併用で補完

ECH構成仕様

  • Hybrid Public Key Encryption (HPKE) を用いた公開鍵暗号方式を採用
  • ECH構成(ECHConfig)は以下の要素で構成
    • version :ECHバージョン識別子
    • length :構成データ長
    • contents :ECHConfigContents構造体
  • ECHConfigContentsの主なフィールド
    • key_config :HPKE公開鍵や暗号スイート情報
    • maximum_name_length :バックエンドサーバ名の最大長(パディング計算用)
    • public_name :client-facing serverのDNS名
    • extensions :拡張情報リスト
  • HpkeKeyConfig の主なフィールド
    • config_id :1バイトの構成識別子(クライアントが暗号化時に利用)
    • kem_id :HPKE KEM識別子
    • public_key :HPKE公開鍵
    • cipher_suites :KDF/AEADの組み合わせリスト
  • サーバは複数のECHConfigを 優先順でリスト化 して配布し、クライアントは対応可能なものを選択

ECHの導入・運用上の注意点

  • ECHの導入により利用者のプライバシーが大きく向上
  • ただし、 DNSやIPアドレスでの情報漏洩対策 も併用が望ましい
  • サーバのTLS構成や挙動が一致していることが匿名性セットの成立条件
  • 実装の詳細や運用上の注意点はRFC本文および関連RFC(RFC9460, RFC9848等)を参照

(必要に応じて、次のセクションや詳細仕様、実装ガイドラインなどを新たなタイトルで展開できます)

Hackerたちの意見

数ヶ月前にECHについて書いたんだけど、その時は仕様がドラフトの段階で、すでに公開が承認されてたんだ。ECHやその歴史に詳しくないなら、短いけど読んでみてね: https://www.feistyduck.com/newsletter/issue_127_encrypted_cl... それに加えて、RFC 9849の他にRFC 9848もあるよ - 「DNSサービスバインディングを使ったTLS暗号化ClientHelloのブートストラップ」: https://datatracker.ietf.org/doc/rfc9848/ 記事の中に使い方の例もあるよ。

書いてくれてありがとう、イヴァン!あなたの仕事の大ファンなんだ!今度はQualysに、ECHをサポートしてないサーバーのSSL Labsの評価をBに制限させる必要があるね。それと、HSTSやHSTS Preloadがないサーバーも一緒に。

記事にはその使い方の例があるよ。Goではちょっと難しいけど、そんなに複雑じゃない。私たちは2024年8月にDNS用のAndroidアプリにECHを実装したけど、今のところうまく動いてるよ。https://github.com/celzero/firestack/blob/09b26631a2eac2cf9c...

面白い機能だけど、最近ちょっとイライラしてる。特にCloudflareではデフォルトでオンになってて、無料プランでは無効にできないし、ビジネスプランが必要なんだ。これってバカげてると思うけど、問題を引き起こしてる。会社の「イントラネット」のためにスプリットDNSの設定を試してるんだけど、以前にサイトにアクセスしたことがあると、ECHが記憶されちゃうんだ。だからブラウザが試みて、最終的にはECHエラーで失敗するか、Firefoxではずっと読み込み中みたいにハングしちゃう。すごくイライラするよ。たまにうまくいくこともあれば、全然ダメなこともあるし、キャッシュをクリアしても効果なし。インコグニートモードではうまくいくこともあるけど、そうじゃないこともある。これは本当の問題じゃないけど、「イントラネット」に完全に切り替えてないから、CloudflareのWAF機能を使ってるときは特にイライラする。

スプリットDNSって本当に醜いハックだよね。デバッグが難しい問題を引き起こすばかり。

公開されて嬉しい!ESNIのドラフトの頃から追ってたんだ。インドにいた時は結構役立ったよ。Jioがランダムにウェブサイトをブロックしてたから、CloudflareがESNIのドラフトをサーバーに導入して、Firefoxもクライアント側で対応してたおかげで、SNIベースのブロックを簡単に回避できたんだ。Echの作業が進む中で、両方がESNIサポートを無効にしてた時期もあったと思うけど、今はかなり進んでるね。ECHサポート付きのフォークしたnginxを設定して、クライアント(ブラウザ)テスターを作ったこともあるよ。これでECHがHTTPSサーバーでもっとメインストリームになって、面白い設定ができるようになるといいな。ECHの面白い点は、サーバーが公開名を検証する必要がない(するかもしれない)から、クライアントは中間者(検閲者)が承認したpublic_nameを使って他のウェブサイトに接続できることなんだ。RustTLSクライアントにこれを追加しようとしてるんだけど、今がその作業を再開する良いタイミングかも。[0] https://rfc9849.mywaifu.best:3443/ [1] https://github.com/rustls/rustls/issues/2741

インドにいた時は結構役立ったよ。Jioがランダムにウェブサイトをブロックしてたから。 Jioを使ってるなら、ECHは全く必要ないよ。ブロックはほとんど基本的なもので、暗号化DNS(DoH / DoT / DNSCrypt)やFirefoxで回避できるからね(TLS ClientHelloパケットを2つに分割する)。それに関しては: https://news.ycombinator.com/item?id=34232190

インド政府は、どうしてIPベースでトラフィックをブロックしなかったんだろう?それなら、回避するのがもっと難しくなるのに。

サーバーは、TLS証明書を持っているドメインと一致しないパブリックネームを広告することもできるんだ。例えば、example.comやnsa.govみたいに。これが仕様で許可されているかは100%確信がないけど、Chromeでは動いてる。私の理解では、この機能がないと小規模なウェブサイトのオーナーにはほとんど役に立たない。なぜなら、ECHのパブリックネーム用に別のドメインを登録する必要があるからで、それは検閲者にブロックされちゃう可能性がある。

ECHの面白い特徴の一つは、サーバーがパブリックネームを検証する必要がない(検証することもできる)から、クライアントは中間ボックス(つまり検閲者)が承認したpublic_nameを使って他のウェブサイトに接続できることだ。RustTLSクライアントにこれを追加しようとしてるんだけど、今がその再開に良いタイミングかもしれない。これがあるからこそ、年齢確認法が合理的になるんだ。高度な親でも「18歳になるまで子供にコンピュータを使わせない」みたいな非解決策なしでは検閲が技術的に不可能になるから、残された解決策はサービス運営者に責任を負わせる法律的なものになる。結局、法律がどの管轄で追いついても検閲は受けることになるけど、マルウェア(例えば広告やトラッキングソフト)がその機能を果たすための不透明性も提供することになる。

ECHについて不思議に思うことがあるんだ:> クライアント向けのサーバー証明書を検証する際、クライアントは公開名をDNSベースの参照アイデンティティとして解釈しなければならない [RFC9525]。DNS名とIPアドレスを同じ構文に組み込むクライアント(例えば、[RFC3986]のセクション7.4や[WHATWG-IPV4])は、IPv4アドレスとして解釈される名前を拒否しなければならない。明らかにIPv6の存在を考慮していないだけでなく、なぜIPベースの証明書が明示的に除外されているの?これじゃあ、小さなサーバーには全く意味がなくて、SNIのスヌーピングからの保護を提供するためには、ホスティングを共有ホストや巨大なCDNに移行する必要があるんだ。

それは、名前をIPアドレスのように見せることはできないって言ってるんじゃないかな。つまり、構文がwww.google.com[142.250.117.139](これは私が作った構文だけど)だとしたら、142.250.117.139[142.250.117.139]のようにはできないってこと。

Hacker Newsで議論の続きを見る