Crash/Deprecation/Intervention Reporting について

目次

ブラウザがWebページを表示する際に発生したエラーを、任意のエンドポイントにレポートさせる「Reporting API」という仕様があります。今回紹介する機能もchromeでいくつか実際に使用できます。

例えば、以前紹介した Deprecation Reporting もこの仕様によって定義されていました。
asnokaze.hatenablog.com

他にもTLS証明書エラーや名前解決エラーといった、ネットワークエラーを通知するNetwork Error Loggingといった仕様もReporting APIを利用しています。
asnokaze.hatenablog.com

Crash/Deprecation/Intervention Reporting

今までCrash/Deprecation/Interventionという3つのエラータイプが、「Reporting API」のドキュメントで定義されていましたが、議論の結果それぞれ独立したドキュメントに分離されることになりました。

背景は以下を参照
discourse.wicg.io

分離されたドキュメントはそれぞれ下記のとおりです。

レスポンスヘッダで下記のように設定することで、そのドメインでエラーなどが発生した場合に、指定したエンドポイントにレポートが送信されます。

Report-To: { "group": "default",
             "max_age": 10886400,
             "endpoints": [
               { "url": "https://example.com/reports", "priority": 1 },
               { "url": "https://backup.com/reports", "priority": 2 }
             ] }

前述のブログでも紹介しましたが、改めてそれぞれ簡単に紹介ようかとおもいます。

Crash Reporting

サイトを閲覧したブラウザがクラッシュした際に、サイト所有者に通知する機能。

下記のデータがPOSTされます

[{
  "type": "crash",
  "age": 42,
  "url": "https://example.com/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "reason": "oom"
  }
}]

reasonは現状下記の2つが定義されています

  • oom: メモリ不足
  • unresponsive: 反応がない

Deprecation Reporting

サイトを閲覧したブラウザがdeprecatedな機能(JavaScript API)を利用していた場合に、サイト所有者に通知する機能。

例えば、「Application Cache API」や「window.webkitStorageInfo」といったものをChromeで使ってるとDeprecation Reportingが飛びます

下記のデータがPOSTされます

    [{
      "type": "deprecation",
      "age": 32,
      "url": "https://example.com/",
      "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
      "body": {
        "id": "websql",
        "anticipatedRemoval": "2020-01-01",
        "message": "WebSQL is deprecated and will be removed in Chrome 97 around January 2020",
        "sourceFile": "https://example.com/index.js",
        "lineNumber": 1234,
        "columnNumber": 42
      }
    }]
}

Intervention Reporting

サイトを閲覧したブラウザがJavaScriptを実行した際など、セキュリティなどの理由によって動作が変更されたりブロックされた場合に、サイト所有者に通知する機能。

下記のデータがPOSTされます

    [{
      "type": "intervention",
      "age": 27,
      "url": "https://example.com/",
      "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
      "body": {
        "id": "audio-no-gesture",
        "message": "A request to play audio was blocked because it was not triggered by user activation (such as a click).",
        "sourceFile": "https://example.com/index.js",
        "lineNumber": 1234,
        "columnNumber": 42
      }
    }]
}

CookieのPriority属性の仕様

あまり知られていないがCookieにはPriority属性がある。

Chromeでは2013年に実装が入っている(該当コミット)、また提案仕様「A Retention Priority Attribute for HTTP Cookies」も2016年に提出されているが標準化には至ってない。

ここらへんの議論は当時の"メーリングリスト"を参照してください。

そんなPriority属性は、長年動きが無かったが、最近ChromeデベロッパーツールでPriority属性を表示するようになった( Chrome Canary 81)。
(JavaScriptからPriority属性を指定して、Cookieを設定した例)
f:id:ASnoKaze:20191219011406p:plain

超簡単にだが仕様を紹介する。

Priority Attribute

CookieのPriorityは保持優先度です。ブラウザが保存容量(ドメイン毎)の都合でCookieを消す場合はPriorityの低いCookieから消していきます。

