Help us understand the problem. What is going on with this article?

HTTP/3 対応の curl を作る

といっても

ほぼ、curl のページをなぞっただけですが……。
https://github.com/curl/curl/blob/master/docs/HTTP3.md

※ Docker 使えます

その前に。

Docker でお手軽に試せます。
https://hub.docker.com/r/keioni/curl-http3

docker run --rm keioni/curl-http3 curl -v -L -s --http3 https://quic.tech:8443

HTTP/3 に対応させた nginx もあるので、併せて使えば HTTP/3 のテストが簡単にできます。

build

ここでは、nghttp3 + ngtcp2 版quiche 版 の二つを紹介します。

現時点(2020年7月27日現在)では、どちらがいいとか悪いとかはない、と感じています1

quiche2 は、CDNプロバイダの Cloudflare が作った実装で、エッジサーバで実際に使っているそうです。

nghttp3, ngtcp2 は、あまり詳しくないのですが、HTTP/2 の実装である nghttp2 に携わった方々によって作られている、もののようです。(違っていたらごめんなさい)

build するにあたっても、

  • quiche 版 は手順は少ないですが、BoringSSL や cargo のような、人によっては不慣れでトラブルに対応するのが難しいかもしれません
  • nghttp3 + ngtcp2 版 は OpenSSL ですし、おなじみの make を使うので単純ですが、手順が少し増えます

ぐらいの違いしかないので、好みで選んでいいのではないかなーと思います。

nghttp3 + ngtcp2 版

パッケージのインストール

まず、git と、gcc などおなじみの build 用パッケージも入れます。環境によってはすでに入ってたりすると思いますが、参考までに Amazon Linux 2 の Docker イメージで私が入れたパッケージをリストアップしました。

yum install git unzip gcc gcc-c++ make autoconf automake libtool \
pkgconfig

次に、build 対象が依存している開発用パッケージもを入れます。

yum install CUnit-devel libev-devel libnghttp2-devel

その他、build する curl で通信の圧縮ができるように zlib も入れておくといいかなーと。

yum install zlib-devel

ビルド

URLは2020年7月20日時点の最新のものです。必要に応じて新しいものを確認してください。

インストール先は、ここでは /opt/http3 にします。

extern PREFIX="/opt/http3"

openssl (+ QUIC patch)

git clone --depth 1 -b OpenSSL_1_1_1g-quic-draft-29 https://github.com/tatsuhiro-t/openssl
cd openssl
./config --prefix=$PREFIX
make
make install_sw

nghttp3

git clone https://github.com/ngtcp2/nghttp3
cd nghttp3
autoreconf -i -v
./configure --prefix=$PREFIX --enable-lib-only
make
make install

ngtcp2

git clone https://github.com/ngtcp2/ngtcp2
cd ngtcp2
autoreconf -i -v
./configure --prefix=$PREFIX PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
make
make install

curl

git clone https://github.com/curl/curl
cd curl
./builconf
./configure \
    LDFLAGS="-Wl,-rpath,$PREFIX/lib" \
    PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" \
    --prefix="$PREFIX" \
    --enable-alt-svc
make
make install

確認

できあがりました。中身を確かめてみます。

# /opt/http3/bin/curl -V
curl 7.72.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.72.0-DEV OpenSSL/1.1.1g zlib/1.2.7 nghttp2/1.41.0 ngtcp2/0.1.0-DEV nghttp3/0.1.0-DEV
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets

ちゃんと nghttp3ngtcp2 を使ってますね。

quiche 版

パッケージのインストール

まず、Rust が入っていない場合は rustup などを使って入れます。

次に、git と、gcc などおなじみの build 用パッケージも入れます。環境によってはすでに入ってたりすると思いますが、参考までに Amazon Linux 2 の Docker イメージで私が入れたパッケージをリストアップしました。

yum install git gcc gcc-c++ make automake autoconf libtool pkgconfig cmake3

通信の圧縮を有効にするときは zlib-devel を、HTTP/3 だけでなく HTTP/2 も有効にしたいときは libnghttp2-devel も導入します。

yum install zlib-devel
yum install libnghttp2-devel

ビルド

cmake パッケージのバイナリが cmake3 になっている場合は cmake にシンボリックリンクを張ります。

ln -s /usr/bin/cmake3 /usr/bin/cmake

quiche + BoringSSL

BoringSSL を含んだ quiche を build します。

以下は、先に示したURLの中身をまるまるコピーしただけです。

git clone --recursive https://github.com/cloudflare/quiche
cd quiche
cargo build --release --features pkg-config-meta,qlog
mkdir deps/boringssl/src/lib
ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) deps/boringssl/src/lib/

