DNS over HTTPSサーバを見つけるためのTXTレコードの提案仕様

20190821 追記
この提案は廃案されました
https://mailarchive.ietf.org/arch/msg/doh/qkmhh93Id6XIngH3LJwp-HokH_Y


DNS over HTTPS(DoH)の標準化が進められており、引き続き注目を集めている。
asnokaze.hatenablog.com

一方で、DoHサーバをどのように見つけるか、見に行かせるかの議論が始まっています。
JPNIC Blog :: DNS over HTTPSとDHCP -IETF102における議論- で紹介されている通り、先月行われたIETF102でもDNSゾルバの識別子と利用についてのBoFがありました。

例えば、設定ファイルだったり、DHCPDNSサーバを設定する際にDoHサーバを設定する際にどうすればいいか、どのようディスカバリさせるかといった議論です。

その流れで、DoH関連の標準化を推し進めているPaul Hoffman氏より「Associating a DoH Server with a Resolver」という提案仕様が出ています。

この手提案仕様では、主なユースケースとして名前解決をDoHに切り替えたいブラウザとしており、その次としてOSとしています。

Associating a DoH Server with a Resolver

この仕様では、resolver-associated-doh.arpa に対してTXTレコードを引くことで、そのリゾルバと関連付けられているDoHサーバのURIを取得できるようにします。

この仕組を解釈するリゾルバは、問い合わせに対してもし関連付けられているDoHサーバがあればそのURI (例 "https://dnsserver.example.net/dns-query{?dns}" )を返し、なければ0x00を返します。

おそらくこんな感じ

;; ANSWER SECTION:
resolver-associated-doh.arpa.  600  IN  TXT  "https://example.com/dns-query{?dns}"

DoHサーバを利用する場合は、レスポンスのTTL時間の間だけ使用されることが推奨されています(SHOULD)。

resolver-associated-doh.arpaは「Special-Use Domain Names」として予約されることになります。

Loading Signed Exchangesの仕様 (WebPackaging)

WebPackagingと呼ばれる仕組みが議論されているのは、以前このブログでも紹介したとおりである。
asnokaze.hatenablog.com

この仕組みは3つの仕様からなる。

署名されたHTTP Exchangesをユーザエージェントがどのように読み込むかを定義したLoadingの仕様ですが、
、他のものにくらべ少々遅くなったが、「Loading Signed Exchanges」としてリポジトリに追加されていたので簡単に目を通す。

が、Fetch力が高くないので詳しい人に補足頂ければ幸いだ。

Loading Signed Exchanges

僕なりの理解としては、大まかなLodingの流れは以下の通り。

Signed HTTP Exchangesの一形式であるsxgファイルを https://distributor.example.org/foo.sxg から読み込んで、署名されているhttps://publisher.example.org/foo からのHTTPレスポンスを読み込む例を示す。

f:id:ASnoKaze:20180824015818p:plain

  • ユーザエージェントがhttps://distributor.example.org/foo.sxgをフェッチする
  • 取得したfoo.sxgのMIME Typeがapplication/signed-exchangeであることを確認し、signed exchangesをパースし、証明書や署名や有効期限などもろもろの確認を行う。
  • もともとのリクエストを https://publisher.example.org/foo にリダイレクトする (通常通りのリダイレクト)
  • そのリダイレクトが signed exchanges に含まれるリクエストとマッチすることを確認
  • signed exchangesからレスポンスを得る

具体的には、Fetchの使用に対してMonkey Patchを当てるとともに、公開鍵や署名といったValidationのアルゴリズムを定義している。またService Workerでの扱いについても言及している。

セキュリティトークンを識別するための secret-token URI Scheme の提案仕様 (RFC8959)

2021/01/30 追記:RFC8959で標準化されました
https://www.rfc-editor.org/rfc/rfc8959.html


セキュリティートークンを間違えて公開してしまうセキュリティインシデントが増えています。例えば、シークレットやトークンをソースコードに埋め込んだままコミット・公開してしまったりなどです。

機械的にセキュリティトークンを識別できるようになれば、意図せずそのようなセキュリティトークンがコミットされたり公開されるのを機械的に防げるようになります。

先日IETFに提出された「The secret-token URI Scheme」という仕様ではsecret-token URI Schemeを定義し、セキュリティトークンを識別できるようにします。

トークンにsecret-token:を付けます

 secret-token:E92FB7EB-D882-47A4-A265-A0B6135DC842%20foo

この仕様はIETFのART WGで議論されるようです。

Cookieにかわる Sec-HTTP-State ヘッダの提案

20190424 追記
IETFに提案仕様が提出されました
https://tools.ietf.org/html/draft-west-http-state-tokens-00


