はじめに
前回記事では、goquicのリバースプロキシを使ってHTTP/3, QUIC接続を試そうとして失敗した
今回はそのリベンジ!
curl --http3
コマンドでHTTP/3通信できることを確認した
今回のリバースプロキシは・・・
Nginxです!
WebサーバーのHTTP/3対応をNginxのリバースプロキシでするためのDockerイメージが出来ました
前回は、goquicをプロキシ、nginxを最終アクセス先としていたが
今回は、nginxがプロキシ、ghostが最終アクセス先とする
(予備知識)Ghostとは
Ghost is a free and open source blogging platform written in JavaScript
無料のブログプラットフォーム(らしい)です
最終アクセス先として、Ghostを採用しただけなので、Ghostについてはここまで
ひと昔前は、こういうコンテンツサイト?ブログサイト?といえばWordPressだったけど・・・
検証環境をつくる on Docker
前回記事と同様に、docker-compose
で環境をつくる
コンテナ | 役割 |
---|---|
client |
curl コマンドを打つ役 |
proxy |
HTTP/3アクセスを受け付けるリバースプロキシ |
ghost |
単なるブログサイト。HTTP/3に対応していない想定 |
クライアント ->(ここはHTTP/3)-> プロキシ -> (ここはHTTP/2以下) -> ブログサイト
クライアントに証明書をインストールする
前回と同じく、クライアントにはサーバー証明書を入れておく
これでHTTPS通信することができるようになる
何はともあれ、クライアントのコンテナに入って作業する
docker compose up -d
docker compose exec client ash
パッケージマネージャが使えないコンテナなので、.crt
ファイルに直接書き込む
cat /nginx/server.crt >>/etc/ssl/certs/ca-certificates.crt
パッケージマネージャが使える環境であれば、このような直書きではなく、コマンドで証明書をインストールしましょう
いざ、接続!
クライアントからHTTP/1.1, HTTP/2, HTTP/3 の3パターンで接続してみる
HTTP/1.1
HTTP接続
curl http://proxy -I
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Tue, 01 Aug 2023 13:37:05 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 10255
Connection: keep-alive
X-Powered-By: Express
Cache-Control: public, max-age=0
ETag: W/"280f-LG5sPxcueSIwKUCwqdjGkQDJ338"
Vary: Accept-Encoding
HTTP/2
HTTPS接続
curl https://proxy -I
HTTP/2 200
server: nginx/1.16.1
date: Tue, 01 Aug 2023 13:39:27 GMT
content-type: text/html; charset=utf-8
content-length: 10255
x-powered-by: Express
cache-control: public, max-age=0
etag: W/"280f-LG5sPxcueSIwKUCwqdjGkQDJ338"
vary: Accept-Encoding
alt-svc: h3-23=":443"; ma=86400
HTTP/3
HTTPSかつ--http3
オプションを付けると、HTTP/3で接続できる
curl https://proxy -I --http3
HTTP/3 200
server: nginx/1.16.1
date: Tue, 01 Aug 2023 13:40:46 GMT
content-type: text/html; charset=utf-8
content-length: 10255
x-powered-by: Express
cache-control: public, max-age=0
etag: W/"280f-LG5sPxcueSIwKUCwqdjGkQDJ338"
vary: Accept-Encoding
alt-svc: h3-23=":443"; ma=86400
HTTPのバージョン違いでパケットがどう変わるか
HTTP1.1, 2, 3 のそれぞれの方法で接続できることがわかった
Ghostの初期サイトは軽量すぎて、アクセス速度の差がわからない
ポートスキャンをしてパケットのやり取りの総量を比べてみる
ポートスキャンの準備
Nginxのコンテナに入り
docker compose exec proxy bash
tcpdump
をインストールする
apt update && apt install -y tcpdump
# バージョン確認
tcpdump --version
tcpdump version 4.9.3
libpcap version 1.8.1
OpenSSL 1.1.1 11 Sep 2018
# キャプチャするコマンド
tcpdum -w /mnt/out.pcap
HTTP/1.1
スリーウェイハンドシェイクでかっちり通信
HTTP/2
HTTP/2については、令和5年春のネットワークスペシャリスト試験午後1問題で解説されている
- HTTP1.1はリクエストを受けたのと同じ順序レスポンスを返す必要があるが、HTTP/2にはその制約がない
- HTTP1.1はパイプラインで多重化している。一方、HTTP/2ストリームと呼ばれる仮想の通信路で多重化している
ヘッダーフィールドの必須フィールド
ヘッダーはHPACKアルゴリズムでバイナリに圧縮されている
:method, :scheme, :path の3つが必須フィールド
ここはもっと書くべきことがありそうだ!後で追記する!
HTTP/3
ここはもっと書くべきことがありそうだ!後で追記する!
おわりに
前回のリベンジで、リバースプロキシを使ってQUICを体感した
HTTP/3に対応していないサーバであっても
このリバースプロキシを使えば、クライアントからはあたかもHTTP/3対応のサーバが動いているように見える
HTTP/2, HTTP/3のパケットキャプチャした結果については
もっともっと中身をよくよんで勉強すべきことがありそう
記事を途中まで書いてから時間がたってしまったので、いったん放流する
付録
docker-compose.yml
version: "3.8"
services:
client:
image: keioni/curl-http3
container_name: client
hostname: client
tty: true
stdin_open: true
volumes:
- './nginx/server.crt:/nginx/server.crt'
networks:
net1:
ipv4_address: 172.23.230.30
proxy:
image: nwtgck/nginx-http3
container_name: proxy
hostname: proxy
restart: always
ports:
- '80:80'
- '443:443'
- '443:443/udp'
depends_on:
- ghost
volumes:
- ./nginx/nginx.conf:/usr/local/nginx/conf/nginx.conf
- ./nginx/server.crt:/etc/ssl/certs/server.crt
- ./nginx/serverinstall.key:/etc/ssl/private/server.key
networks:
net1:
ipv4_address: 172.23.230.60
ghost:
image: ghost
restart: always
depends_on:
- ghost-db
environment:
database__client: mysql
database__connection__host: 172.23.230.80
database__connection__user: root
database__connection__password: password
database__connection__database: ghost
networks:
net1:
ipv4_address: 172.23.230.70
ghost-db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: password
networks:
net1:
ipv4_address: 172.23.230.80
networks:
net1:
ipam:
driver: default
config:
- subnet: 172.23.230.0/24