値としては下記の3つです。それ以外の値が指定された場合はMediumとして扱われます。

  • High
  • Medium
  • Low

消す際は、LowとMediumごとにLデータ量・Mデータ量ふるい方から消されていきます。細かいところは実装依存になりそうです。

Priorityが指定された場合の、具体的な削除順番は仕様中の例を参照
https://tools.ietf.org/html/draft-west-cookie-priority-00#section-3.1

HTTPヘッダに構造定義を与える Structured Headers の提案仕様 (draft-14)

2年前にも同様の記事を書きましたが、当時はdraft-00でしたが、2年ほど立ち draft-14が出ておりところどころ変わっているので書き直します。
asnokaze.hatenablog.com

背景

新しいHTTPヘッダを定義するときに、新しい仕様毎にシンタックスを記述するのは非常に煩わしい作業です。

そこで、リストや辞書形式のようなデータ構造の定義を「Structured Headers for HTTP」として与えることで、新しいHTTPヘッダを定義するときはこの仕様を参照しリストや辞書形式のヘッダを定義できるようになります。実際、近年提案されている仕様ではしばしば参照されています。

また仕様ではこれらのデータ構造のパース手順も定義されており、実装としてもパースの処理が汎用的に再利用できるようになります。

// 2020/03/10追記
(最新仕様では 名称が "Structured Field Values for HTTP" に変更されました)

概要

Structured Headersでは、

  • トップレベルとして「Lists, Dictionaries, Items」という3つの形式がある
  • ListsとDictionariesはコンテナであり、Items もしくは Inner Listsを持つ
  • ItemsとInner ListsはKey/Value形式でパラメータ化できます
Lists

ListsはItemやInner Listsを持ち、カンマで区切られます。

Example-StrListHeader: "foo", "bar", "It was the best of times."
Inner Lists

Inner Listsはカッコで囲まれ、itemをスペース区切りで持ちます

Example-StrListListHeader: ("foo" "bar"), ("baz"), ("bat" "one"), ()
Parameters

ParametersはitemやInner Listsに関連付けられたKey/Valueのペアです。itemやInner Listsの後ろに;で記述されます。Keyは文字で、valueはitemとなります

Example-ParamListHeader: abc;a=1;b=2; cde_456, (ghi;jk=4 l);q="9";r=w
Dictionaries

DictionariesはKey/Valueからなる順序付きのマップです。

   Example-DictHeader: en="Applepie", da=*w4ZibGV0w6ZydGU=*
   Example-DictListHeader: rating=1.5, feelings=(joy sadness)
   Example-MixDict: a=(1 2), b=3, c=4;aa=bb, d=(5 6);valid=?1
Item

Itemは下記の種類があります

  • Integers
  • Floats
  • Tokens
  • Byte Sequences
  • Booleans

それぞれ例を示します

Integers

Example-IntegerHeader: 42 

Floats

Example-FloatHeader: 4.5

Strings (ダブルクォートで囲まれます)

Example-StringHeader: "hello world"

Tokens (短い単語)
(アルファベット及び":" "/"を持つ。なぜかこれだけ仕様で例が示されていない)

Byte Sequences (*で囲まれたBase64)

Example-BinaryHdr: *cHJldGVuZCB0aGlzIGlzIGJpbmFyeSBjb250ZW50Lg==*

Booleans (?で始まり、0 or 1)

Example-BoolHdr: ?1

使用例

このStructured Headersは多くの仕様で参照されていますが、一つの例をあげます。

FastlyのMark Nottingham氏が提案する「The Cache-Status HTTP Response Header」では、CacheにHitしたかなどをレスポンスヘッダで通知する新しいヘッダを定義しています。

このようにCache-StatusはListであると定義しています。このようにシンタックスの定義はStructured Headersを参照するだけになります。

   The Cache-Status HTTP response header indicates caches' handling of
   the request corresponding to the response it occurs within.

   Its value is a List [I-D.ietf-httpbis-header-structure]:

