OpenSSL QUIC メモ
概要
OpenSSL 3.2 で QUIC v1 のクライアント、3.3 で QUIC v1 サーバーが実装される予定です。それに伴い、OpenSSL の QUIC 実装についてまとめていきます。
ついでに Erlang/OTP の QUIC 関連のもまとめておきます。
モチベーション
サーバーで利用する QUIC を 1 から実装するのも楽しそうで良いのですが、ビジネスで利用する場合はまずは既存の実装に乗っかるのがよさそうと考えています。
自分たちが利用している Erlang/OTP に QUIC を実装する場合は、1 から Erlang で実装するのと、NIF (Native Implemented Functions) で C/C++/Rust などで書かれた QUIC ライブラリを利用するの二択になります。
であれば、最初から Erlang で利用している OpenSSL に入る QUIC を利用するのがとてもキレイだと判断しました。自分たちの用途だと QUIC の上に HTTP/3 、WebTransport 、そして Media over QUIC Transport を実装する必要があります。
この部分は Erlang でがっつり書いて、性能が必要な QUIC 部分を OpenSSL に依存するという流れで行けるのではないかと考えています。
ゴール
OpenSSL QUIC を利用して Media over QUIC Transport を Erlang/OTP で提供すること。
OpenSSL QUIC
-
WIP: master QUIC support by tmshort · Pull Request #8797 · openssl/openssl
- 事の発端
-
QUIC and OpenSSL - OpenSSL Blog
- 2020 年 2 月の記事
- OpenSSL は 1 から自分たちで開発することを選択した
3.0 のリリースが完了すると、QUIC が私たちの取り組みの重要な焦点となることが期待されています
私たちは、早期に提供される不安定な API よりも、長期的に正しい安定した API を入手することの方が重要であると考えています
-
OMC Release Requirements
- 2021 年 10 月の話だと OpenSSL 4.0.0 で QUIC の完全な実装が提供されるという感じになるらしい
次のメジャー リリース番号は、完全に機能する QUIC リリース用に予約されることを目的としています
-
OpenSSL 3.2 Release Candidate - OpenSSL Blog
- 2023 年 11 月末リリース予定の 3.2 で QUIC v1 のクライアント実装が含まれる
-
OpenSSL's QUIC Implementation Supports RFC 9221 · openssl/openssl · Discussion #22539
- QUIC の Unreliable Datagram extension の実装予定について自分が聞いたスレ
- 早いと 3.3 (2024 年 4 月リリース) 、遅くとも 3.4 (2024 年 10 月リリース) には含まれる予定との回答を貰った
-
openssl/doc/designs/quic-design at master · openssl/openssl
- OpenSSL QUIC のデザインドキュメント一覧はこっから
- これを読めば何がどうなっていくかが見える
- openssl/README-QUIC.md at master · openssl/openssl
-
openssl/demos/http3 at master · openssl/openssl
- OpenSSL QUIC と nghttp3 を組み合わせた HTTP/3 のデモ
資料
- https://github.com/openssl/openssl/blob/master/README-QUIC.md
- https://www.openssl.org/docs/manmaster/man7/openssl-quic.html
- https://www.openssl.org/docs/manmaster/man7/ossl-guide-quic-introduction.html
- https://www.openssl.org/docs/manmaster/man7/ossl-guide-quic-client-block.html
- https://www.openssl.org/docs/manmaster/man7/ossl-guide-quic-multi-stream.html
- https://github.com/openssl/openssl/blob/master/demos/guide/quic-multi-stream.c
-
WIP: master QUIC support by tmshort · Pull Request #8797 · openssl/openssl
- Red Hat の人の Pull-Request
OpenSSL へのフィードバック
Erlang/OTP + OpenSSL QUIC
- Erlang/OTP では暗号処理に OpenSSL が利用されています
- 自社では最新の OpenSSL を利用するため、自前ビルドして静的リンクしています
- NIF を利用する際に C を利用するか Zig を利用するか悩んでいます
- OpenSSL + C のコードが多くなる可能性が高そうなのでその部分を C ではなく Zig で書いてしまおうかと考えています
- https://github.com/shiguredo/rebar3_zig
WebTransport over HTTP/2
QUIC だけならいいのですが、WebTransport を利用する際のフォールバック先としての HTTP/2 での利用をどうするか考える必要があります。
OpenSSL では QUIC までしか面倒見てくれないため、WebTransport over HTTP/2 は自前実装する必要があります。この部分は Cowboy の fork を想定しています。もちろん、メインラインへのマージして貰えるのが一番ですが、QUIC 部分が OpenSSL に依存してしまうことを考えると難しいかも知れません。
Erlang/OTP + QUIC
-
xflagstudio/requiem: WebTransport (over HTTP/3) framework for Elixir
- Cloudflare の Quiche をベースにした WebTransport + Elixir 実装
-
emqx/quic: QUIC protocol for Erlang & Elixir
- msquic を NIF で読み込んでる QUIC 実装
- MQTT over QUIC に利用されている
-
HTTP/3 by essen · Pull Request #1599 · ninenines/cowboy
- Cowboy による HTTP/3 実装
- emqx/quic を前提としている
$ openssl s_client -quic を試す
- OpenSSL 3.2.0-beta1
- mkcert localhost で証明書を作成
- mkcert -CAROOT
- quic-go でシンプルな quic サーバーを立てる
$ openssl s_client --connect localhost:4242 -verifyCAfile rootCA.pem \
-quic -alpn test -keylogfile key.txt
雑に Go で書いた QUIC サーバー
- 証明書を指定
- ポートは 4242
package main
import (
"context"
"crypto/tls"
"log"
"github.com/quic-go/quic-go"
)
func main() {
tlsCert, err := tls.LoadX509KeyPair("localhost.pem", "localhost-key.pem")
if err != nil {
log.Fatal("tls.LoadX509KeyPair: ", err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"test"},
}
listener, err := quic.ListenAddr(":4242", tlsConfig, nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
conn, err := listener.Accept(context.Background())
if err != nil {
log.Fatal("Accept: ", err)
}
_, err = conn.AcceptStream(context.Background())
if err != nil {
log.Fatal("AcceptStream: ", err)
}
}