HTTP 418ステータスコードが予約される

「418 I’m a tea pot」としてよく知られる 418 ステータスコードについて、IETF HTTPbis WGで議論になっていました。

「418 I’m a tea pot」はジョークRFCである「RFC2324 Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)」で定義されているステータスコードです。

ここで注意するのは、418はHTCPCPで定義されているステータスコードであり、HTTPで定義されているステータスコードではないという点です。

この議論については以前 Qiita で書いたとおりです。
qiita.com

HTTPで418ステータスコードを予約

以前このブログで書いたとおり、HTTPセマンティクスに関して仕様の再改定が行われております
asnokaze.hatenablog.com

その後、3つの仕様に分割され、HTTPのセマンティクス、HTTP/1.1のフォーマット、キャッシュに関する3つの文書に整理されています。

この改訂版HTTP仕様 (HTTPtre) のdraft-03が本日提出され、そのHTTP Semanticsでついに418が Unused として予約されました

418 (Unused)

418はすでにHTTP実装でイースターエッグとして実装されている可能性があるため、418を予約し、今後も仕様としては418は利用しないことになりました。

Auto Upgrade Mixed Contentとは

HTTPSのサイト内にHTTPで提供される画像やスクリプトがあると、「Mixed Content」の仕組みによりURLバーに黄色い警告が出たり、リソースがブロックされます。

もちろんスクリプトがブロックされればWebページを正しく表示できません、URLバーに表示されたシールドマークから通信を許可することもできますが、一般ユーザにとって分かりにくいUXとなっています。

そこでChromeでは、HTTPで読まれるリソースをブロックするのではなく、HTTPSに自動でアップグレードしてリソースを取得する「Autoupgrade Mixed Content」という仕組みが検討されています。

以前、GoogleのMike West氏から提案されていた「Mixed Content Level 2」と似たような仕組みです。
asnokaze.hatenablog.com

( Auto Upgrade Mixed Contentの資料には「THIS DOCUMENT IS PUBLIC」と書かれてるので、おそらく大丈夫)

実験

Chromeでは、6通りの方式を実験してどのようなアップグレード手法が有効か模索しようとしています。この実験を解析し、新しい機能を改めて提案するかが決定されます。

3種類のアップグレード方式と、それぞれについてHTTPSのロードに失敗した場合HTTPにフォールバックするかの2種類を試し、計6種類を実験するようです。

stableのユーザのうち1%で実験を行うと書かれています。この実験では、画像など今までブロックされていなかったリソースもフォールバックなしだと表示されなくなる場合がありそうです。

方式

Upgrade blockable mixed content to HTTPS

Scriptなどのblockable mixed contentをアップグレードします。すでにブロックされているリソースですので、HTTPSにアップグレードしてリソースが読み込めなくてもページを破損させることはありません。

Upgrade only optionally blockable mixed content to HTTPS

画像などのoptionally blockable mixedのみをアップグレードします。通常、表示できているリソースですので、HTTPSににアップグレードすることで読み込めなくなり、ページを破損させる可能性があります。

Upgrade all mixed content to HTTPS

すべてのmixed contentをアップグレードします。このケースでは、警告表示や、ユーザによるmixed contentの許可はなくなります。

サイトがupgrade-insecure-requests ヘッダを指定した場合と似た挙動となります。

フォールバック

HTTPSにアップグレードを試みて、リクエストが失敗したりタイムアウトした場合はHTTPにフォールバックします。このフォールバックは、表示速度が遅くなるとともに処理も複雑になることが懸念されています。

NTPを暗号化する Network Time Security for NTP の提案仕様

サーバが正しい時刻に設定されていることは重要であり、時刻同期に使用されるNTPにおいてもサーバの認証や改ざんを防ぎたいというモチベーションは理解できる。

IETFのNTP WGでは、まさにNTPを暗号的に保護するNetwork Time Security for the Network Time Protocol」という仕様策定が進められている。

NTPにはいくつかモードがあるが client-server モードを前提としている。

NTPは詳しくないがざっと見てみる

(正しくはNTPの暗号化ではなく、保護的な感じはある)

目的

