Webサイトのバグの報告先を示す contributing.txt

Webサイトのバグを見つけたとしても、その報告先を知る統一的な方法は現状ありません。

たとえば、脆弱性についてはsecurity.txt があります。https://www.facebook.com/security.txt などで使われています。
asnokaze.hatenablog.com

同様の仕組みで、contributing.txt という形式でバグの報告先を示せるようにする仕組みが提案されています。提案仕様は「a simple way to provide informations for contributors」としてIETFに提出されています。

contributing.txtをWebページの最上位階層に配置します (例: https://example.com/contributing.txt )

そのファイルは次の情報を含めることが出来ます。

Admin: Valentin Binotto
Bugs: bugs@vauly.net
Open Source: github.com/valentinbino
License: Creative Commons Attribution 4.0 Int. Public License
Guidelines: github.com/valentinbinotto/v434/guidelines.txt
# Valentin Binotto
# Hello, world!
  • Admin: Webサイトの管理者
  • Bugs: バグレポートを出せるメールアドレスまたはURL
  • Open Source: GithubやGitlabなどより議論するのに適切なURL
  • License: ウェブサイトのコンテンツに適応されるライセンス
  • Guidelines: このWebサイトにコントリビューションするためのガイドラインのURL
  • #~~ : コメント

ChromeのCache Transparencyに関するメモ

Chromeではキャッシュの効率改善を目的とした「Cache Transparency」という仕組みが検討されているようです。

これは、「Double-keyed HTTP cache」によってキャッシュヒット率低下を緩和します

まだまだ実験を行っている段階ですが、簡単にメモとして残しておく

背景: Double-keyed HTTP cache

Double-keyed HTTP cacheは、ユーザのプライバシーを保護するために、HTTPのキャッシュをサイトごとに分離する仕組みです。

簡単な例で見ていきましょう

この時、https://cdn.exampleから読み込んだリソースをキャッシュするわけでが、同一のリソースであったとしてもa.example用とb.example用でキャッシュ領域を分けます。

こうしておかないと、a.example側はアクセスしたユーザがb.exampleにすでにアクセスしたことがあるのか、リソースの読み込み速度から類推することができしていまいます。

この時、キャッシュのキーが 『読み込んだサイト(URLバーに表示されてるURL)』+『読み込んだリソースのURL』と2つのキーになることからDouble-keyed HTTP cacheと呼ばれています。

Chromeの分析では、Double-keyed HTTP cacheによりキャッシュのヒットミスが3%増えたという分析がなされています。

Cache Transparency

Cache Transparencyは、Blink-devメーリングリストの下記のスレッドで議論されています
groups.google.com

主な目的は、Double-keyed HTTP cache導入によって上がったキャッシュのヒットミス率の低減があげられています。

その方法としては、一般に広く利用されているリソースであれば、Single-Keyキャッシュで扱ってもユーザのプライバシーには影響しないという仮説に基づいています。

"一般に広く利用されているリソース" は、Google独自の方法(Chromeのテレメトリ, クローラー)で調査され、Pervasive Payloads listとしてリスト化されます。Pervasive Payloads listには、リソースのURLとペイロードハッシュ値が含まれ、それに一致するリソースはSingle-Keyキャッシュとして保存されます。

まだ事前の効果測定を行う段階で、実験として以下の条件を満たすリソースを対象にすることが議論されていますが。まだFixはしてなさそうです。

  • 少なくとも500のサイトに含まれる
  • 月に少なくとも1,000万回フェッチされたもの

終わりに

Double-keyed HTTP cacheによる、キャッシュミスヒット率の緩和策として出てきたCache Transparency。

まだまだ話が始まったところなのでどうなるかはわからないが、Webサイトのデベロッパーとしては、JSやCSSは共通のCDNをURLからダウンロードしたほうがお得になるかもしれない...

どうなるんだろう

NICからの割り込みを適切なCPUに振り分けるための、IPヘッダオプション

NICからの割り込みを適切なCPUに振り分けられるようなHintをIPヘッダオプションとして定義する「Multiple Core Performance Hint Option」という提案が提出されています。(特許としても申請中とのこと)

ざっくり眺めて見ようかと思います。ここらへん詳しいわけではないので、間違いがあればご指摘ください。

背景

10Gbpsなどのトラフィックを処理する場合、NICからの割り込みを一つのCPUコアで処理しきれないことがあります。

NICからの割り込みを複数のCPUコアで分散する仕組みとして、Linuxでは「Receive Side Scaling (RSS)」、「Receive Packet Steering (RPS)」、「Receive Flow Steering (RFS)」などの仕組みがあります。

このとき、同じ通信フローの処理は同じコアで処理するのが好ましいです。TCPなど、処理するパケット順番が変わってしまうと、Head-of-Line-Blockingにつながります。

同一フローを同一コアに割り振るために、割り振りの方法として、送信元IP・送信先IP・送信元ポート・送信先ポートのハッシュから割当先を決める方法があるようです。


Multiple Core Performance Hint Option

先述の通り、CPUコアへの割り振りにL4の送信元ポート・送信先ポートを使用します。しかし、それらの値が取得できないケースがあります。例えば次の場合です

  • パケットがフラグメントしてる場合
  • IPSecを使用している場合

Multiple Core Performance Hint Option」では、そのような場合でも同一の通信フローを適切に割り振れるようにIPヘッダオプションを定義します。

MCPHINT

新しいIPヘッダのオプションとして、MCPHINTを定義します。
MCPHINTはIPv4, v6ともで利用でき、2バイトのデータ領域 (Differentiation Data)を持ちます。

このDifferentiation Dataを用いてフローを識別し、CPUに割り振ることを想定しています。
(送信側がフロー毎に異なるDifferentiation Dataを格納するという仕組み)

感想

実用性がどこまであるのかちょっと実感がないが、面白い提案だなとおもった。

NIC割り込み処理の割り振り先を決定するためのヒントとして、IPヘッダにオプションを新しく定義するとは、なるほど。

QUICのマルチキャスト拡張

QUICを使ってマルチキャスト配信を可能にする「Multicast Extension for QUIC」という仕様が、AkamaiのJake Holland氏らによって提案されています。

マルチキャストでデータを配信することで、よりネットワーク帯域を効率用使うことが出来ます。

まだ最初の提案であり、まだTBDとなってるところもあり、これから変わりそうだが一旦目を通しておく。

背景/関連動向

まず、この「Multicast Extension for QUIC」登場と、関連状況について簡単に説明します。

AkamaiのJake Holland氏はWebでマルチキャストを使うために幅広く活動されています。今回の「Multicast Extension for QUIC」もWebでコンテンツを配信するための流れでの提案となっています。(もちろんただのQUIC拡張ですので、用途はそれに限りません)

W3Cでは「Multicast Community Group」を設立しています。
asnokaze.hatenablog.com

また、実際にブラウザ(chromiumのfork)でマルチキャストデータを受信可能にするAPIを実装していたりします。
github.com

関連仕様

関連する仕様は次のとおりです

これらに、マルチキャストでアプリケーションデータを配信するためのQUIC拡張が追加されたというながれです。

Multicast Extension for QUICの仕様

Multicast Extension for QUIC」の仕様について眺めていきます。

ユニキャストで通常のQUICコネクションを確立した後に、マルチキャストチャネルとしてマルチキャストでデータ(1-RTTパケット)を送信できるようになります。もちろんマルチキャストチャネルはサーバ側からの一方向でしかQUICパケットを送れません。なお、マルチキャストの識別にはRFC4607で定義される(S,G)を用います。(マルチキャストルーティングについては下位層の話なので、この仕様では言及されません)

特徴としてはざっくりこんな感じ

  • QUICコネクションはRFC9000で定義された通り
  • マルチキャストデータは暗号化される(マルチキャストチャネル用の対象鍵により、他の参加者も同じデータを受信し処理できる)
  • マルチキャストチャネルのデータがパケットロスした場合は、QUICコネクション経由で再送してもらえる (なお、DATAGRAMフレームも使える)

この仕様では、拡張機能ネゴシエーション、クライアントのマルチキャストチャネルの参加/離脱、フロー制御などについて定義しています。またそのために、新しい拡張フレームやエラーコードを定義します(MC_で始まる一連の拡張フレーム)。

大まかな流れ

マルチキャストでデータ受信の大まかな流れ

  • クライアントは、QUICコネクション確立時にmulticast_client_paramsトランスポートパラメータで初期値をサーバに伝える
  • サーバは、MC_CHANNEL_ANNOUNCEフレームを送信し今存在するマルチキャストチャネルの情報をクライアントに送信します。
  • サーバは、MC_CHANNEL_JOINフレームでマルチキャストチャネルに参加を呼びかけます
  • クライアントは、サーバからの要求に対しMC_CLIENT_CHANNEL_STATEフレームを返します。MC_CLIENT_CHANNEL_STATEフレームは"参加"、"拒否"、"離脱"をサーバに伝えることが出来ます
  • クライアントは、マルチキャストチャネルでのデータ受信を開始します
  • その後サーバがMC_CHANNEL_LEAVE でクライアントに離脱を要求するか、もしくはクライアントが自発的に離脱するとマルチキャストチャネルのデータ受信が完了します
パケロス

マルチキャストチャネルのパケロスに対して、クライアントはユニキャストのQUICコネクションで再送を要求します。

MC_CHANNEL_ACKをクライアントから送ることで、パケロスしたパケットをサーバに伝えます。サーバは、ユニキャストのQUICコネクションで該当パケットのデータを再送します (QUICでは、パケロスしてもそのパケットをそのまま送り直すのではなく、再送が必要なデータのみを送ります)。

マルチキャストチャネルで受信可能なフレーム

マルチキャストチャネルで受信可能なフレームは次のとおりです。

  • PADDING Frames ([RFC9000] Section 19.1)
  • PING Frames ([RFC9000] Section 19.2)
  • RESET_STREAM Frames ([RFC9000] Section 19.4)
  • STREAM Frames ([RFC9000] Section 19.8)
  • DATAGRAM Frames (both types) ([RFC9221] Section 4)
  • PATH_CHALLENGE Frames ([RFC9000] Section 19.17)
  • MC_CHANNEL_PROPERTIES
  • MC_CHANNEL_LEAVE (however, join must come over unicast?)
  • MC_CHANNEL_INTEGRITY (not for this channel, only for another)
  • MC_STREAM_BOUNDARY_OFFSET
  • MC_CHANNEL_RETIRE

おわりに

今回はほんの一部の紹介でしたが、また機会があればフレームレベルで紹介したいと思います。

Webでのマルチキャスト配信は夢がありつつ、まだまだ熱量が高い領域ではありません。今後の動向が気になるところです。
技術的には大変おもしろいので追っていきたい。

40年越しにTCPの仕様(RFC793)が改訂される RFC9293

2022/08/09 追記 「RFC 9293 Transmission Control Protocol (TCP)」として正式なRFCが出ました


TCPのコア部分の仕様は1981年に発行された「RFC793 TRANSMISSION CONTROL PROTOCOL」で標準化されています。

この、RFC793の改訂版となる「Transmission Control Protocol (TCP) Specification」は、2013年からIETFのTCPM WGで議論されてきましたが、4月4日にIESGによって承認されました(参考URL)。現在はRFC出版の準備に入っています(新しいRFC番号はこの後正式に決まります)

www.ietf.org

改めてTCPの仕様を読みたい場合はこのドキュメントを読むのが良さそう。

概要

この改訂版の仕様(通称 rfc793bis)は、RFC793が公開されて以来断片的に公開されたTCPに関連する追加のRFCを一つにまとめ直しています。

ですので、プロトコルとしてこの改訂により大きな変更があるわけではなく、すでに標準化されているものが整理される形になります。

例えばTCPの基本的な機能について述べた次のRFCが取り込まれます

その他にも「RFC5961 Improving TCP's Robustness to Blind In-Window Attacks」の内容を、このrfc793bisで更新します。

その他にも、すでに報告されていた仕様上のエラッタなどが修正されている他、新しく公開された輻輳制御アルゴリズム(RFC2581, RFC5681, RFC6298)など多くのドキュメントを参照するようアップデートされています。

RFC793からの変更点

rfc793bisでは「5. Changes from RFC 793」に、RFC793からの変更点がまとめられています。(先にあげたRFCの取り込みとかぶりますが、かいつまんで紹介)

  • RFC793のエラッタの修正
  • RFC1011、RFC1122、RFC6093に記載されている緊急ポインタの仕様の変更の取り込み
  • RTOの説明がRFC6298を参照するように更新
  • RFC6528の初期シーケンス番号生成アルゴリズムの取り込み
  • RFC6429で記述されるている持続的接続のリソース消費に関する考慮事項について注記
  • 輻輳制御の実装上の説明を追加

TCPのRSTパケットに拒否理由をつける提案仕様

TCPの接続拒否理由を通知する「TCP RST Diagnostic Paylaod」という提案仕様がIETFに提出されています。

TCPでは様々な理由により接続拒否を示すRSTパケットが送信されます。NATやファイアウォール、リッスンされてないポートへの接続時などです。

しかしRSTパケットの受信者は、RSTパケットが返された理由を知る手段はありませんでした。それを可能にするのが「TCP RST Diagnostic Paylaod」です。

TCP RST Diagnostic Paylaod

TCP RST Diagnostic Paylaod」ではRSTパケットに接続拒否理由の格納方法を指定します

もともと、RSTパケットにデータを含めることができます。TCPの仕様の改訂版である「rfc793bis」でもSHOULDで指定されています。

TCP implementations SHOULD allow a received RST segment to include data (SHLD-2)

そこに次のような情報をCBOR形式で情報を格納します。例えば次のとおりです (例はCDDLで記述します)

[
  12345,
  {
    "reason-code": 2, 
    "reason-description": "brief human-readable description"
  }
]
  • 12345: この仕様のデータが含まれていることを示すマジックナンバー (後で正式に決定)
  • reason-code: 接続拒否理由を示す番号
  • reason-description: 人間が読める理由を示す文字列
reason-code

reason-codeとして次のものが定義されています

  • 1: クローズ後にデータを受信した
  • 2: リッスン状態なのにACKを受信した
  • 3: 不正なメッセージ
  • 4: 許可されていない
  • 5: リソースの超過
  • 6: ネットワークの障害 (中継装置などで利用)
  • 7: ピアによってリセットを受信した (中継装置などで利用)
  • 8: ピアへの到達性がない (中継装置などで利用)
  • 9: コネクションタイムアウト (中継装置などで利用)
Diagnostic Payloadの扱い

このデータはアプリケーションに渡すことが許可されています。デバックに使用することができます。

Memcachedのproxy機能を触ってみる

Memcashedでは、1月にリリースされた version 1.6.13から実験的にProxy機能が搭載されています。

公式のドキュメントはコチラ
github.com

概要

主な通信の流れは次の通りです
f:id:ASnoKaze:20220404003718p:plain
(通信内容は簡易的に記載するが、実際は通常のmemcacheプロトコルです)

  • memcachedをproxyモードで起動する際、グループ毎にサーバプールを指定する (例: foo, bar)
  • Clinetから値をsetする際は、keyにサーバプールを示すプレフィックスを付ける (例: /foo/, /bar/)
  • Proxyは、サーバプールを示すプレフィックスを取り除いたものを、バックエンドのmemcachedサーバにsetする
    • サーバプールに複数サーバがいる場合は、Keyのハッシュ計算に基づいて振り分け先が決まる (例: /foo/key1, /foo/key2)。

上記はsetの例だが、getも同様に動作する

サーバプールの指定

サーバプールの指定は、luaスクリプトで記述する。
サーバプール毎にnameを指定し、バックエンドとなるmemcachedサーバを指定するだけです。

local s = require("lib/simple")

-- by default, sends "/foo/*" to "foo" and "/bar/*" to "bar"
s.pool{
    name = "foo",
    backends = {"127.0.0.1:11212", "127.0.0.1:11213"},
}

s.pool{
    name = "bar",
    backends = {"127.0.0.1:11214", "127.0.0.1:11215"},
}

起動時に proxy_configを読み込む

./memcached -o proxy_config=./example.lua
stats proxy

proxyモードのmemcachedは "stats proxy" コマンドで状態を統計情報を取得できる

$ echo "stats proxy" |nc  localhost 11211
STAT user_simple_failovers 0
STAT cmd_mg 0
STAT cmd_ms 0
STAT cmd_md 0
STAT cmd_mn 0
STAT cmd_ma 0
STAT cmd_me 0
STAT cmd_get 1
STAT cmd_gat 0
STAT cmd_set 3
(略)
END

ビルド

現状この機能を使うには、自分でビルドすることになる。手順は公式ドキュメントの通りです
github.com

終わりに

まだ実装は実験段階だが面白い機能です。
luaスクリプト弄ったらもっといろいろ出来るかもしれないので触ってみる。単純にrepolicationとか出来ると嬉しいかも。

(最近はほぼマネージドサービス使っちゃうので、10年くらい早く欲しかった...)