Hatena::ブログ(Diary)

あすのかぜ Twitter

2017-02-24

CSPの仕様に report-sample が追加された

まだ、WIPではあるもののCSPの仕様に "report-sample" と言う機能が追加されました(URL)。


これは、違反したインラインのScriptやStyleの最初の40文字がレポートに追加されます。外部ファイルの場合はレポートされません。昨年から議論がされていましたが、もともとはFirefoxに以前実装されていたscript-sampleプロパティと同等の機能ですが、Styleも対象になります。


これにより、今までレポートは送られてくるもの攻撃なのかそうじゃないのか分からなかったというケースが、多少なりとも少なくなるのではないだろうか。


すでに、Chromeへの実装が進められています(URL)


report-sample

普通のCSPと同様に、HTTPヘッダもしくはmetaタグで report-sampleを指定します。

Content-Security-Policy: script-src 'nonce-abc' 'report-sample'
<meta http-equiv="Content-Security-Policy" content="style-src 'nonce-abc' 'report-sample'">

sample

下記のようなタグが含まれていた場合

<script>alert(1);</script>

このようにレポートにsampleが追加されます

    {
      ...
      "sample": "alert(1);"
    }

2017-02-12

HTTP over マルチキャストQUIC とは

Hypertext Transfer Protocol (HTTP) over multicast QUIC」で、マルチキャストのQUIC上でHTTP通信を行う仕様が提案されている。マルチキャストQUICは単方向通信であり、その上でサーバプッシュを行う感じである。


f:id:ASnoKaze:20170213073224p:image


現状QUICの仕様ではIPマルチキャストの利用は想定されていない(もちろん双方向通信)ため、この仕様ではQUICのトランスポートレイヤ、HTTPレイヤを利用しつつも、IPマルチキャストを利用できるように一部の変更(制限)を加えている。


BBC Researchの方が書かれているので、主に動画像配信での利用を考えているんだと思う。


ざっと仕様を読んだのでかいつまんで特徴を紹介する。


また、QUICの仕様はまだ変わる可能性があり、本仕様はそれに併せて変わる旨注意書きがつけられている。


HTTP over マルチキャストQUIC

セッション

マルチキャストQUICでは、単方向通信になる。そのため、コネクションではなくセッションという用語を使用する(コネクションIDではなく、セッションID)。このセッションに参加者が参加する形になる。


セッションのステートは、個々のエンドポイント間で同期されるわけではないが、参加者(送信者も含む)の有無に関して「Idle」、「Half-established」、「Fully-established」、「Finished」の4つの状態が存在する。


Idle状態から開始され、参加者がいなくなるか、明示的に通信を終了することも出来ます。


エンドポイントは他のセッションにマイグレーションすることも出来ます。


セッションの広告

Alt-Svcを用いて、セッションの広告を行います。マルチキャストQUICは単方向通信であるためCryptoハンドシェイクは使用せず、このAlt-SvcにセッションIDやセッションで使用する暗号スイート、暗号化キーが含まれます。受信者は、自身が暗号スイートに対応してるか判断して、セッションに参加するか決めます。また、この時にトランスポートの鍵が提供されます。


プロトコルの識別子は、hqmを使用します。

   Alt-Svc:
       hqm="[ff3e::1234]:2000"; source-address="2001:db8::1"; quic=1;
       session-id=10; session-idle-timeout=60;
       max-concurrent-resources=10; peak-flow-rate=10000;
       cipher-suite=1301; key=4adf1eab9c2a37fd

source-addressは、Source-specific multicast (SSM) に使用される。


また、Alt-Svcはユニキャストの代替サービスも広報出来ます(後述)。


フローコントロール

QUICトランスポートでは、クレジットベースのフロー制御を行っています。しかし、単方向通信では実現不可能であるため、peak-flow-rateというパラメータを使用します。これは、1秒あたりのビット数で表され、Alt-Svcパラメータで通知されます。

送信者はこのレートを超えないようにしなければなりません。しかし、受信者はそれを超えても切断しなくてもよいです。


パケットロスの回復

マルチキャストQUICは単方向通信であるため、ACKフレームは送信者・受信者双方で使用が禁止されます。同様にSTOP_WAITINGフレームも送信できません。