Listの中身についてはもう少し細かい言及があるのですが、詳細は割愛します
実際のCache-Statusヘッダの例です。

Cache-Status: "CDN Company Here"; res-fresh=545,
                 OriginCache; cache-fresh=1100; collapse-hit=?1

Parameters及びBooleansが使用されている事がわかりますね。

その他

このようなHTTPヘッダでデータ構造を扱うという案が出たとき、最初はJSONを使うことが検討されましたが、議論のすえ現在の形式となっています。その経緯については提案仕様の Appendix-B に書かれています。興味ある方はよんでみてはいかがでしょうか。

HTTPで部分的アップロードを可能にする Partial Uploadsという提案仕様

HTTPリクエストは一度中断してしまうと、途中から再開することは出来ません。特に大きなファイルをアップロードしている場合は、最初からやり直すことになってしまいます。(ダウンロード自体は、Content-Rangeを指定することで部分的な取得が可能です)

そこで、細かく分割して部分的なアップロードを可能にする「Partial Uploads in HTTP」という仕様が提出されています。

この仕様では、PATCHメソッドとContent-Rangeヘッダを使用して部分的なアップロードを行います。また、部分的なアップロードに対するレスポンスコード2xx Sparse Resource(具体的な番号はTBD)を新しく定義しています。

部分的なアップロードは、Content-Typeにmessage/byterangeを指定し、PATCHメソッドでデータを送信します。message/byterangeはmultipart/byterangesのような構造を持ちますが単一のRange領域からなります(Content-Rangeは必須)。

部分アップロードの最初の1リクエストは以下のようになります。この例では600バイト中200バイトをアップロードしています。

   PATCH /uploads/foo HTTP/1.1
   Content-Type: message/byterange
   Content-Length: 281
   If-None-Match: *

   Content-Range: bytes 0-199/600
   Content-Type: text/plain
   Content-Length: 200

   [200 bytes...]


つづけて、次の200バイトをアップロードする場合は、以下のようになります。最初同様message/byterangeを指定します。

   PATCH /uploads/foo HTTP/1.1
   Content-Type: message/byterange
   Content-Length: 283
   If-None-Match: *

   Content-Range: bytes 200-399/600
   Content-Type: text/plain
   Content-Length: 200

   [200 bytes...]

部分アップロードを行うリクエストに対するレスポンスのステータスコードは2xx Sparse Resourceを使用します。このSparse Resourceレスポンスは、データ全体を受信したわけではないが該当の部分アップロードリクエストはエラーではないことを示します。

すべてのデータ全体がアップロードされた際のステータスコードは200 OKを返します。

ネットワークメトリクスを示すTransport-Info HTTPレスポンスヘッダ

トランスポートレイヤの性能を示すTransport-Infoレスポンスヘッダの提案仕様「The Transport-Info Response Header」が提出されています。

この仕様の目的は、ブラウザでより詳しいトランスポートレイヤのパフォーマンスを取得することが目的となっており。HTTPレスポンスヘッダに通信の情報(RTTやMSS)が格納されます。

W3Cで議論されている「Network Information API」よりもより詳しい情報が取得できます。

Transport-Infoレスポンスヘッダ

以下のように、Structured Headersの規則に則って表現されます。

Transport-Info = ExampleEdge; ts=1567176968.69; alpn="h2"; cwnd=24;
                       rtt=250; mss=1460; rttvar=10; dstport=12345

まず最初に製品やサービスを示す識別子(例ではExampleEdge)が入ります。エッジサーバ側のメトリックが続きます。意味は下記のとおりです

  • tls: unitタイムのタイムスタンプ
  • alpn: ALPN識別子
  • cc_algo: 輻輳制御アルゴリズム
  • cwnd: 輻輳ウインドウ
  • rcv_space: 受信ウィンドウ
  • dstport: 送信先ポート
  • mss: Maximum Segment Size
  • rtt: ラウンドトリップタイム (ミリ秒)
  • rttvar: RTTVAR (RFC6298)
  • send_rate: 一秒あたりの送信データ量 (キロバイト/秒)

