WebTransport のサンプルをローカル環境で動かす in 2022/04
噂によると、 WSL2 とホスト機の間で UDP 通信が出来ないらしいので再現するか確認中(ネットワークはうといので原因とか理由とかはよくわかってない)
サーバのソースコードはこれ
クライアントはこのページ
証明書は mkcert を使って生成
$ python3 webtransport_server.py localhost.pem localhost-key.pem
DEBUG:asyncio:Using selector: EpollSelector
INFO:webtransport_server:Listening on https://::1:4433
WSL2 上でサーバを起動した場合、接続を試みても何もログが追加されないのを確認。
> python3 .\server.py .\localhost.pem .\localhost-key.pem
server.py:246: DeprecationWarning: There is no current event loop
loop = asyncio.get_event_loop()
DEBUG:asyncio:Using proactor: IocpProactor
INFO:webtransport_server:Listening on https://::1:4433
Listening on https://::1:4433
PowerShell で起動するとそもそもワーニングが出るので、根本的に何か違ってそう(ソースコードは同じ)
PowerShell で動かしている python は scoop を使ってインストールしている。ライブラリをコンパイルするのに、多分 Visual C++ のなにがしか必要(メモり忘れた)
クライアントのページから接続しようとすると、下記エラーが出る。
Initialize protocol
DEBUG:quic:[bb5a734fc689848c] Network path ('::1', 60322, 0, 0) discovered
DEBUG:quic:[bb5a734fc689848c] QuicConnectionState.FIRSTFLIGHT -> QuicConnectionState.CONNECTED
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[bb5a734fc689848c] Duplicate CRYPTO data received for epoch Epoch.INITIAL
DEBUG:quic:[bb5a734fc689848c] TLS State.SERVER_EXPECT_CLIENT_HELLO -> State.SERVER_EXPECT_FINISHED
ProtocolNegotiated(alpn_protocol='h3')
DEBUG:quic:[bb5a734fc689848c] Discarding epoch Epoch.INITIAL
DEBUG:quic:[bb5a734fc689848c] Network path ('::1', 60322, 0, 0) validated by handshake
INFO:quic:[bb5a734fc689848c] Connection close received (code 0x12E, reason 199:TLS handshake failure (ENCRYPTION_HANDSHAKE) 46: certificate unknown)
DEBUG:quic:[bb5a734fc689848c] QuicConnectionState.CONNECTED -> QuicConnectionState.DRAINING
DEBUG:quic:[bb5a734fc689848c] Discarding epoch Epoch.HANDSHAKE
DEBUG:quic:[bb5a734fc689848c] Discarding epoch Epoch.ONE_RTT
DEBUG:quic:[bb5a734fc689848c] QuicConnectionState.DRAINING -> QuicConnectionState.TERMINATED
ConnectionTerminated(error_code=302, frame_type=0, reason_phrase='199:TLS handshake failure (ENCRYPTION_HANDSHAKE) 46: certificate unknown')
HELLO は届いているが、証明書がわからんとなる。
Google Chrome のショートカットを作成して、プロパティから「リンク先」の所を編集。
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --origin-to-force-quic-on=localhost:4433 https://googlechrome.github.io/samples/webtransport/client.html
--origin-to-force-quic-on=localhost:4433
これは Chrome の挙動として、デフォルトでは HTTP/2 または 1.1 で接続を開始し、 Alt-Svc を見て HTTP/3 に繋ぎなおすというのが現在の状態なので、指定したサーバに接続する時は強制的に QUIC でつないでもらうためのオプションの様子。
他の Chrome ウィンドウを消して上のショートカットから起動。
connect ボタンを押してこうなったら接続が確立された証拠。
Initialize protocol
DEBUG:quic:[401650361d6f8d6a] Network path ('::1', 53657, 0, 0) discovered
DEBUG:quic:[401650361d6f8d6a] QuicConnectionState.FIRSTFLIGHT -> QuicConnectionState.CONNECTED
INFO:quic:[401650361d6f8d6a] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[401650361d6f8d6a] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[401650361d6f8d6a] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[401650361d6f8d6a] Duplicate CRYPTO data received for epoch Epoch.INITIAL
INFO:quic:[401650361d6f8d6a] Duplicate CRYPTO data received for epoch Epoch.INITIAL
DEBUG:quic:[401650361d6f8d6a] TLS State.SERVER_EXPECT_CLIENT_HELLO -> State.SERVER_EXPECT_FINISHED
ProtocolNegotiated(alpn_protocol='h3')
DEBUG:quic:[401650361d6f8d6a] Discarding epoch Epoch.INITIAL
DEBUG:quic:[401650361d6f8d6a] Network path ('::1', 53657, 0, 0) validated by handshake
DEBUG:quic:[401650361d6f8d6a] TLS State.SERVER_EXPECT_FINISHED -> State.SERVER_POST_HANDSHAKE
DEBUG:quic:[401650361d6f8d6a] Discarding epoch Epoch.HANDSHAKE
INFO:quic:[401650361d6f8d6a] ALPN negotiated protocol h3
HandshakeCompleted(alpn_protocol='h3', early_data_accepted=False, session_resumed=False)
DEBUG:quic:[401650361d6f8d6a] Stream 2 created by peer
ConnectionIdIssued(connection_id=b'\xb1\xaa 5.\xee\xe7w')
StreamDataReceived(data=b"...", end_stream=False, stream_id=2)
DEBUG:quic:[401650361d6f8d6a] Stream 10 created by peer
DEBUG:quic:[401650361d6f8d6a] Stream 0 created by peer
StreamDataReceived(data=b'...', end_stream=False, stream_id=10)
StreamDataReceived(data=b'...', end_stream=False, stream_id=0)
DEBUG:quic:[325826080f47f0fa] Discarding epoch Epoch.ONE_RTT
DEBUG:quic:[325826080f47f0fa] QuicConnectionState.CONNECTED -> QuicConnectionState.TERMINATED
ConnectionTerminated(error_code=<QuicErrorCode.INTERNAL_ERROR: 1>, frame_type=<QuicFrameType.PADDING: 0>, reason_phrase='Idle timeout')
DEBUG:quic:[757b4b5967f86243] Discarding epoch Epoch.ONE_RTT
DEBUG:quic:[757b4b5967f86243] QuicConnectionState.CONNECTED -> QuicConnectionState.TERMINATED
ConnectionTerminated(error_code=<QuicErrorCode.INTERNAL_ERROR: 1>, frame_type=<QuicFrameType.PADDING: 0>, reason_phrase='Idle timeout')
接続成功時のサーバ側のログはこんな感じ。
ということで
- WSL2 で WebTransport サーバを立てることは(まだ)出来ない(話によると WSL 2 上で UDP サーバ自体立てれないらしい)
- このサーバサンプルコードでは
--origin-to-force-quic-on=localhost:4433
を指定して起動しないといけないので、エンドユーザーに使ってもらうのは結構厳しい - 証明書は mkcert で作った奴なら、 https://github.com/aiortc/aioquic/tree/main/examples にある
--ignore-certificate-errors-spki-list=BSQJ0jkQ7wwhR7KvPZ+DSNk2XTZ/MS6xCbo9qu++VdQ=
オプションをつけなくてもいい(無効な証明書をスルーするオプション) - サンプルコード自体は動作することが分かった
サーバサイドのコードで、 HTTP/2, 1.1, 0.9? もリッスンできるようにして、手動でプロトコルを HTTP/3 に付け替えるような実装が出来れば、起動オプションを指定しなくてもつながるようになるかもしれない。しかし aioquic の実装はようわからんので、もうちょっと深追いする必要がありそう。