仕様の中では、損失したデータの回復する方法を2つ示しています。

  • Forward Error Correctionを使用する方法。現在IETFの仕様ではFECはオプショナル仕様で、将来仕様策定される予定になっています。
  • ユニキャストで復元する方法。失われたパケットがFECで回復出来ない場合、もしくは閾値を超えて損失した場合は、ユニキャストを用いてデータを取りに行きます。

HTTP2まわり

マルチキャストQUICはHTTP/2のサーバプッシュに依存します。そのため、受信者はサーバプッシュを受け付けられる必要があります。また、マルチキャストQUICは単方向のため、受信者からHEADERSフレームを送ることはありません、そのためサーバからのPUSH_PROMISEフレームの送信は予約されたストリームを参照します


同様に、単方向通信のためにHPACKの動的テーブルを同期するのは不可能です。そのため、動的テーブルは使用できません。


また、単方向通信であるためもちろん受信者からPriorityを指示することも出来ません。


アプリケーションレイヤセキュリティ

HTTPレイヤでコンテンツの完全性と、相手が本当に正しいこと(主に送信者が正しいこと)を確認する事が推奨されます。


RFC3230 Instance Digests in HTTP」を使用し完全性を、「Signing HTTP Messages

」を用いて真正性を担保することを推奨しています。また、再送攻撃については、Dateヘッダを署名対象に含めるように推奨しているが、それ以上については仕様の範囲外としている。


そのほか機密性が必要があれば別途アプリケーションレイヤでの暗号化をするように推奨しているが、鍵の配送については規定していない。


そのほか

Security and Privacy Considerationsとして、セキュリティ(なりすまし、再送攻撃)・プライバシー(広域盗聴など)、DoS攻撃について手厚く書かれています。

たとえば、送信者のなりすましは可能であるため、上記で述べているようなアプリケーションレイヤの対策が推奨されている。

2017-02-11

Nginxがstale-while-revalidateに対応した

20170214 追記

このコミット(URL)で入った proxy_cache_background_update で、stale-while-revalidateを使わなくてもバックグラウンドキャッシュ更新するように設定できるようになる模様



このコミット(URL)で、Nginxのproxy_cache機能がstale-while-revalidateとstale-if-errorに対応した。次のNginxのバージョンで使えるようになるだろう。


stale-while-revalidate、stale-if-errorとは

stale-while-revalidateとは、以前「Cache-Controlヘッダのstale-while-revalidateとは」で書いたとおり、Cache-Controlヘッダで指定できる拡張機能である(RFC)。


max-ageでキャッシュが切れたあとに、指定した期間の間それぞれ以下の挙動をする


  • stale-while-revalidate: 一旦キャッシュを使用して、その後にファイルが更新されてないか確認しに行く。まずはキャッシュを使うので待ち時間が少ない
  • stale-if-error: ネットワークエラーがあった場合のみ、キャッシュを使用する

以下のように指定する

Cache-Control: max-age=600, stale-while-revalidate=30

max-age(600sec)後に、30secの間はキャッシュを使用した後にファイルが更新されているか確認し、キャッシュの更新をする。


Nginxの場合

この機能はリバースプロキシ・バックエンドサーバ間でも使用できます。


Nginx側の設定に特殊なことは必要ない。デフォルトでこの機能は有効になっている。

    proxy_cache_path /tmp keys_zone=zone:10m;
    server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass http://localhost:8080;
            proxy_cache zone;
...

初回アクセス

f:id:ASnoKaze:20170211223440p:image:w480

初回は普通にリバースプロキシする。バックエンドはHTTPレスポンスにstale-while-revalidateなどを付与する。

Nginxはそのコンテンツをキャッシュする。


stale-while-revalidate、max-age経過後

f:id:ASnoKaze:20170211223711p:image:w480

手元のキャッシュを使用してから、ファイルが更新されてないか確認しに行く。


stale-if-error、max-age経過後

f:id:ASnoKaze:20170211224242p:image:w480

エラーがあった場合のみ手元のキャッシュを使用する。そうでなければいつもどおりに処理する


それぞれ動作確認したところ、上記のように動作していたが。デモが非常にわかりにくいので割愛するorz