CookieのSameSite属性にFirstPartyLaxを追加する提案仕様

2020/11/02 追記
First-Party Sets自体はChromeへの実装が進められる一方、FirstPartyLaxについては廃止されたようです


Cookieのセキュリティ改善を推し進めているGoogleのMike West氏から「First-Party Sets and SameSite Cookies」という提案仕様がIETFで提出されています。

この提案仕様では、CookieのSameSite属性に下記の2つを指定できるようにします。

  • FirstPartyLax
  • FirstPartyStrict

これにより、Cookie送信先をFirst-Partyに緩和することが出来ます。

既存のDomain属性では一方的に共有先に追加していましたが、後述のFirst-Partyはお互いのドメインがFirst-Partyとして認識しあってる点が異なっています。

これらの説明をする前にドメインを超えてFirst Partyを指定できる「First-Party Sets」という仕様を紹介します。

First-Party Sets

First-Party Sets」は同じくMike West氏が提出している仕様ですが、こちらはW3CのWICGで議論されています。

例えば、Webでは、全く異なるドメインが同一主体によって運営されているものがあります。

こういった、ドメインが "First Party" であるというのを分かるようにするのがFirst-Party Setsです。この仕様では、あくまで"First Party"が分かるようにするだけで、既存のWebの仕組みや機能を変更することは有りません。

またFirst-Party Setsの仕様では、無関係なサイト間でのログインや、無関係なサイト間でのターゲティング広告の効果測定は目的に含まれていません。

First-Partyの宣言の仕方

下記ドメインがFirst-Partyであることを宣言する例を示します。

f:id:ASnoKaze:20200621012935p:plain

このとき、Well-Known URLを使用します。パスは「.well-known/first-party-set」で、ここにJSONを配置します。

https://a.example/.well-known/first-party-set

{
  "owner": "a.example",
  "version": 1,
  "members": ["b.example", "c.example"],
  "assertions": { 
    "chrome-fps-v1" : "<base64 contents...>",
    "firefox-fps-v1" : "<base64 contents...>",
    "safari-fps-v1": "<base64 contents...>"
  }
}

https://b.example/.well-known/first-party-set

{ "owner": "a.example" }

お互いのドメインでお互いがFirst-Partyであることを示します。assertionsではUAのポリシーをマッチしていることを示す署名がつけられます ( Certificate-Transparencyのような、別途署名機関が想定されている)。

また、b.exampleはアクセスしてきたクライアントに「Sec-First-Party-Set」HTTPレスポンスヘッダを返すことで、ownerを示すことが出来ます。

  Sec-First-Party-Set: owner="a.example", minVersion=1

このレスポンスヘッダを受け取ったクライアントはそれぞれのjsonファイルを取得し、マッチしていれば両ドメインをFirst-Partyとして扱います

FirstPartyLax、FirstPartyStrict

First-Party Sets and SameSite Cookies」で定義されるSameSite属性のFirstPartyLaxとFirstPartyStrictは、CookieをFirstPartyには送信するように指定できるようになります。

Set-Cookie: test=value; SameSite=FirstPartyLax

Lax, Strictの意味合いは元のSameSite属性と同様、LaxではトップレベルのナビゲーションでもCookieが送信されます。

NginxのHTTP/3を試す (2020年6月)

NginxのHTTP/3対応版が公開されました。実際に動かしていきます。(なお、現在サポートしているのはHTTP/3 draft 27版です)
www.nginx.com

基本的には 「README」 の通りやるだけです。

HTTP/3の詳細についてはガッツリ解説を書いたので、ご参考にしていただければ
asnokaze.hatenablog.com

準備

(ちなみに環境は Ubuntu18.04 Bionicです)

パッケージのインストールと、依存するboringsslのビルドをしておきます
https://boringssl.googlesource.com/boringssl/+/HEAD/BUILDING.md

$ sudo apt install mercurial ninja-build
$ git clone https://boringssl.googlesource.com/boringssl
$ cd ./boring/
$ mkdir build
$ cd build
$ cmake -GNinja ..
$ ninja
$ ../

nginxのビルド

ビルドします

    $ hg clone -b quic https://hg.nginx.org/nginx-quic
    $ cd nginx-quic
    $ ./auto/configure --with-debug --with-http_v3_module       \
                       --with-cc-opt="-I../boringssl/include"   \
                       --with-ld-opt="-L../boringssl/build/ssl  \
                                      -L../boringssl/build/crypto"
   $ make
   $ #sudo make install ##面倒くなければ install してしまっても良い

