OpenSource-Hub

quiche

ライブラリ

cloudflare/quiche

Rustで実装されたQUICおよびHTTP/3の高性能ネットワーク転送ライブラリ。

概要

quiche は Rust で実装された QUIC トランスポートプロトコルおよび HTTP/3 ライブラリであり、パケットと接続状態を処理するための低レベル API を提供します。アプリケーション側で I/O、イベントループ、タイマーを自ら管理する必要があります。Cloudflare のエッジネットワーク、Android における DNS over HTTP/3、curl の HTTP/3 サポートなどで採用されています。

README プレビュー

\n\n[](https://crates.io/crates/quiche)\n[](https://docs.rs/quiche)\n[](https://opensource.org/licenses/BSD-2-Clause)\n\n\n[quiche] is an implementation of the QUIC transport protocol and HTTP/3 as\nspecified by the [IETF]. It provides a low level API for processing QUIC packets\nand handling connection state. The application is responsible for providing I/O\n(e.g. sockets handling) as well as an event loop with support for timers.\n\nFor more information on how quiche came about and some insights into its design\nyou can read a [post] on Cloudflare's blog that goes into some more detail.\n\n[quiche]: https://docs.quic.tech/quiche/\n[ietf]: https://quicwg.org/\n[post]: https://blog.cloudflare.com/enjoy-a-slice-of-quic-and-rust/\n\nWho uses quiche?\n----------------\n\n### Cloudflare\n\nquiche powers Cloudflare edge network's [HTTP/3 support][cloudflare-http3]. The\n[cloudflare-quic.com](https://cloudflare-quic.com) website can be used for\ntesting and experimentation.\n\n### Android\n\nAndroid's DNS resolver uses quiche to [implement DNS over HTTP/3][android-http3].\n\n### curl\n\nquiche can be [integrated into curl][curl-http3] to provide support for HTTP/3.\n\n[cloudflare-http3]: https://blog.cloudflare.com/http3-the-past-present-and-future/\n[android-http3]: https://security.googleblog.com/2022/07/dns-over-http3-in-android.html\n[curl-http3]: https://github.com/curl/curl/blob/master/docs/HTTP3.md#quiche-version\n\nGetting Started\n---------------\n\n### Command-line apps\n\nBefore diving into the quiche API, here are a few examples on how to use the\nquiche tools provided as part of the [quiche-apps](apps/) crate. These are not\nsuitable for production environments; see [disclaimers and\nnotes](#disclaimers-and-notes).\n\nAfter cloning the project according to the command mentioned in the [building](#building) section, the client can be run as follows:\n\n```bash\n $ cargo run --bin quiche-client -- https://cloudflare-quic.com/\n```\n\nwhile the server can be run

FAQ (5)

トラブル対応
送信側が MAX_DATA を超えていないにもかかわらず、quiche が長時間実行されている QUIC バルク転送を FLOW_CONTROL_ERROR でクローズしてしまう問題は、どのように修正すればよいですか?

これはquicheのissue #2696が原因です。長さゼロのnon-FIN STREAMフレームは、ストリームの最大受信オフセットを進め、コネクションレベルのフロー制御に計上されますが、RecvBuf::write()はストリームのハイウォーターマークを進めずに空フレームを破棄します。その後、実際のデータがそのオフセットに到達すると、同じバイトが再度計上され、最終的に正当なトラフィックがMAX_DATAを超過しているように見えてしまいます。この問題はリビジョン0b1a89afで再現され、典型的には、長時間の転送の終盤で、大きなストリームID/オフセットによりパケットの残り容量をちょうど埋める空のSTREAMフレームが生成される場合に発生します。レシーバー側の修正として、RecvBuf::write()内の空のnon-FIN早期リターンパスを更新し、リターンする前にハイウォーターマークを同期してください: self.len = cmp::max(self.len, buf.max_off());。また、センダー側の修正も適用してください: stream-frameのemit()が(0, false)を返した場合はSTREAMフレームをエンコードせず、これをapplication-limitedではなくpacket-size-limitedとして扱い、BBR2サンプルがapp-limitedとしてマークされないようにします。quicheを再ビルドして再デプロイするか、issue #2696のPRを含むリリースにアップグレードしてください。一時的な緩和策しか実施できず、かつ両方のピアを管理下に置いている場合は、センダー側の変更をデプロイすることで、これらの冗長な空フレームの生成を防ぐことができます。

参照 Issue #2696
トラブル対応
quiche で長さゼロの STREAM FIN がドロップされ、ピアが EOF を受信できなくなる問題を修正するにはどうすればよいですか?

これは quiche 0.29.2 のバグです: SendBuf::is_complete() は、FIN を運ぶ STREAM フレームが一度も送信・確認応答されていない場合でも、すべてのストリームバイトが確認応答されればストリームを完了とみなします。そのため、すでに確認応答済みのオフセットへの長さゼロの stream_send(id, b"", true) は破棄される可能性があり、ピアは最終的なストリームサイズを知ることができません。

修正 stream: track FIN acknowledgements separately を含むリリースにアップグレードしてください。この修正では、確認応答済みのバイト範囲とは独立して FIN の確認応答を追跡します: fin_off にある FIN=true の STREAM フレームが確認応答されるまで、ストリームは保持され、空の FIN はフラッシュ可能/再送可能な状態のままとなります。

送信する最終データがある場合の一時的な回避策として、後から空の FIN を送信するのではなく、データと FIN を組み合わせて送信してください:

// 避けるべき:
stream_send(id, b"response", false)?;
// ... データが確認応答された後 ...
stream_send(id, b"", true)?;

// 推奨:
stream_send(id, b"response", true)?;

真に長さゼロのストリームの場合は、FIN をピギーバックできる空でないデータフレームが存在しないため、アップグレードするか FIN 追跡パッチを適用する必要があります。

参照 Issue #2525
トラブル対応
quiche が RFC 9000 の 3x anti-amplification limit を超えないようにするにはどうすればよいですか?

増幅防止係数に3より大きい値を設定しないでください。quicheはデフォルトでRFC準拠の値3を使用するため、デフォルト設定のまま利用するアプリケーションは安全です。Rustでconfig.set_max_amplification_factor(v)を呼び出す場合、またはCでquiche_config_set_max_amplification_factor()を呼び出す場合は、v <= 3であることを確認してください。プロトコルの最大値には3を使用し、より厳しい制限を設ける場合はそれより小さい値を使用してください。例: config.set_max_amplification_factor(3);。4のような値は、アドレス検証の前に3 * received_bytesを超える送信を意図的に許可するものであり、RFC 9000 §8.1/RFC 9001 §9.3に違反します。コンプライアンスを強制する必要があるフォークを維持している場合は、セッター内で入力を拒否するかクランプしてください。例えばself.max_amplification_factor = v.min(3);のようにします。

参照 Issue #2679
トラブル対応
quiche が重複した RETIRE_CONNECTION_ID フレームの後に PROTOCOL VIOLATION で QUIC 接続を閉じてしまう問題を修正するにはどうすればよいですか?

issue #1833 の修正を含むリリースに quiche をアップグレードするか、リンクされた PR を適用/cherry-pick して再ビルドしてください。Git からビルドする場合は、重複した RETIRE_CONNECTION_ID の修正を含む quiche のリビジョンを使用してください。

正しい動作は次のとおりです:
1. まず、アクティブなコネクション ID リストでシーケンス番号を検索します。
2. シーケンス番号がすでに廃止されているか、不明な場合は、フレームを有効な再送信として無視します。
3. ID がアクティブな場合にのみ廃止します。
4. アクティブな ID を廃止した結果、使用可能なコネクション ID が残らない場合にのみ、プロトコル違反を返します。

quiche/src/cid.rs では、inner.len() による可用性チェックは、通知されたシーケンス番号が現在アクティブであることを確認する前に実行してはいけません。RETIRE_CONNECTION_ID フレームはパケットロス後に再送信される可能性があるため、重複した RETIRE_CONNECTION_ID フレームは RFC 9000 で許可されています。

一時的な回避策: パッチを適用した quiche ビルドを使用するか、廃止によってコネクション ID セットが枯渇しないように、ピアが追加のアクティブなコネクション ID を利用できる状態にしてください。

参照 Issue #1833
トラブル対応
acceptストリームがドロップされた後にtokio-quicheリスナーがUDPソケットを解放しない問題を修正する方法

これは tokio-quiche 0.20.0 に影響します。ルーターは accept_sink.is_closed() をチェックしますが、アイドル状態のリスナーはストリームのクローズに対する waker を登録しないため、UDP/接続イベントでパークされたままとなり、ソケットを保持し続けます。ルーターの poll/select ループ内で accept チャネルの Sender::closed() フューチャーを保持してポーリングするアップストリームの修正を適用してください。これにより、返された accept ストリームがドロップされると、アイドル状態のリスナーが起こされ、シャットダウンできるようになります。PR fix(tokio-quiche): wake idle listener on stream drop を含むリリースを使用するか、その PR から tokio-quiche にパッチを適用するか、修正済みのコミットをビルドしてください。一時的な回避策として、UDP パケットを受信するとパークされたルーターを起こしてクローズフラグを認識させることができますが、パッチこそが信頼できる修正です。

参照 Issue #2760