Network Time Securityの目的は以下の通り

  • Identity: x.509 証明書で通信相手を確認する
  • Authentication: 時刻同期のパケットを認証し、改ざんされていないことを確認する
  • Confidentiality: 時刻情報に秘匿性はありませんが、NTP拡張フィールドの暗号化をサポートする
  • Replay prevention: 以前のパケットが再送されても検知できるようにする
  • Request-response consistency: クライアントの要求に対する応答で有ることを確かにする
  • Unlinkability: クライアントが別のネットワークに移動して通信を行ったとしても、経路上からは同一クライアントか識別できないようにする
  • Non-amplification: 増幅攻撃が行われないように、リクエストより大きなレスポンスを返さない
  • Scalability: サーバはユーザ固有の状態を保存せず、多くのクライアントにサービスを提供できるようにする

プロトコル概要

このNTSは2つの疎結合のサブプロトコルからなります

暗号化するための鍵を交換するNTS Key Establishment と、NTPv4を暗号化してやりとりするための拡張を定義したNTS Extensions for NTPv4です。

f:id:ASnoKaze:20181005023438p:plain

NTS Key Establishment (NTS-KE)

NTPv4のNTS拡張領域で使用するキーマテリアル(お馴染み RFC5705)を取得するメカニズムです。

TLSを使用して鍵を交換し、クライアントに最初のCookie、NTPサーバのIP等を提供します。また、暗号アルゴリズムなどいくつかのパラメータをネゴシエーションします。

NTS Extensions for NTPv4

NTPv4でNTS用の拡張領域を持ちます。この領域によって正しいサーバと通信できており、時刻情報が改ざんされていないことを確認できるようになります。

具体的には以前に取得したキーマテリアルを使用してNTPv4を暗号的に保護する複数の拡張領域が定義されます。

すべての状態はクライアント側に保持され、サーバはクライアントの状態を保持する必要がないため、スケーラビリティがあります。これらの拡張フィールドには、NTS-KEハンドシェイクから抽出されたキーマテリアルを使用して計算されたCookieと認証タグが含まれます。

NTPサーバはこのクッキーを使用してこのキーマテリアルをリカバリし、認証されたレスポンスを返します。 レスポンスには新しく暗号化されたCookieが含まれます。クライアントは次はこのCookieを使用します。こうすることで、返されたレスポンスは自身のリクエストがあってから生成されたレスポンスであることが確認できます。

実装

すでにいくつかの実装が出ている

その他

時刻同期プロトコルでサーバ認証を行う際、クライアントの時刻が同期されておらずサーバ証明書の検証が失敗される問題が有る。このドキュメントでも完璧な解決策は無いと書かれている。いくつかの緩和策は述べられていますが、やはり本質的な改善では無いようです。

JS Self-Profiling API とは

W3C Web Performance Workingの議事録に「JS Self-Profiling API」についての議論があったので簡単に眺めておく。

ミーティングの「発表スライドはこちら

JS Self-Profiling API

いわゆるRUM(Real user monitoring)などと同様、実際のユーザ側でJavaScriptのプロファイルを取得可能にするというのが「JS Self-Profiling API」のようだ。

f:id:ASnoKaze:20181004002206p:plain

ユーザにより端末やネットワーク環境が違うため、実際のユーザ側でJavaScriptのプロファイルを取りたい。timerを使うことで擬似的に測定はできるが、コード量やオーバヘッドが増える。この提案を行っている、Facebookの人らはJavaScriptとSharedArrayBuffersでサンプリングプロファイラを実装したが正確性とパフォーマンスの欠点があると述べています

といった背景から、このような提案が出ているようだ。

使い方

プロファイルを取るサンプルコードが出ている。
performance.profileでプロファイリングを開始して、stopして得られた結果を送信するような流れである。

const profiler = performance.profile({ categories: ['js'], sampleInterval: 10 });
for (let i = 0; i < 1000000; i++) {
     await doWork();
}
const trace = await profiler.stop();
sendTrace(trace);

profileデータ

得られたデータのフォーマットは、V8のTrace Event FormatGecko profile formatを参考に作られているようだ。

interface ProfilerTrace {
  readonly attribute FrozenArray<ProfilerFrame> frames;
  readonly attribute FrozenArray<ProfilerStack> stacks;
  readonly attribute FrozenArray<ProfilerSample> samples;

  [Default] object toJSON();
};

framesから実行状態を取れる模様

QUICの信頼性のないデータグラム拡張(MESSAGEフレーム/Datagramフレーム)

QUICはUDP上で暗号化された信頼性のあるデータ通信を提供するトランスポートプロトコルです。

現在IETFの「QUIC WG」で標準化が進んでおり、先行して実装されていたGoogle版QUICもIETF版QUICへの移行が進められています。

QUICのアプリケーションレイヤ