設定と起動

/usr/local/nginx/conf/nginx.conf にこんな感じで入れます
listenにhttp3とreuseportを指定します。また、HTTP3対応をクライアントに通知するために、Alt-Svcヘッダを送ります。

    http {
        server {
            # for better compatibility it's recommended
            # to use the same port for quic and https
            listen 443 http3 reuseport;
            listen 443 ssl;

            ssl_certificate     certs/example.com.crt;
            ssl_certificate_key certs/example.com.key;
            ssl_protocols       TLSv1.3;

            location / {
                # required for browsers to direct them into quic port
                add_header Alt-Svc 'h3-27=":443"; ma=60';
            }
        }
    }

接続

公式曰く、Firefox 75以上、Chrome 83以上で動くらしいので

今回は試しにChrome Canaryでhttp3 draft27を有効にして起動します。

 $ ./chrome --enable-quic --quic-version=h3-27 

chromeの起動パスがわからない場合は、chromeを起動して、chrome://version/ とURLバーに打ち込むと、起動パスがわかります。それに、上記オプションを追加します。

(ブラウザの進捗は早いので、将来h3-27の代わりに仕様上最新のh3-29を使用できる可能性もあります)

動作確認

接続するとChromeデベロッパーツールからh3-27で通信していることが確認できました

https://asnokaze.com/
f:id:ASnoKaze:20200611133029p:plain

HTTP/3の解説を書いた (2020/06/01)