DoHを利用しないように指示するCanary domainの仕組み

DoHはプライバシー向上のための重要な技術です。

一方で、DoHのディスカバリ、アプリケーションに対してのConfiguration方法、ポリシーの適応など、いくつかの課題が議論されています (IETFの資料を参照)。

課題の一つに、DoHの利用が適さないネットワークにおいて、それをどうブラウザ(クライアント)に通知するのかの問題がある。

DoHの利用が適さないネットワーク/ユーザとは

  • ペアレンタルコントロールなど、子供に不適切なサイトへのアクセスを抑制する必要がある場合
  • 会社内など、社内用途でのドメインを利用している場合

現在このようなネットワークでDoH使用を制御する方法は標準化されていませんが、FirefoxではCanary domainという仕組みを用いてこれを実現しています。

Canary domain

Fifrefoxでは、そのネットワークでDoHを使用するか判断するにあたって「use-application-dns.net.」の名前解決を利用します。

実際にアクセスするとMozillaの解説サイトに飛びます。もちろん名前解決もできます。

$ dig @8.8.8.8 use-application-dns.net. +short
63.245.208.212

Firefoxは use-application-dns.netの名前解決をしてDoHを使用するか決めます。
OSに設定されたDNSサーバを利用して、use-application-dns.net. の名前解決し、以下のどちらかの場合はDoHを使用しません。

  • NXDOMAIN(存在しないドメイン)やSERVFAILなど、NOERROR以外のレスポンスコードが返ってきた
  • NOERRORレスポンスコードだが、AやAAAAレコードが含まれない

ネットワーク管理者(社内DNSISPDNS管理者)がuse-application-dns.netの名前解決に対してNXDOMAINを返すようにすることで、ユーザに対してDoHの利用を抑制できるようになります(DoHが無効になる条件は他にもあり、OSのペアレントコントロール設定なども検出します)。

利用状況

NXDOMAINを返す、ISP内のリゾルバの割合です。
f:id:ASnoKaze:20191201160941p:plain
https://www.isi.edu/~hardaker/news/20191120-canary-domain-measuring.html

その他

悪用されない方法で、適切にポリシーを適応する方法は悩ましいなあと思う今日このごろ

QUIC, HTTP/3の標準化状況を確認したい (2019年11月版)

2020/06/01追記
まるっと解説記事を書き直しました
asnokaze.hatenablog.com


目次

QUICは現在IETFで標準化が進められているトランスポートプロトコルであり、HTTP/3はそのQUICの上で効率よくHTTPのメッセージをやりとりするプロトコルです。

ChromeFirefox, Nginxなどがすでに実装を行っており、「相互接続テスト」を定期的に実施している。その他多くの実装があり、「Implementations」から確認ができる。

その標準化状況について、QUIC WGとHTTP WG両方のチェアを務めるMark Nottinghamが先週行われたIETFで発表した「Quick QUIC Update」の資料が良かったので、大変おこがましいが自分なりに補足しながら紹介したい。

技術的な詳細は過去に紹介しているので、"QUICカテゴリ"をご覧いただければと思います (関連記事をブログ最後に羅列しておきます)。

Status

QUIC WGでは、下記の4つをコアドキュメントとして扱っている。現在 draft-24であり、各ドキュメントとも歩調を合わせて改定されている。(その他にもQPACKやオペレーションに関するドキュメントも扱っている)