Cookieの様々な問題を解決するために、Webセキュリティー界隈で活躍されるMike West氏から「Tightening HTTP State Management」というCookieに変わるHTTPにおいてステートを扱う仕組みが提案されています。

現在はIETFのHTTPbis WGのMLに投稿されただけで仕様が正式にinternet-draftとして提出されたものではありません。まだまだどうなるかは全然わからない状態です。

この提案では、現在のCookieはセキュリティと非効率性とプライバシーの問題があると言っています。

現在のcookieは、Same-Origin-Policyとは異なりオリジンを超えて共有されたり、パスを指定して共有されたりもします。また、Secure属性やHttpOnly属性の利用率は10%以下であり、SameSite属性では0.06%以下となっています。使用されているデータ量も多く、ブラウザによる統計の中央値ではドメインあたり409バイト、99パーセンタイルでは4,601バイトにもなります。

ここまでのCookieの改善など

Cookieをどうにかしたいという要望は根強く、2010年にもAdam Barth氏より「Simple HTTP State Management Mechanism」という提案仕様でcookieならぬ"cake"ヘッダが提案されていました。その後「Origin Cookies」と改題されましたが標準化されることはありませんでした。

既存のCookieの仕様である「RFC 6265 - HTTP State Management Mechanism」に"Cookie Prefixes"や"Same-Site"を追加した改定仕様も進行中ですが、その利用率は低いままです。
asnokaze.hatenablog.com

そういった中で、Cookieに変わる新しいステート管理の新しい仕組みを定義し、Cookieから徐々に移行できるようにと出てきたのが「Tightening HTTP State Management」です。

Sec-HTTP-Stateヘッダ

Cookieの持つ様々な問題を解決するために、「Simple HTTP State Management Mechanism」の仕様では、ブラウザがセキュアなオリジン(HTTPS, WSS)にアクセスする際に256bitのトークンをSec-HTTP-Stateヘッダに付加して送信します。

Sec-HTTP-State: token=*J6BRKagRIECKdpbDLxtlNzmjKo8MXTjyMomIwMFMonM*

サーバはこのトークンを用いてステート管理を行うことになります。

このSec-HTTP-Stateヘッダは以下の特徴を持ちます。

  • Clientがトークンを発行します
  • このトークンはJavaScriptやService Workersからはアクセスできない
  • この256bitのトークンはオリジン毎に生成され、そのオリジンのみに送信されます
  • 非セキュアなオリジン(HTTP, WS)では生成されない
  • same-siteへのリクエスト時のみ送信される(Third-Partyには送信されない)
  • トークンはサーバ、ユーザ、ブラウザによってリセットされるまで保持される

もちろん、サーバ側からトークンを発行可能にするかなどの議論はされるでしょう。

Sec-HTTP-State-Optionsヘッダ

サーバ側からトークンのオプションを指定する事もできるようになっています。HTTPレスポンスでSec-HTTP-State-Optionsヘッダで指定します。すでにいくつか考えられています。

Cross-Siteアクセス

Sec-HTTP-State-Options: ..., delivery=cross-site, ...

Sec-HTTP-State-Options: ..., delivery=same-origin, ...

TTL

Sec-HTTP-State-Options: ..., ttl=3600, ...

Sec-HTTP-State-Options: ..., ttl=0, ...

NginxでTLS1.3の0-RTTハンドシェイク (ssl_early_data)を試す

追記20180922
OpenSSLも対応しました
「support for TLSv1.3 early data with OpenSSL.」
http://hg.nginx.org/nginx/rev/548a63b354a2


昨日、NginxがTLS1.3の0-RTTハンドシェイクをサポートしたので試した。無事動作することが確認できた。

該当コミットはこの2つ

TLS1.3の0-RTTハンドシェイクは、一度ハンドシェイクをした相手とはClientHelloに続けてアプリケーションデータ(HTTPリクエスト)を送信することで、より早くデータのやりとりを開始する方法です。

