WebTransport over QUICのサンプルサーバを試してみる

2022/01/04追記: この記事はすでに古いです。WebTransport over QUICは標準化せずに、WebTransport over HTTP/3を標準化する方向です。Chromeの実装もそちらに移っています。


"WebTransport over QUIC"の標準化及び、Chromiumでの実装が進んでいます。

今回はクライントを書いて、Chromiumに同梱されているquic_transport_simple_serverと通信してみました。環境は Ubuntu 18.04です。

WebTransport over QUICについては以前書いたブログを参照してください
asnokaze.hatenablog.com

quic_transport_simple_server のビルド

Chromiumのビルド手順通り勧めます (Google社員向けはスルーしましょう)
https://chromium.googlesource.com/chromium/src/+/master/docs/linux/build_instructions.md

  • Install
  • Get the code
    • Install additional build dependencies
    • Run the hooks
  • Setting up the build

フェッチに時間がかかります。
最後にビルドする際に、chromeのビルドではなく、サンプルサーバのみをビルドします

autoninja -C out/Default chrome #この部分を
ninja -C out/Default quic_transport_simple_server #こうする

証明書・鍵の作成

サーバを起動するのにPKCS#8形式の鍵が必要です

openssl req -new -key server.key > server.csr
openssl req -new -key server.key > server.csr
openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt
openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in server.key -out server.p8

起動

ビルドができていれば、実行ファイルがありますので実行します

~/chromium/src/out/Default$ ./quic_transport_simple_server \
    --accepted_origins="" \
    --key_file="/path_to/server.p8" \
    --certificate_file="/path_to//server.crt" \
    --allow_unknown_root_cert --port="10000" 
  • --accepted_origins: client indicationで受け付けるオリジン名(空を指定)
  • --key_file: 鍵
  • --certificate_file: 証明書
  • --port: ポート

クライアントサイド

WebTransport over QUICでは、QUIC DATAGRAMフレームのサポートが必須です。実際にはトランスポートパラメータでmax_datagram_frame_sizeを指定する必要があります。

今回はDATAGRAMフレームをサポートしてる、PythonのQUICライブラリ「aioquic」を利用します。
(exampleとして、DATAGRAM検証用プロトコル"siduck"実装が含まれてるのも選んだ理由です)

インストール方法は「aioquicのgithubリポジトリ」を参照。

./examples/siduck_client.py を雑にいじって、WebTransport over QUIC クライアントを作成します。
ソースはこちら https://gist.github.com/flano-yuki/3ab550393138066b19d2ff4d44e0cb47

~/work/aioquic$ python3 examples/quic_transport.py  localhost 10000 -k -q out -l ./ssllog
2020-01-13 21:04:51,881 INFO quic [229cca53a4662860] ALPN negotiated protocol wq-vvv-01
2020-01-13 21:04:51,882 INFO client Sent Client Indication
2020-01-13 21:04:51,883 INFO client Say Hello
2020-01-13 21:04:51,885 INFO client Echo is received: 
2020-01-13 21:04:51,885 INFO client b'hello world'

(-k はデバックログをファイルに出力、-lは復号用の鍵ファイルをファイルに出力)

quic_transport_simple_serverにデータを送って、Echoを受信することに成功しました。

修正ポイント

ポイントは

  • ALPNとして"wq-vvv-01"を指定する
  • Client Indicationを送信する(OriginとPATHをそれぞれ指定)
    • PATHとして/echoを指定すると、サーバはechoモードで動作します (ソース)
        b  = b'\x00\x00' + b'\x00\x17' + b'https://example.com:443'
        b += b'\x00\x01' + b'\x00\x05' + b'/echo'
        self._quic.send_stream_data(2, b, True)
  • クライアントからデータが送れるストリームでデータを送り、Echoされたデータを受信する
  • (いくつか試したが、DATAGARAMフレームにはEchoを返してくれない...? ソース的には未実装?)

終わりに

とりあえず、通信できるところまでうまく行ったので、ちゃんとクライアントを実装したい。quic-go もDATAGARAMフレーム実装が進んでるので、そっちでも試したい (サーバ・クライアント両方)