curl

curl 本体を build します。

cd ..
git clone https://github.com/curl/curl
cd curl
./buildconf
./configure \
    LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" \
    --prefix="/opt/http3" \
    --with-ssl="$PWD/../quiche/deps/boringssl/src" \
    --with-quiche="$PWD/../quiche/target/release" \
    --enable-alt-svc
make

確認

できあがりました。中身を確かめてみます。

# /opt/http3/bin/curl -V
curl 7.72.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.72.0-DEV BoringSSL zlib/1.2.7 nghttp2/1.41.0 quiche/0.5.1
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL UnixSockets

quiche が使われていることが分かります。

実行

実際に動作を試してみましょう。

/opt/http3/bin/curl -v --http3 https://quic.tech:8443

nghttp3 + ngtcp2 版と quiche 版では若干表示が違っています。

nghttp3 + ngtcp2 版

こんな感じになるはずです。

*   Trying 45.77.96.66:8443...
* Connect socket 5 over QUIC to 45.77.96.66:8443
*   Trying 2001:19f0:5:c21:5400:1ff:fe33:3b96:8443...
* Immediate connect fail for 2001:19f0:5:c21:5400:1ff:fe33:3b96: Cannot assign requested address
* QUIC handshake is completed
* Connected to quic.tech () port 8443 (#0)
* Using HTTP/3 Stream ID: 0 (easy handle 0xaaaa00)
> GET / HTTP/3
> Host: quic.tech:8443
> user-agent: curl/7.72.0-DEV
> accept: */*
>
< HTTP/3 200
< server: quiche
< content-length: 462
< priority:
<!DOCTYPE html>

<html>
<head>
:
(省略)
:
</head>

<body>
    <div class="cont">
        <img src="/quic.svg" />
    </div>
</body>
</html>
* Connection #0 to host quic.tech left intact

quiche 版

quiche 版だとこんな感じです。

*   Trying 45.77.96.66:8443...
* Sent QUIC client Initial, ALPN: h3-29,h3-28,h3-27
*   Trying 2001:19f0:5:c21:5400:1ff:fe33:3b96:8443...
* Immediate connect fail for 2001:19f0:5:c21:5400:1ff:fe33:3b96: Cannot assign requested address
* Connected to quic.tech (45.77.96.66) port 8443 (#0)
* h3 [:method: GET]
* h3 [:path: /]
* h3 [:scheme: https]
* h3 [:authority: quic.tech:8443]
* h3 [user-agent: curl/7.72.0-DEV]
* h3 [accept: */*]
* Using HTTP/3 Stream ID: 0 (easy handle 0x23969d0)
> GET / HTTP/3
> Host: quic.tech:8443
> user-agent: curl/7.72.0-DEV
> accept: */*
>
< HTTP/3 200
< server: quiche
< content-length: 462
< priority:
<
<!DOCTYPE html>

<html>
<head>
:
(省略)
:
</head>

<body>
    <div class="cont">
        <img src="/quic.svg" />
    </div>
</body>
</html>
* Connection #0 to host quic.tech left intact

リクエストの “GET / HTTP/3” と、レスポンスの “HTTP/3 200” が出ていれば成功です! いえい!

Alt-Svc

詳細は省きますが、Alternate service (Alt-Svc) にも対応しているので、その挙動を見るのにも使えます。

/opt/http3/bin/curl -v --alt-svc altsvc.cache https://quic.aiortc.org/

さいごに

HTTP/3 対応のサイトは2020年7月27日現在、ほとんどありません。
今この curl を使うとしたら、自分で HTTP/3 サーバを建てるときでしょう。というわけで、HTTP/3 対応の nginx を作る方法も書きました。よろしければぜひ。

あと、既存のテストサイトもあります。お手軽に試してみてくださいー!
https://bagder.github.io/HTTP3-test/

(あと、こっそり私のサイトも対応させています。いつ止めるか分からないですが……)


  1. プロトコル自体が正式版になっていないので、この段階で速度がどうとか言うものでもないですし、コードは日々アップデートされていくので clone した版によっては不安定なこともあると思います 

  2. quiche は甘くないパイというかタルトのような「キッシュ」と同じ綴りです。ロゴもそれっぽいですね 

keys
双子のロシアンブルーと同居するインフラ系エンジニア。楽するための苦労はいとわないタイプ。最適化とか自動化が大好き。IPv6, AWS, Docker, Serverless, Python, セキュリティといった単語に反応するようです。すみっコぐらしの推しはとかげ。みにっコだとざっそう。
https://devel.keys.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした