Cross-Origin-Resource-Policyヘッダとは

Cross-Origin-Resource-PolicyヘッダというのがSafari 12でサポートされるらしい

もともとは、W3C側でFrom-Originと呼ばれていた仕組みらしいが、Fetch Starndardに入れる議論がされているようだ。

github.com

このCross-Origin-Resource-Policyヘッダを用いることで、自分サイトでホストしている画像やJavaScriptなどのリソースをクロスオリジンで他所のサイトで表示・利用されることを防ぐことができる。

https://example.com/img.jpg を<img>タグで呼び出せるのはexample.comのサイトだけで、https://asnokaze.comから<img>タグで画像を埋め込んでも表示することができなくなる。

Cross-Origin Read Blocking (CORB) とは」でも書いたように、昨今サイドチャネルなどの攻撃によってリソースなどのデータが第三者に読み取られる可能性があるため、それらの攻撃を防ぐのを目的にしている。( Issue参照 )

サイドチャネルを行う目的のサイトで、本人しか見えない画像や、http://localhost/img.pngを読み込まれて、中身を見られたりしたら困るわけだ。

Cross-Origin-Resource-Policyヘッダ

画像やJavaScriptなどのリソースを返すときに、レスポンスヘッダにつける。

Cross-Origin-Resource-Policy: same-origin

(WWDCではヘッダ値はsameと書かれていたが、Fetchの仕様ではsame-origin/same-site)

  • same-originは同一オリジンの場合のみ許可される
  • same-siteはhttpsかつ同じホスト名の場合のみ許可される

まだ議論中なので、実際どうなるかはわからない

QUICの現状確認をしたい 2018/5 (Stream 0の再設計案などなど)

IETFでは引き続き、QUICの標準化が進められています。


次回
asnokaze.hatenablog.com

前回分
asnokaze.hatenablog.com


現状確認したい

ちょうど先週に、コアドキュメントのdraft-12も出ています

例えば大きなところで、draft-11で「Coalescing Packets」が入り複数のQUICパケットを一つのUDPデータグラムに格納できるようになった。draft-12ではパケット番号の暗号化などの更新が含まれています。これによって、通信経路上ではパケットを観察してもほとんどの情報が見えなくなりました。

また、HTTPヘッダの圧縮の仕様であるQPACKもwg draft-00が出し直されており、大きな差分があります。

ホットトピックとして、後述するStream 0の再設計や、ECNサポートがあります。
6月4~5日に行われる、QUIC WGの中間会合で議論されることでしょう。
wg-materials/agenda.md at master · quicwg/wg-materials · GitHub

相互接続テスト状況

QUICでは、draftバージョンの実装を持ち寄って相互接続テストを定期的に行っています。
現在は、「5th Implementation Draft」としてテストしています。

f:id:ASnoKaze:20180530013031p:plain

Stream 0 Design Team

draft-12のQUICでは、Stream 0上でTLS1.3のメッセージをやり取りして、そこから通信を暗号化するための鍵を共有します。

このStream 0上でのTLS1.3のやりとりする設計は、IETF101で問題が提起されました。その時の発表資料は、「wg-materials/Stream0-EKR.pdf at master · quicwg/wg-materials · GitHub」で公開されています。

以前以下の記事でも書いたとおり、Stream 0上でCrypto handshakeを行うため、Stream 0の再送や信頼性について特殊扱いすることになっています。ストリームは転送順番やロスが回復されますが、そのためのメッセージもQUICでは暗号化されますが、Stream 0では鍵の共有を行っている途中というわけです。(僕の認識が違ったらすみません)

QUIC over DTLSの議論も行われましたが、変更が大きすぎる点やDTLS自体への変更も考える必要があるため、QUIC over DTLSの方向ではなく、Stream 0を再設計する方針となりました。
asnokaze.hatenablog.com

Stream 0 の再設計には、デザインチームが結成されました。
この「Stream 0 Design Team」は、MLにかかれている通り、ガチ勢ばかりです。

Stream0 Design Team Proposal

そのStream 0 Design Teamによる、提案が出てきました。

Documentの方の図を見ると、どのような変更がされたのかがよくわかります。

draft-12では以下のような感じです
f:id:ASnoKaze:20180530011328p:plain
stream 0でTLSレコードをそのまま送信します。TLSレコードには通常通り、ServerHello, EncryptedExtensions, Fin, NewSessionTicketsなどのTLSメッセージが含まれています。


提案方式では
f:id:ASnoKaze:20180530012004p:plain
Stream 0を撤廃し、新しく定義されたCRYPTO_HSフレーム上にTLSレコードではなく、TLSメッセージを直に設置しています。Stream 0を撤廃することで、Stream 0の特殊扱いはなくなります。
(CRYPTO_HSフレームは、CRYPTOフレームに改名されるかも)


おわり

この変更により、パケット番号空間や再送らへんもいろいろ変更が入っています。ちょっと細かいところまで理解が進んでいないので、時間をかけて差分を読んでいきたいです

ブラウザのネットワークエラーをレポートさせるNetwork Error Loggingが来た

20180727追記
CORS対応が必要になりました
asnokaze.hatenablog.com

20180703追記
ドキュメントはhttps://w3c.github.io/network-error-logging/ にが移されました

20180608追記
仕様上は、jsonの各値はハイフンではなく、アンダースコアを使用するようになります

  • report-to => report_to
  • max-age => max_age
  • ... etc

https://github.com/WICG/network-error-logging/commit/86c4d1c0fa4c5d5ca1d8bdcd9fa931e7e4ab65c2

こんな感じ

nel: {"report_to": "network-errors", "max_age": 2592000, "include_subdomains": true, "success_fraction": 1}
report-to: { "endpoints": [{"url" : "https://asnokaze.com/report", "priority": 1}], "group": "network-errors", "max_age": 10886400, "include-subdomains":true}


以下本編


TCPコネクションタイムアウトTLS証明書エラー・名前解決エラー・リダイレクトループなど、ブラウザでは様々なネットワークエラーが発生します。ユーザ側の環境にも依存するため、サーバ側からは検知できない場合もあります。

そういったブラウザで発生したネットワークエラーをレポートさせる「Network Error Logging」がついに、Chrome開発版(dev) で利用できるようになったので試してみる

たまにdisableになってたりするけど、再起動すると使えたりする。。。

Network Error Logging

Network Error Logging」は、W3CのWICGで議論されている仕様です。

HTTPレスポンスヘッダで、nelヘッダを指定することでネットワークエラーを指定したエンドポイントに対してレポートするようになります。レポート先エンドポイントは「Reporting API」で定義されるように、report-toヘッダで別途指定します。

指定例

nel: {"report-to": "network-errors", "max-age": 3600, "include-subdomains": true,"success-fraction": 0}
report-to: { "endpoints": [{"url" : "https://asnokaze.com/report"}], "group": "network-errors","max-age": 10886400, "include-subdomains":true}

nelヘッダでは以下のような指定ができます

  • report-to: エンドポイントのグループ識別子(別途report-toヘッダで指定する)
  • max-age: このヘッダで指定される指示の有効期限
  • error-fraction: エラー発生時にレポートを送信する割合。1.0~0.0の間で指定
  • success-fraction: エラーが発生していなくてもレポートを送信する割合。1.0~0.0の間で指定
  • include-subdomains: サブドメインのネットワークエラーもレポートするか

このように指定すると、以後そのドメインでネットワークエラーが発生した場合に以下のようにレポートがPOSTされる。
404エラーが発生した場合と、名前解決エラーが発生した場合のレポート例です(jsonは整形済み)

どのページで、どういたネットワークエラーが発生したか確認できる。

[
	{
		"age": 240003,
		"report": {
			"elapsed-time": 33,
			"protocol": "http/1.1",
			"referrer": "https://asnokaze.com/nel.html",
			"sampling-fraction": 1,
			"server-ip": "160.16.124.39",
			"status-code": 404,
			"type": "http.error",
			"uri": "https://asnokaze.com/img/b.gif"
		},
		"type": "network-error",
		"url": "https://asnokaze.com/img/b.gif"
	},
	{
		"age": 147358,
		"report": {
			"elapsed-time": 7,
			"protocol": "",
			"referrer": "https://asnokaze.com/nel.html",
			"sampling-fraction": 1,
			"server-ip": "",
			"status-code": 0,
			"type": "dns.name_not_resolved",
			"uri": "https://nothing.asnokaze.com/"
		},
		"type": "network-error",
		"url": "https://nothing.asnokaze.com/"
	}
]

動作確認

Chromeの「chrome://net-internals/#reporting」より、Network Error Loggingが有効であること、レポートとして送信されるデータが確認できる
f:id:ASnoKaze:20180528205145p:plain

一応、NEL確認用ページ
https://asnokaze.com/nel.html

エラーの種類

Network Error Loggingでは様々なエラーが定義されています。

  • ok エラーはない
  • dns.unreachable DNSサーバへ到達できない
  • dns.name_not_resolved DNSサーバは応答したが名前解決に失敗
  • dns.failedRequest 上記以外の理由で名前解決エラー
  • tcp.timed_out TCP接続タイムアウト
  • tcp.closed TCP接続がクローズされた
  • tcp.reset TCP接続がリセットされた
  • tcp.refused TCP接続が拒否された
  • tcp.aborted TCP接続が中断された
  • tcp.address_invalid TCP接続のアドレスが正しくない
  • tcp.address_unreachable TCP接続のアドレスへ到達できない
  • tcp.failed 上記以外の理由でTCP接続が失敗した
  • tls.version_or_cipher_mismatch TLSのバージョンや暗号が合わない
  • tls.bad_client_auth_cert クライアント認証が正しくない
  • tls.cert.name_invalid 証明書の名前が正しくない
  • tls.cert.date_invalid 証明書の有効期限が正しくない
  • tls.cert.authority_invalid 証明書のauthorityが正しくない
  • tls.cert.invalid それ以外の理由で証明書が正しくない
  • tls.cert.revoked 証明書が執行している
  • tls.cert.pinned_key_not_in_cert_chain key pinningのエラー
  • tls.protocol.error TLSプロトコルエラー
  • tls.failed それ以外の理由でTLS接続が失敗した
  • http.protocol.error HTTPプロトコルのエラー
  • http.response.invalid レスポンスが空やcontent-lengthが不一致、そのたユーザエージェントがレスポンスの処理を中断
  • http.response.redirect_loop リダイレクトループ
  • http.failed 上記の理由以外でHTTPエラー
  • abandoned ユーザによる中断
  • unknown 不明

今後

Blinkの開発者MLでChromeへの導入について議論している
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/nNji_u7BRxo

このまま行けば、Chrome 68の安定版にも入ってくるだろう

GREASE for HTTP/2 の提案仕様

AkamaiのMike Bishop氏から、「GREASE for HTTP/2」という提案仕様が出ています。

HTTP/2では、未知のフレームタイプとSETTINGSパラメータは無視するようになっています。これは、将来HTTP/2を拡張できるようにするためで、実際に「RFC 8336 The ORIGIN HTTP/2 Frame」では新しくORIGINフレームを定義しています。新しい機能をつかっても、未対応な実装にはただ無視されるだけですので、利用しやすいです。

本来は未知のフレームやSETTINGSは無視すべきですが、未知のSETTINGSパラメータによって通信を終了する実装があるようです(URL)。このような実装は、将来の拡張を妨げる原因になります。

そこで、HTTP/2にもGREASEを導入するのが今回の提案です。また、HTTP over QUICにおいても同様の仕組みが盛り込まれるかもしれません。

GREASE for HTTP/2

GREASEとは

TLSにおけるGREASE、「Applying GREASE to TLS Extensibility」についての解説が詳しいです
jovi0608.hatenablog.com

ちゃんと、未知のパラメータが無視されるように、GREASE用の意味を持たないパラメータを送信します。これによって、日頃から未知のパラメータを受け取っても不具合を起こさず無視する実装であることを確認します。

こうすることで、実際にプロトコルを拡張する前、実装者は未知のパラメータを受け取ったときに不具合があれば気づけるようになります。

GREASE for Frame Types

0xb + (0x1f * N) のフレームタイプをGREASE用に予約します。このフレームはまったく意味を持っておらず、PADDINGの代わりに使用できます。

具体的には、0x2A (42), 0x49(73), 0x68(104).... などのフレームタイプ番号です。

GREASE for SETTINGS

"0x?a?a" のSETTINGSパラメータをGREASE用に予約します。このSETTINGSはまったく意味を持っていません。

具体的には、0x0a0a (2570), 0x1a1a(6682), 0x2a2a(10793).... などのSETTINGSパラメータです。

Sec-Metadataヘッダについて

20190215追記
Sec-MetadataはFetch Metadataになりました
asnokaze.hatenablog.com


CSRF攻撃やクロスドメインリクエストに対してサイドチャネル攻撃をすることで、情報がリークすることがあります。

それを防ぐために、どのようにHTTPリクエストが行われたかサーバサイドでより詳しく判断できるように、Sec-Metadataヘッダという仕様がW3Cの WebAppSec WGで議論されています。仕様については提案者のMike West氏のリポジトリに説明があります「Sec-Metadata (TODO: Bikeshed the name)

すでに、Chromeへの導入も検討されています。
Intent to Implement: The `Sec-Metadata` HTTP request header.

例を見るとより分かりやすいと思います

Sec-Metadataヘッダ

たとえば、銀行のWebサイトで講座を操作するエンドポイント(リクエストをうけるURL)が、タグでクロスドメインでアクセスされることはないはずです。

Sec-Metadataヘッダは、そのHTTPリクエストがどのようなリクエストなのか情報を付加します。

以下は例です。

// <picture>
Sec-Metadata: initiator=imageset, destination=image, site=cross-site, target=subresource

// Top-level navigation
Sec-Metadata: initiator="", destination=document, site=cross-site, target=top-level, cause=user-activation

// <iframe> navigation
Sec-Metadata: initiator="", destination=document, site=same-site, target=nested, cause=forced
  • initiator及び、destininationは どのようにしてリクエストがトリガーされたかわかります。
  • targetは、browsing contextを示すtop-level, nested, subresourceのどれかになります
  • siteは、same-origin, same-site, cross-siteのどれかです
  • causeは、user-activation、forcedです。URLバーへの入力などユーザのアクションによってリクエストが行われたのか、window.locationなどユーザの意志とは別にリクエストが行われたのか識別できます

これらの情報を元に、サーバでは想定していないかどうか識別できるようになります。

Web5Gとはなんなのか

W3Cでは、「Web5G」を掲げ5G及び関連するネットワークの進化に向けて、それにあわせたWeb標準技術・APIを模索しているようである。

個人的な印象としては、ネットワークレイヤとWebアプリケーションレイヤが連携するようなイメージでいる。ネットワークを性能ごとに切り出して提供するネットワークスライスや、ネットワークエッジで処理を行うモバイルエッジコンピューティング(MEC)を具体的に想定しているものもあれば、そうでないものもある。

すでに幾つかの資料がネット上に上がっており、僕は5Gは全然詳しくないが、今回は「Web5G Roadmap」と「Web5G Workshop」を眺めつつ、どのような事が思い描かれているかみていく。

5Gとどのように関わるかわからないが、BBCのネットワークエッジまで HTTP over QUICマルチキャストで配信する例は非常に興味深い

Web5G Roadmap

W3Cのロードマップの中に「Web5G Roadmap」というページがある。既に標準化が進められている仕様の他に、「Features not covered by ongoing work」として将来思い描いている機能の一部が紹介されている。

特に「Network Control」に書かれている部分は興味深い

Real-time adaptative to live network conditions

エッジに設置され使用されるマルチアクセスエッジコンピューティング(MEC)によって、現在のネットワーク環境をリアルタイムにサーバ(クライアントへも?)に通知されるようなネットワークの登場が考えられている。そのときにブラウザはアプリケーションにどのような情報を提供すれば良いのか考えているようだ

セルラネットワークから、サーバへの情報提供可能にするメカニズムとプロトコルIETFで議論されているようだ。
Mobile Throughput Guidance Inband Signaling Protocol

Adaptation to cost of network operations

以前書いた、Mobile Data Plan Sharing APIのように、ユーザでデータPlanと連携する仕組み。ユーザが使っていない時にあわせてバックグラウンドで同期する仕組みなどを一般化できるか考えているようだ
asnokaze.hatenablog.com

Network-provided optimizations

WebRTCでは、アプリケーションプロパイダがNATやファイアウォールを超えるためのリレーサーバ(TURNサーバ)を提供しています。

ネットワーク事業者がこれらをサービスとして提供できるようなる仕組みが、「Operator-Assisted Relay Service Architecture (OARS)」で考えられている

Prioritization in enterprise networks

AppleCiscoは、ビジネスアプリケーションに最適化されたエンタープライズネットワークを提供するために協力してきました(URL)。これをWebアプリケーションへも拡張できるか?

Web5G Workshop

5/10 ~ 5/11にかけてイギリスで「W3C Web5G Workshop」が行われました。その資料が上がっているので幾つか絵を紹介する

Enabling the thrilling applications that will drive usage of 5G networks

Web技術やプロトコルの進化や利用の広がりがまとめられている(ppt URL)。その中で「Integration of the Network Protocol Layer」というスライド、Webとネットワーク制御レイヤが連携する図が出ている。

以下の図では2つの例が出ており、ブラウザからネットワークの情報を取得したりパラメータをセットする。

  • ブラウザから、Network Controle Endpointに対し現在のネットワーク状況を問い合わせ取得する。取得した情報をJavaScript APIでアプリケーションに提供する
  • ブラウザからNetwork Controle Endpointに対してnetwork adaptationを要求し、ネットワークに対してQoSが設定される

f:id:ASnoKaze:20180517012822p:plain

Network advances for Media: Server Push

BBCの発表(スライドURL)。動画は、MPEG-DASHでユニキャスト配信されており、その量が増えているという話のようだ。

そのなかで、ネットワークエッジにデバイスを設置し、そこまでマルチキャストで配信して、そこからユニキャストで配信などやっているようである。

BBCではQUICの利用を考えているようで、IETFでもQUICを用いたマルチキャストやサーバプッシュに関する拡張を提案している。

workshopでのこの一枚が象徴的で、ネットワークエッジまで HTTP over QUICマルチキャストで配信し、そこから先をユニキャストで配信することを考えているようである
f:id:ASnoKaze:20180517013810p:plain

Immersive Web & 5G

サムスンのWeb, XR, 5Gに関する発表(スライドURL)。

おそらく、低レイテンシで帯域が増えるとゲームやXRにとって良いという話

The evolution of the Web to enable greater network collaboration

IETFでのworkの話。レイヤが違くてあまり良くわからない...

Web5Gとはなんなのか

よく分からない

プロトコルにおける「堅牢性原則」は害悪か

Internet Architecture Board (IAB)でもあるMartin Thomson氏から「The Harmful Consequences of the Robustness Principle」という文書が提出されている。

これは、堅牢性原則(Robustness Principle)について言及している文書である

Robustness Principle

プロトコルの設計と実装に関する原則として、「送信するものに関しては厳密に、受信するものに関しては寛容に」と掲げる堅牢性原則(Robustness Principle)というものがある。

TCP/IP, SMTP, DNS, FTPなどの開発に関わった故ジョン・ポステル氏によって提唱され、ポステルの法則とも呼ばれている。

Wikipedia(ジョン・ポステル)によると

元々はポステルがTCPを規定した RFC793 において
相互運用性を確保するためにTCPの実装が持つべき性質として要約した節が
より一般化されて知られるようになったものである。

と書かれている。

当時の仕様の曖昧性や解釈の違い、実装のバグなどがあったとしても、極力通信が続けられるようにという原則である。プロトコルがデプロイされ使われるようにするため、このような原則となっている。

1996年に発行された RFC1958 Architectural Principles of the Internetでも「Be strict when sending and tolerant when receiving」と書かれている。

The Harmful Consequences of the Robustness Principle

提出された「The Harmful Consequences of the Robustness Principle」では、堅牢性原則(Robustness Principle)では、バグのある実装との通信を可能とするために受信側が寛容性を持つと、バグを定着させることになり、長期的なプロトコルのメンテナンス(拡張)を難しくすると述べています。

JSONの例があげられており、元の仕様であるRFC4627「The application/json Media Type for JSON」ではUnicodeの処理、オブジェクトメンバーの順序付け、数値のエンコーディングなど、詳細に書かれておらず、実装によってさまざまな解釈がされた。更新された RFC7159でも問題は解決されておらず、サブセットを定義し問題ある部分の仕様を禁止したRFC7493 I-JSON とも相互運用できていない。そのため、広くは使用されておらずJSONパーサは、[ECMA262]で指定されたより正確なアルゴリズムを実装している。

その他にもTLSのバグのある実装と通信を可能にするためのワークアラウンドが行われていることや、HTTP/1.1の仕様の曖昧性を無くすために数年の労力を要したことなどがあげられている。

そのためこの文書では、堅牢性原則(Robustness Principle)よりも、初期設計やデプロイを超えて長期的なプロトコルのメンテナンスの継続を推奨しています。

エラーハンドフィングとフィードバック

プロトコルのメンテナンスするうえで、実装しデプロイしている人からのフィードバックが重要です。

エラーハンドリングについては、仕様に不正状態の取扱について記述されていることが理想的です。そして実装は、エラー状態からの回復を試みるのではなく、致命的なエラーとすることでそれを改善する動機を与えます。

また、自動化されたエラーレポートの仕組みは、デプロイされたプロトコルのより良いフィードバックを得ることが出来ます。実装者に不具合をレポートする仕組みは優れていますが、ユーザのプライバシに留意する必要があります。

所感

ここ数年だけを外から見ても、ossification(硬直化)と言われているように、プロトコルのメンテナンスに対するコストは上がっているように見える。エラーハンドリングやレポーティングの仕組みが充実していくのは非常に喜ばしい一方で、やはり実際に通信するためバグ実装に対するワークアラウンドが出てくるのはどうしても不可避に感じる。

HTTPの仕様改定がまた始まっているように、プロトコルのメンテナンスは継続して進めていかれるのは明らかであるし、続けていかなければならない。そのために、より良い仕組みや考え方が広まっていけばいいなあと思いました。