Cookieの新しい属性、SameParty属性について

ChromeCookieのSameParty属性の開発が進められている (コミット)。

現在のところ「SameParty cookie attribute explainer」に説明が書かれている。

今回は、CookieのSameParty属性について簡単にメモしていく。

背景

ラッキング対策、プライバシーの観点でサードパーティクッキーは制限する方向に進んでいる。その制限をSame Partyの場合に緩和する仕組みを提供するのがSameParty属性の話である。

例えば、同一主体により運営されているドメインの異なるサイト (例えば、google.co.jp, google.co.uk) 間においては、いわゆる(cross-site contextsで送られる)サードパーティクッキーを許可しようという話です。

もともとは、First-Party Setsを活用しSameSite属性にFirstPartyLax/FirstPartyStrictという2つの値を新しく定義していた。しかし、SameSite属性自体はCSRFなどを防ぐ、セキュリティの目的で導入されたものでした。

このSame Partyでクッキーを取り扱うことはプライバシーの観点の話なので、別途SameParty属性が定義された形のようだ。

First-Party Sets

SameParty属性のまえに、まずFirst-Party Setsの説明をする。

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

こういった、ドメインが "First Party" であるというのを分かるようにするのが「First-Party Sets」です。

ドメインがお互いに一つのpartyであることを宣言しあう形となる。
f:id:ASnoKaze:20200621012935p:plain

詳細については、以前記事を参照
asnokaze.hatenablog.com

CookieのSameParty属性

取り扱い方は、その他の属性と同様である。Set-Cookieやdocument.cookieを介して設定できる。

Set-Cookie: cookie=tasty; SameSite=Lax; Secure; SameParty

さて、次にどのようなときにクッキーが送られ、どのようなときにクッキーが送られないのか見ていく。サードパーティクッキーの制限を緩和する位置づけと見ると分かりやすいかと思う。

SameParty cookie attribute explainer」にかかれている具体例を拝借する。