現在QUIC上のアプリケーションプロトコルとしては「HTTP over QUIC」にフォーカスして標準化が進められています。

一方で、WebRTC over QUIC (Quartc)、QUIC as a VPN (QBone)、DNS over QUICといったその他のアプリケーションプロトコルでもQUICを使用する考えを持ってる人もいます。

そこでそういったプロトコルのトランスポートとして使用できるように、QUIC上でロスしたパケットに含まれるデータを再送しないデータ通信を可能にする拡張仕様が提案されています。もちろん通信は暗号化されていますし、Ackにより相手が受信したかどうかは確認することが出います。

MESSAGEフレーム/Datagramフレーム

提案自体は同時期に個別に2つの仕様が出ています。

1つ目の「QUIC Messages」はGoogleのIan Swett氏提案しているMESSAGEフレームを定義し利用するもので、Google QUIC v45ですでに実装されています。

2つ目の「An Unreliable Datagram Extension to QUIC」はApple人らによって提案されているDATAGRAMフレームを定義利用するものです。著者はIETF102において、Ian Swett氏との議論に基づいてDraftを書いたと述べています。

これらはフレーム名を除いて同じもののようです。実際に、Ian Swett氏は共同で作業していく意思を示しています。

DATAGRAMフレーム

DATAGRAMフレームのフレームタイプは、0x1c又は0x1dであり最下位ビットが1の場合はLengthフィールドを持ちます。0の場合はパケットの最後まででデータであることを意味します。

DATAGRAMフレームのフォーマットは次のとおりです
f:id:ASnoKaze:20180922223804p:plain

STREAMフレームの場合はストリームIDによって一つのコネクション上に多重化されますが、DATAGRAMフレームの場合は多重化するのならQUICを利用するアプリケーションの責任によって実施されます。

DATAGRAMフレームのみのパケットにはAckする必要がありますが、ロス回復には使用されないためAckを遅延させてバッチ的に応答すべきです(SHOULD)。DATAGRAMフレームはコネクションレベルのフロー制御を受けます。また、輻輳制御やフロー制御によりブロックされた場合はそのままドロップすることもできます(MAY)

ブラウザからシリアルポートにアクセスするSerial API

blink-devメーリングリストに「Intent to Implement: Serial API」として「Serial API」の実装に着手する旨の投稿がされている。

この「Serial API」はW3CのWICGで議論がされており、ブラウザからシリアルポートにアクセス可能にする。3DプリンタやArdbinoなど、様々なデバイスと接続できるようになる。

パーミッションの要求については、すでに実装されている「Web Bluetooth」「WebUSB API」とおなじになるようだ。

sample

仕様では、Ardinoからデータを読み込む例が示されている

//Request the list of ports from the user
SerialPort.requestPorts().then(ports => {

  //Pick the first matching port
  var serial,
      kind = "Arduino",
      key = "manufacturer",
      //find the Arduinos!
      arduinos = ports.filter(port => port.get(key).search(kind) > -1);

  if (arduinos.length) {
     serial = new SerialPort(arduinos[0].path);
     serial.in.read(readData)
  }

  function readData(){
    while(let data = yield serial.read()) {
      console.log(data);
    }
  }
})
.catch(console.error);

Chrome 71で検討されている iframeへのPermission Delegation

Webサイトがカメラや位置情報をアクセスする際にパーミッションを要求する場合がある。iframeで埋め込んだページでも同じようにパーミッション要求が行える。

Chrome 71で導入が検討されている「Permission Delegation」では、iframeで埋め込まれたページでのパーミッション要求の仕組みがわかりやすくなる。(iframe内のドメインからパーミッション要求されても、普通のユーザにはわかりにくい)

iframe内でパーミッションが必要になった際、top level origin(URLバーに表示されているサイト)がパーミッションを要求し、その権限を移譲する形になる。

その結果各パーミッションはtop level originに紐づくため、ユーザは権限の管理が行いやすくなる。

https://asnokaze.com/pd.html は以下のように、iframeを埋め込む。allow属性でiframe内で許可するパーミッションを指定する

<iframe allow="geolocation;camera;" src="https://permission.site">
iframe内でカメラへのアクセスを要求する

  • Chrome 69では、iframe内のドメイン名(permission.site)が要求していると表示される
  • Chrome 71では、のtop level origin(asnokaze.com)が要求していると表示される
パーミッションの削除

Chrome 71では、権限はtop level originに紐付いているので、権限の削除もtop level originから削除すれば良い