f:id:ASnoKaze:20180808013052p:plain
(引用: https://blog.cloudflare.com/tls-1-3-overview-and-q-and-a/)

通常のResumptionよりも1-RTT分早くHTTPリクエストを送信されることになります。しかし、このデータは再送攻撃が可能ですので、冪等なリクエスト以外はearly_dataを拒否すべきです。詳しくは以前書いた記事を参照
asnokaze.hatenablog.com

BoringSSL

コミットログに書かれている通り、BoringSSLを使用する必要があります。
基本的には公式のビルド手順のとおりです

(ninjaの公式ページからninjaをダウンロードしておく)

git clone https://github.com/google/boringssl.git
cd ./boringssl

mkdir build
cd build
cmake -GNinja ..
ninja

nginxのビルド準備

#./boringsslのディレクトリ
mkdir -p .openssl/lib 
cd .openssl 
ln -s ../include . 
cd ../ 
cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib

nginxのビルド

wget http://hg.nginx.org/nginx/archive/tip.tar.gz
tar zxvf ./tip.tar.gz
cd ./nginx-ba971deb4b44 #解凍したディレクトリ

./auto/configure  --with-openssl=/PATHTO/boringssl/ --with-http_ssl_module
make

config

nginx.conf内で、ssl_early_data on と指定することで0-RTT early_dataが有効になります

    server {
        listen       443 ssl ;
        server_name  localhost;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

        ssl_early_data on;
...

アクセスしてみる

nginxを起動する

sudo ./nginx-ba971deb4b44/objs/nginx

せっかくなので boringssl のtoolを使う

cat ./boringssl/build/request.txt //early_dataをtxtに書いておく
GET / HTTP/1.1
host:localhsot


./boringssl/build/tool/bssl client -tls13-variant draft28 -connect 127.0.0.1:443  -test-resumption -early-data @./request.txt
Connecting to 127.0.0.1:443
Connected.
  Version: TLSv1.3
  Resumed session: yes
(略)
  Early data: yes #★ Early data: yesとなる 

HTTP/1.1 200 OK
Date: Tue, 07 Aug 2018 16:25:00 GMT
Content-Type: text/html
(略)

nginx ログ

nginxのログでも、$ssl_early_data でearly_dataがあったか確認できる

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '$ssl_protocol $request_time early=$ssl_early_data';

こんな感じのログが出る

127.0.0.1 - - [07/Aug/2018:16:19:15 +0000] "GET / HTTP/1.1" 200 612 "-" TLSv1.3 0.000 early=1

Fetchの仕様で application/report を送信時にCORSが必要になった

以前このブログでも書いたNetwork Error Loggingなど、Webサイトを表示する際に発生した問題のレポートを指定されたエンドポイントに送信する機能が増えてきている。
asnokaze.hatenablog.com

このレポート送信に関する仕様はReporting APIで定義されている。

一方で、Fetchの仕様としてCORSを送信する必要のないContent-Typeは下記の通りになっている 。見ての通り、レポート送信時に使用される content-type である

  • `application/csp-report` [CSP]
  • `application/report` [REPORTING]
  • `application/expect-ct-report+json` [EXPECT-CT]
  • `application/xss-auditor-report`
  • `application/ocsp-request` [OCSP]

この除外リストが出来るまでの議論はいぜん書いたとおり
asnokaze.hatenablog.com

Remove Reporting API from CORS exceptions

上記の除外リストから、application/reportを取り除くようである
github.com

そのため、Reporting API を使用している場合は、CORS対応を対応する必要が出てくる。Network Error Logging は対応必須である。一方で、report-uriディレクティブで個別にレポート先エンドポイントを指定してるCSPやExpect-CTは対応する必要はない。

実装

Reporting: Send CORS preflight before uploading reports」で、Chromeはすでに実装が入っている。

Chrome Dev(69)で実際にnelヘッダを試すとOPTIONSが飛んでくることが確認できた

2018/07/27 01:18:24 [debug] 4815#0: *86 http2 http request line: "OPTIONS /report HTTP/2.0"

Clear-Site-Dataヘッダでブラウザに記憶されているデータを消す

Webブラウザは表示したサイトに関する様々なデータを記憶しています

例えば

  • cookie
  • cache
  • HTTP認証の情報
  • localStorage
  • service worker registrations

しかしサーバ側からこれらのデータを明示的に消すのは難しい場合があります。例えば、httpOnlyのcookieは現在ブラウザにどのようなCookieがセットされているか知るのは難しいでしょう。

そこで、そのようなデータを消す Clear-Site-Data レスポンスヘッダW3Cで議論されています。実は、3年前に「Clear Site Data、ブラウザのローカルデータを削除する仕組み」で書いたときから微妙な変更が入っている。

また、ブラウザへの実装も進んでおり試せるような段階となってきている。

試す

こんな感じのヘッダを付けて、Chromecookieが消えるのを確認した

Clear-Site-Data: "cache", "cookies", "storage"

ちなみに仕様上指定できるのは

雑にCookieを設定する

f:id:ASnoKaze:20180724020335p:plain

消える

reloadしてClear-Site-Dataレスポンスヘッダを受け取ると消える。
executionContextsや、HTTP認証情報などは現状消えないが概ね動作している模様
f:id:ASnoKaze:20180724020714p:plain