@flano_yukiがHTTP/3について書きました。(無料です。

2020年6月時点の内容となっています。概ねQUICやHTTP/3の大枠は固まっており、2021年の内容と照らし合わせても、大きな変更はありません。PDFを下に貼ってあります。


, (宣伝) また、2021年6月にアップデートも含め、WEB+DB PRESS Vol.123に記事を書かせていただいております(有料) gihyo.jp

http3-note

https://github.com/flano-yuki/http3-note にPDFを置きました 公開形式は、そのうちなんとかするかも

内容

  • 1. はじめに(HTTP/3と概要)
    • 1.1 はじめのはじめに
    • 1.2 HTTPのセマンティクスとバージョンの話
    • 1.3 HTTP/3の概要
    • 1.4 HTTP/3 と呼ばれるまでの道のり
    • 1.4.1 Google QUICの実験
    • 1.4.2 HTTP over QUIC、標準化の開始
    • 1.4.3 HTTP/3への改称
    • 1.5 標準化動向を追うために
  • 2 QUICについて
    • 2.1 QUIC、はじめに
    • 2.2 QUICの概要
    • 2.3 QUICコネクションとQUICパケットの基礎
    • 2.4 フレームについて
    • 2.5 ストリームについて
    • 2.6 コネクションの確立
    • 2.7 コネクションのクローズ
    • (TODO) 2.8 負荷分散・トラフィックのオペレーション
    • 2.9 その他 (FEC, Multipath, LB)
    • 2.9.1 Forward Error Correction(FEC)
    • 2.9.2 MP-QUIC
    • (TODO) 2.9.3 QUIC-LB
    • 2.10 応用例
    • TODO
  • 3 HTTP/3について
    • 3.1 HTTP/3のはじめに
    • 3.2 HTTP/3対応の通知とコネクションの開始
    • 3.3 QUICストリームの利用
    • 3.4 HTTP/3 フレーム
    • 3.5 HTTPメッセージの送受信
    • 3.5.1 HTTPメッセージを送るまで
    • 3.5.2 HTTPメッセージの送受信
    • 3.5.3 CONNECTメソッド
    • 3.6 ヘッダ圧縮 QPACK
    • 3.6.1 ハフマン符号
    • 3.6.2 静的テーブル、動的テーブル
    • 3.6.3 ヘッダ表現
    • 3.7 サーバプッシュ
    • 3.8 優先度制御
    • 3.9 コネクションの終了
    • 3.10 拡張性
  • 4 HTTP/3 拡張仕様と応用
    • 4.1 HTTP/3 拡張仕様と応用、はじめに
    • 4.2 HTTP/2の拡張フレーム
    • 4.3 DATAGRAMフレーム
    • 4.4 WebTransport
    • 4.4.1 背景と概要
    • 4.4.2 WebTransport over QUIC
    • (TODO) 4.3.3 WebTransport over HTTP/3
    • (TODO) 4.5 MASQUE
    • (TODO) 4.6 RIPT
    • (TODO) 4.7 HTTP over multicast QUIC

CONNECT-UDP HTTPメソッドの仕様 (RFC 9298)

2022年8月追記: この記事は古くなっています。仕様自体は RFC 9298として標準化さました。
RFC 9298: Proxying UDP in HTTP


2022年7月追記: この記事は古くなっています。現在の最新仕様では、拡張CONNECTメソッドを使うことになってます
asnokaze.hatenablog.com


MASQUEプロトコルの標準化の流れで、GoogleのDavid Schinazi氏から「The CONNECT-UDP HTTP Method」という提案仕様が提出されている。

MASQUEは、HTTP/3でプロキシサーバに接続した後にそのコネクションをトンネルとして使用し、VPNのように任意のデータをやりとりするプロトコルです。通信を観測する第三者からは、ただのHTTP通信を行っているようにしか見えません。

このMASQUEは現在IETFでワーキンググループを作成している最中であり、まだまだ議論が始まったばかりの仕様になります。

CONNECT-UDP HTTPメソッド

CONNECT-UDP HTTPメソッドは、HTTPの接続をUDPでプロキシするのに使用されるメソッドです。

クライアントは以下のようなリクエストを送信します (HTTP/2以降は疑似ヘッダで表現される)

:method CONNECT-UDP
:authority server.example.com:443
Datagram-Flow-Id 2

(Datagram-Flow-Idヘッダについては後述する)

このリクエストを受け取ったプロキシは接続先のサーバに対してUDPソケットを開き、クライアントに200番台のレスポンスを返す。それ以降プロキシはう受け取ったデータをUDPでターゲットサーバに転送します

なお、HTTP/3を使用している場合は「HTTP/3 DATAGRAM Frame」を使用できます。HTTP通信は同一ストリーム上ではデータは送った順番通りに処理される必要があります。HTTP/3 DATAGRAM Frameは、パケットが欠損したりパケットの順番が入れ替わっても届いた順番で処理していいデータを運ぶ用のフレームです。

以前解説した、QUICレイヤのDATAGRAM Frameとは異なり、HTTP/3レイヤで送信されるフレームです。
asnokaze.hatenablog.com

フォーマットも微妙に異なっており、Flow Identifierという識別子を持ちます。CONNECT-UDPリクエストを送信する際に、Datagram-Flow-Idヘッダを送信しますが、利用するHTTP/3 DATAGRAM FrameのFlow Identifierと同じ値を入れて、紐付けを行います。

これによりHead-of-line blockingを防ぐことができます。


そのた

(間違ってる箇所があったらすみません)

サポートしてないwell-known URIs に対するステータスコードを確認する提案仕様

Webの仕様ではWell-know URIとして特別なPathを指定するものがあります。

例えば、現在議論が進められている「A Well-Known URL for Changing Passwords」では .well-known/change-password をパスワード変更用のページにリダイレクトする特別なパスとして定義しています。

実際にtwitterFacebookではすでに対応しています

サポートしていないwell-known URIs に対するリクエストには200番台以外のステータスコードを返さなければなりません。しかし、実際にはリソースが存在しないのに200番台のレスポンスを返すサーバがいるようです。


そのために 200番台を絶対に返さない well-known URIs を定義し、そういったサーバを検出できるようにするのが「Detecting the reliability of HTTP status codes」です

Detecting the reliability of HTTP status codes

後述の通り、「Detecting the reliability of HTTP status codes」では必ず200番台のレスポンスを返さないwell-known URIsを定義します。

具体的には下記のとおりです

.well-known/resource-that-should-not-exist-whose-status-code-should-not-be-200

このパスに対してリクエストを送ることで、サーバが返すステータスコードの信頼性を確認できます。

これらの仕様は、W3CのWICGで管理されているドキュメントです。これから、まだまだ変更される可能性があります。

Compact TLS 1.3の提案仕様

TLS1.3の仕様を書いたEric Rescorla氏らより「Compact TLS 1.3」という提案仕様が提案されており、すでにWG Draftとなっています。

このCompact TLS (cTLS)は、よりコンパクトなTLSを定義しデータの通信量を削減しています(リソースなどが制限されたデバイスでも利用できるようにというモチベーションもあります)。TLS1.3自体とisomorphic(同型)でありやり取りされるメッセージの意味自体は同じですがメッセージのフォーマットは異なっており、cTLSとTLS1.3自体と相互通信はできません。

しかし、cTLS, TLS1.3両方に対応することはできるので、将来的にそういうサーバが出てくれば問題なく通信できるようになりそうです。

アプローチ

主なアプローチは

  • TLS1.3の冗長なフィールド、廃止されたフィールドを取り除きます (TLS1.2との互換性の都合形だけ入ってたフィールドなど)
  • 可変長整数を使い、整数値のフィールドを削減します
  • 不要な値の省略
  • デフォルト値を定義可能にするテンプレート (profile)

結果として、下記の通りデータ転送量を削減できます。
f:id:ASnoKaze:20200430000115p:plain

いくつか説明していきます

冗長, 不要なフィールドの廃止

TLS1.2との互換性のために確保されてた領域をクリーンアップしています

Record Layer

         struct {
             ContentType type;
             opaque fragment[TLSPlaintext.length];
         } TLSPlaintext;

ClientHello

         struct {
             Random random;
             CipherSuite cipher_suites<1..V>;
             Extension extensions<1..V>;
         } ClientHello;

ServerHello

         struct {
             Random random;
             CipherSuite cipher_suite;
             Extension extensions<1..V>;
         } ServerHello;

テンプレート(Profile)

ProfileはJSON形式で記述され、暗号関連のパラメータ・TLS拡張・証明書などが事前定義されており。ハンドシェイク時はこれらの値を使う場合は省略されます。また、randomの長さなども短く設定することもできます。

このProfileはクライアントとサーバで事前に共有されている必要があります。(標準Profileを定義するかや、ハンドシェイク中に使用しているProfileを相手に通知する方法などは現在議論中です。)

Profile例

   {
     "version": 772,
     "cipherSuite": "TLS_AES_128_CCM_8_SHA256",
     "dhGroup": "X25519",
     "signatureAlgorithm": "ECDSA_P256_SHA256",
     "randomSize": 8,
     "finishedSize": 8,
     "clientHelloExtensions": {
       "server_name": "000e00000b6578616d706c652e636f6d",
     },
     "certificateRequestExtensions": {
       "signature_algorithms": "00020403"
     },
     "knownCertificates": {
       "61": "3082...",
       "62": "3082..."
     }
   }

Cookieのセキュリティを改善する Scheming Cookiesについて

Chromeが「Cookie の SameSite=Lax をデフォルト化」を進めたことは記憶に新しい。
asnokaze.hatenablog.com

Cookieの改善は引き続き議論されており、Cookieの扱いでスキーム(http://やhttps://)を考慮に入れることが検討されている。

Incrementally Better Cookies

Cookieのセキュリティ改善を精力的に行っているGoogleのMike West氏は、Secure属性の利用が30%、"__Secure-"プレフィックスの利用が0.18%ほどにとどまっていると述べており(リンク)、セキュリティ改善のためにCookieの扱いを段階的に変更していくことを考えている。

同氏がIETFに提出している「Incrementally Better Cookies」では、Cookieを次のように段階的に改善することを提案している。

  1. 「SameSite = Lax」をデフォルトにする
  2. 「SameSite = None」にするにはHTTPSから配信される必要がある
  3. same-siteはスキームを考慮にいれるようにする (Schemeful Same-Site)
  4. Cookieはスキームを尊重する必要がある (Scheming Cookies)
  5. 非セキュアなスキームのCookieは、セッションの最後に削除する
  6. セッションの定義を厳しくする

すでに、最初の2つは実施されている。これに続く、Schemeful Same-Siteや、Scheming Cookiesなどについて簡単に書いていく。

ただし、同氏がBlink-devで「Reducing web compatibility risk.」述べているように、昨今の状況を鑑みてWebの互換性を壊しうる変更はすぐにブラウザには入らないだろう。

Schemeful Same-Site

Same-Site の判定は、eTLD+1である。

例えば下記はsame-siteである。

また、https:// と http:// は考慮に入らないが、Schemeful Same-Siteではスキームを考慮にいれるという変更である。

Same-site Cookieの場合は、https://example.comでセットされたcookieは.http://www.example.com へのリクエストでは付加されません。逆もそうなります。

Scheming Cookies

(same-site属性なしでも) スキームを考慮するようにします。Scheme-Bound Cookies とも呼ばれます。

ブラウザがCookieを保存する際に、スキーム情報も保存します。ブラウザは今までの条件に加えスキームも一致している場合のみ、Cookieを送信します。

非セキュアなCookieの失効

次の段階として、非セキュアなスキームでセットされたCookieをセッション終了時に失効することも検討されている。