f:id:ASnoKaze:20201214012717p:plain
(画像が見にくいので、オリジナルを参照: https://github.com/cfredric/sameparty/blob/main/images/same_party_table.png)

owner.exampleと下記のドメインがFirst-Party Setsを用いた同一partyであるとする

  • member1.example
  • member2.example

このとき

  • 同一party間でリソースが埋め込まれている場合はクッキーが飛ぶ。
  • other.example のような同一party外のページに埋め込まれた場合はクッキーが飛ばない

という挙動となる

RFC8879 TLS Certificate Compression について

RFC8879 TLS Certificate Compression」が昨日公開されました。

これは、TLSハンドシェイク中に送信されるサーバ証明書を圧縮する仕組みを定義しています。

これによって、ハンドシェイクの通信量を削減できます。ハンドシェイク中は、パケットロスが起こっても後続のパケットは多くないのでロスリカバリとしては不利な状況です。ハンドシェイクに必要なパケット数が減るというのはメリットが有るのかなと思います。

また、QUIC(HTTP/3)においてもTLSハンドシェイクを利用していますが、QUICではClient Address Validationが終わるまで一度に送れる通信量に制限があるため、通信量が減ることはそういった意味でもメリットがあります。

この点については、FastlyのPatrick McManus氏がブログを書かれています。実際に送信されるパケット数がどうなるかといった統計データもあり興味深いです。
www.fastly.com

なお、TLS1.2以下ではこの仕組みは使えないことになっています。

TLS Certificate Compression

TLS Certificate Compressionは以下のような流れで行われます

f:id:ASnoKaze:20201203235800p:plain

  • クライアントはClientHelloにおいて、compress_certificate拡張で圧縮アルゴリズムを指定します
  • サーバは暗号化されたCompressed Certificateメッセージで圧縮された証明書を送信します

仕様内で定義されている圧縮アルゴリズムは次の3つで

  • zlib
  • zstd
  • brotli

試してみる

Google Chrome及び、Facebookがすでにこの機能に対応しているので試してみます。なお、Compressed Certificateメッセージは圧縮されているので復号してやる必要があります。

f:id:ASnoKaze:20201204000404p:plain

Wiresharkで通信を見てみると、下記の通りサイズが削減されている事がわかります

  • 元のサイズ: 2798バイト
  • 圧縮サイズ: 1968バイト

Chromeでは、QUICでの証明書圧縮は行われてなかったんですがちょうど本日修正コミットが入りましたね。
https://chromium.googlesource.com/chromium/src/+/5c5f62bfa818d30eb9c09e2f513f039c7ed9ef15

Prometheusが利用するOpenMetricsの仕様がIETFに提出された

OpenMetricsという提案仕様が、11月25日にIETFに提出されました。仕様は「OpenMetrics, a cloud-native, highly scalable metrics protocol」こちらから閲覧できます。

これはIETFでの標準化の一歩目であり最終的にRFCとなるかはまだまだわかりません。

ただ標準化の観点で興味深いと思っています。ですので今回は、仕様の中身には触れずラフに書いていこうかと思います。

はじめに

自分自身は、監視やモニタリングについて専門ではないものの、多くのインフラ/クラウド環境のモニタリングでPrometheusが使用されているのは知っています。

そのPrometheusが使っている、メトリクス収集のプロトコル/フォーマットであるOpenMetricsがIETFに持ち込まれたという点は、標準化側の視点で興味深く見ております。

もちろん、SPDYやQUICといったように特定企業が開発/試験を行った後にIETFに持ち込まれ標準化されると言ったことは普通にあることです。IETFが掲げる「We believe in rough consensus and running code」という考え方と照らし合わせても、実際に動いて使われているものがあるというは大事です。

一方で、rough consensus として、これがIETFで取り組むべきであるか?などWGでコンセンサスが得られる必要があります。まずは、IETFという場でどれほど興味を持ってもらえるかという点も気になるところです。

著者はもともと今年3月に行われる予定だったIETF107でその議論を行うつもりがあったようですが、タイミング的にも叶わなかったようです。

投稿者のことば

提案仕様の第一著者であるGrafana LabsのRichard Hartmann氏は、OPSA ワーキンググループに下記のメールを投稿しています。

「[https://mailarchive.ietf.org/arch/msg/opsawg/KpIY3phzcBzPnypy55uwnCoLkBU/:title=[OPSAWG] Introducing draft-richih-opsawg-openmetrics]」

このメールではOpenMetricsが2014年ごろから、多くのベンダー, プロジェクトで広く使われていることを説明しています。

さらに、Open Standardsを強く信じており、IETFが標準化するのに最も適切な場所だとも述べています。

いくつかの資料も合わせて読むと、彼らが当初からIETFでの標準化を望んでいたこともうかがい知ることができます。

しかし今のところこのメールに対するコメントはまだついてないようです。

今後

この提案仕様に関する議論はOPSA WGのメーリングリストで行われていくでしょう。

メーリングリストでの議論でどの程度コンセンサスが得られるか分からないですが、個人的には大きな動きがあるとするならばIETF本会合が開催される来年3月なのかなと思っております。うまく進めば、そこでBoFなりが開催されるかもしれません

まだ提案の標準化が進むのか、どのようになるかはわかりませんが、標準化をウォッチしてる人間としては気になるので引き続き追っていければなと思います。

よし、仕様読むぞ

CDNのキャッシュを制御する CDN-Cache-Control ヘッダ

CDNのキャッシュを制御する「CDN-Cache-Control」を新しく定義する提案仕様「The CDN-Cache-Control HTTP Response Header Field」が出ているので、簡単に紹介する。

2021/10/16 追記: 最新仕様では「Targeted HTTP Response Header Fields for Cache Control」と呼ばれる

はじめに

HTTPではキャッシュを制御するのにCache-Controlヘッダを使用しますが、クライアントとは別にCDNに対して個別にキャッシュの制御を行いたい場合もあります。

その用途のために使用する「CDN-Cache-Control」を新しく定義しようというのが「The CDN-Cache-Control HTTP Response Header Field」です。

この仕様は、Akamai, Fastly, Cludflareに所属する三人が共著で提出している点も興味深いところです。

CDN-Cache-Control

CDN-Cache-ControlヘッダのディレクティブはCache-Controlヘッダと同様です。

CDN-Cache-Controlがある場合は、Cache-control及びExpiresヘッダは無視されます。(CDN-Cache-Controlがなければ、Cache-controlが使用されます。)

例えば下記のようなレスポンスヘッダは

Cache-Control: max-age=60, s-maxage=120
CDN-Cache-Control: max-age=600
  • CDNでは600秒 レスポンスはfresh となる
  • CDN以外ではshared cacheは120秒、その他は60秒 fresh となる

例えばCDNではキャッシュを許可し、それ以外では保存させないという事もできます。

Cache-Control: no-store
CDN-Cache-Control: max-age=600

その他

提案仕様では、いくつかのFAQが書かれています。詳しくは原文を見てもらうとして、軽く紹介

なぜSurrogate-Controlを使わないのですか?

Surrogate-Controlヘッダーの実装はいくつかあるが、一貫性がないため、相互運用性の観点で新しいヘッダとして定義した

なぜCache-Controlヘッダに組み込まないのですか?

冗長性が減るが、相互運用上の観点で複雑性がますため

これはCDN専用ですか?

そうです。CDNゲートウェイキャッシュは区別すべきです。

複数CDNをつかってるんですが

複数CDN利用してる際にそれぞれ違うCASH制御したい場合があるかもしれません。

CDNは独自のヘッダ名を使うことが検討できます。

例えばFoo CDNでは「Foo-CDN-Cache-Control」を使うと言った風に。

POSTリクエストを冪等処理可能にするIdempotency-Keyヘッダの提案仕様

はじめに

HTTPリクエストには冪等なものと非冪等なものがあります。

仕様上、GETやOPTIONSは冪等であり、同じリクエストであれば何度行っても問題ありません。そのため通信上エラーが起こっても自動的にリトライすることが出来ます。

一方で、POSTリクエストは冪等ではありません。同じリクエストでも複数回行うと、結果が変わってしまいます。投稿や課金APIであれば2重に処理されてしまいます。

POSTリクエスト中にタイムアウトが発生した時に、サーバに処理される前にタイムアウトしたのか、サーバが処理したあとにレスポンスを返そうとしたところでタイムアウトしたのかクライアントは区別できません。そのため、POSTリクエストを一概にリトライすることは出来ません。

そこで、リトライにより複数回同じPOSTリクエストを受け取っても、同じものと識別できるように識別子をHTTPリクエストに付加できるようにする提案が行われています。

Idempotency-Keyヘッダ

PayPalのJayadeba Jena氏らに提出された「The Idempotency HTTP Header Field」では、冪等処理用の識別子としてIdempotency-Keyヘッダを定義しています。

   Idempotency-Key: "8e03978e-40d5-43e8-bc93-6894a57f9324"

クライアントはランダムな値(UUID)などを、ヘッダ値をセットします。

サーバはこのIdempotency-Keyを元に複数回同じリクエストを受け取っても冪等処理を行います。2回目以降のリクエストに対しては、初回と同じレスポンスを返します。

サーバは一定期間後に受け取ったIdempotency-Keyの値を忘却しても問題ありません。

Idea

この提案のアイデアは様々なところで似たような事が行われています。まさに、Idempotency-Keyという名前を使ってる他、リクエストIDという名前のものからあります。

参考までに、提案仕様の中で紹介されています

  • StripeのIdempotency-Keyヘッダ
  • PayPalPayPal-Request-Idヘッダ
  • Google Standard Payments APIのrequestId

などなど。。。

おまけ

余談ですが

HTTPのリトライ/リプレイに関しては、用語及び各実装の状況に整理している Mnot先生のドキュメントが学びになります

「Retrying HTTP Requests」

ホスト名の異なるTLS session resumptionについて

TLS1.3でホスト名が異なるTLS session resumptionを支援する拡張仕様が出ているので紹介する。

TLS1.3とセッション再開(session resumption)

RFC 8446 TLS 1.3 では、セッション再開(session resumption)という方法が定義されています。このsession resumptionを使うことで、2回目からのセッション確立を効率よく行えます。

このとき、TLS1.3からは異なるSNIを指定してのsession resumptionが出来るようになっています。

例えば、証明書が*.example.comの時に、a.example.comで確立したセッションを元に、b.example.comに対してsession resumptionを行えます。

しかし、一般に証明書がカバーしているホスト名だとしてもセッション再開のための状態がサーバ間で共有されているとは限りません。うまく行かないのにクライアントはセッション再開を試みるのは、セッションチケットを無駄にしてしまいます。

そこで、サーバから「この証明書がカバーするホスト名では、SNIの異なるsession resumptionをして良い」と明示する拡張仕様が検討されています。

TLS Resumption across Server Names

TLS Resumption across Server Names」は、GoogleのVictor Vasiliev氏によって提案されている仕様です。

この仕様では、NewSessionTicketメッセージの拡張としてresumption_across_namesを定義しています。

このresumption_across_names拡張をクライアントに通知することで、「この証明書がカバーするホスト名では、SNIの異なるsession resumptionをして良い」ということを示します。

パフォーマンス

Victor Vasiliev氏らの提案とは関係なく、2019年にハンブルク大学のErik Sy氏らによって「Enhanced Performance for the encrypted Web through TLS Resumption across Hostnames(pdf)」という論文が公開されています。

この論文では、有名サイト閲覧時、異なるホスト名でセッション再開した場合の効率性を調査しています。

調査によると、Web上のサイトを取得する際に、行われるTLSハンドシェイクのうち約6割ほどがホスト名の異なるセッション再開が行えるとのことです。

これにより、セッション確立にさかれる時間を最大30%早く出来るとのことです。

NTPの次期バージョンv5の標準化が始まる

NTPの次期バージョンとなるv5のドラフト(草案)が出たので目を通す。

はじめに

2010年にRFC 5905としてNTPv4が標準化されています。それから10年たち、IETFのNTP WGではNTPv4の問題点を整理ながら、NTPv5をどのようにするか議論してきました。

そして11月23日にRed HatのMiroslav Lichvar氏から最初の草案となる「Network Time Protocol Version 5」が提出されました。

下記の4つのタイムスタンプを元に時刻同期を行うというところは大きく変わってはいません

  • クライアントがパケットを送った時間
  • サーバがパケットを受信した時間
  • サーバがパケットを送信した時間
  • クライアントがパケットを受信した時間

一方細かい改善で高精度化や、うるう秒対策で使われるleap smearの対応などがあります。そういったNTPv4との違いについてかんたんに眺めていきます。

ただし、最初期案のため、ここから変更が入ると思われます。

NTPv5

Clientモード/Serverモードのみサポート

NTPv4はAssociation Modeとして6つが定義されていました

  • Symmetric Active
  • Symmetric Passive
  • Client
  • Server
  • Broadcast Server
  • Broadcast Client

NTPv5では、ClientとServerのみのサポートになりました

UTC以外のtimescaleに対応 (leap smearもあるよ!)

NTPではUTCで時刻を指定していましたが、v5では下記の4つが選択できるようになりました

  • UTC
  • TAI
  • UT1
  • Leap-smeared UTC

特に、昨今よくつかわれているLeap-smeared(うるう秒を1日かけて調整する方式)を指定できるようになっています。こうすることで実装同士がLeap-smearedされていることを認識できるようになりますね。

アルゴリズムの記述を削除

NTPv4の仕様は「Network Time Protocol Version 4: Protocol and Algorithms Specification」でしたが、v5では「Network Time Protocol Version 5」となっています。

この通り、サーバと同期するのに適切化フィルタするアルゴリズム(Clock Filter Algorithm)らへんの記述はなくなりました

NTPv4では、ユーザランドでパケット送信処理を行ったあとに、低レイヤ(OS/ハードウェア)から得られるより正確な時刻情報を同期に使えるようにする「NTP Interleaved Modes」という仕様が存在しています。

これをNTPv5では、これを行うためのフラグ及びCookieを持ちます

Reference IDsの改善

NTPサーバは上位のサーバを示すために、32bitReference IDフィールドに上位サーバのIPアドレスを格納します。

この値はループ防止に使用されていましたが、アドレス変換などがあると適切に扱えていませんでした。

そのためReference IDsも改善される予定です

32-bit 秒フィールドの高精度化

NTPには、Root Delayといった32-bitで秒を示すフィールドがあります。

NTPv4では16bitを整数部・16bitを小数部として秒を表現していましたが、この場合15ミリ秒の精度になってしまいます。

NTPv5では4bitを整数部・28bitを小数部として秒を表現することで、約3.7ナノ秒の精度で表現可能となっています。

拡張

MACなどが拡張フィールドとなっていたりしている。現在NTPv5で定義されている拡張フィールドは下記の通り

  • Padding Extension Field
  • MAC Extension Field
  • Reference IDs Extension Field
  • Correction Extension Field
  • Reference timestamp
  • Monotonic Timestamp Extension Field

また、拡張フィールドは任意長になった (NTPv4だと4オクテットの倍数)

パケットフォーマット

f:id:ASnoKaze:20201115231335p:plain

(拡張フィールドは任意長かつ、任意回繰り返し)

eraもパケットに入るため、タイムスタンプ32bit整数部で表現できる136年✕256(8bit)で約35000年の範囲を表すことができます。

おわりに

まだたたき台が出てきたところで、これからどんどん変わると思われるので注意。

ひとまず、来週あるIETF109でどのような議論が行われるか注目していきたい。