QUIC WGでは標準化にあたってEarly-Stage ProcessとLate-Stage Processという2段階のステージにのっとって議論を進めている。Early-Stage Processではドキュメントの著者の裁量が強く早く柔軟性が強いです。Late-Stage Processでは、WG内でのコンセンサスが得られたものが仕様に反映されます。(プロセスの詳細はURLを参照

現在はTransport, TLS, Invariants(説明は割愛)がLate-Stage Processです。HTTP/3, QPACK, RecoveryはEarly-Stage Processですが、Late-Stage Processへの移行も近そうです。

また、先述の通り実装をもちよっての相互接続テストを実施し仕様の確度を高めています。

*2019/11/27追記
HTTP/3, QPACK, RecoveryはLate-Stage Processになりました
https://mailarchive.ietf.org/arch/msg/quic/hxadXDI53V83dCiNe-bKGaws8-A

The Plan

2019年末頃にWorking Group Last Callが予定されています。実装及びデプロイ結果からのフィードバックを受け付けるため、長い停止時間が設けられます。

2020年中頃に、IETFの技術的責任を持つIESG(Internet Engineering Steering Group)に送られレビューされます。

その後RFCとしての体裁が整えられ、RFCとして出版されることになります。

Versions

QUICではたくさんの仕組みや機能が導入されていますが、闇雲になんでも機能追加するわけではなくQUICv1として世の中に出す機能は絞られてきました。そのため、FECやマルチパスといったいくつかの機能はQUICv2へと見送りになってきました。

QUICv2が問題なく使えるように、バージョンのネゴシエーション・管理の仕組みや、ossification(硬直化)を避ける仕組みが議論され導入されています。

しかし、現時点でQUICv2がどの様になるかは、パケットファーマット(invariants以外の部分)や機能含め具体的な議論は始まっていません。

Extensions

QUICは拡張できるようになっています。

現在検討されているもの

  • QUIC Load Balancers (duke-quic-load-balancers)
  • QUIC Version Negotiation (schinazi-quic-version-negotiation)
  • QUIC Datagrams (pauly-quic-datagram)

QUICのロードバランサとバックエンドが連携するための仕様、バージョンをより柔軟にネゴシエーションする仕様、再送を必要としないアプリケーションデータの送信などが拡張として議論されています。

その他に、下記の仕様が検討されています。

  • Loss Bits (ferrieuxhamchaoui-tsvwg-lossbits)
  • 0RTT-BDP (kuhn-quic-0rtt-bdp)
  • Multipath (deconinck-quic-multipath)

経路上からQUICコネクションでパケロス発生したことを観測できるようにする仕様、経路特性を学習し接続を再開したときによりスループットを良くする仕様、Wi-Fiとキャリア回線など複数経路を用いて通信を行うマルチパスの仕様などが議論されています。

Applications

QUICはトランスポートプロトコルですので、アプリケーションプロトコルはHTTP/3に限りません。

多くのアプリケーションプロトコルがQUICの利用を検討しています

  • WebTransport (vvv-webtransport-quic)
  • Media
  • Proxy/tunnelling (e.g., draft-schinazi-masque)
  • Others (e.g., DNS, NETCONF)

WebSocketのようなWebで双方向通信を行うWebTransport(この上でメディアも流すユースケースもあります)や、RTP over QUIC、VPNのようにつかうmasqueプロトコルDNS over QUICなど様々です。

Other Things

その他にも、シミュレータツール、デバック用ログフォーマット、衛星通信での利用などのトピックがあります

  • QUIC Network Simulator
  • QLog logging format (marx-qlog-main-schema)
  • Pluginised QUIC
  • QUIC for SATCOM (kuhn-quic-4-sat)

More Information

その他の関連事項については、下記を参照
https://github.com/quicwg/base-drafts/wiki/Related-Activities

  • 拡張仕様は、ドラフトを書いてQUIC WGへ
  • アプリケーションは、ドラフトを書いてArea Directorへ

関連記事

手前味噌だが、今回取り上げたトピックの多くを本ブログで紹介済みである

仕様関連 (日付降順)

実装関連 (日付降順)

Qiita