nghttp3を使ってcurlでHTTP/3通信する


Cloudflareが作成したrust製のQUICライブラリ、quicheを使ったcurlでのHTTP/3通信は以前の記事を使って実現できましたが、ngtcp2とnghttp3を使ったcurlのビルドが上手くいかず、放置してました。

今日やってみたら動くようになってたのでうれぴーって感じです。
こんなかんじ。

$ docker run --rm -it inductor/curl-quic-ngtcp2
# curl --http3 https://facebook.com/
curl --http3 https://www.facebook.com/ -v -s -o /dev/null
*   Trying 31.13.82.36:443...
* Connect socket 3 over QUIC to 31.13.82.36:443
* QUIC handshake is completed
* Using HTTP/3 Stream ID: 0 (easy handle 0x558bdb587c60)
> GET / HTTP/3
> Host: www.facebook.com
> User-Agent: curl/7.66.0-DEV
> Accept: */*
.
.
.
< HTTP/3 200
* Added cookie fr="1tGZFXUxpL87OCnxK..BdfLZR.Wn.AAA.0.0.BdfLZR.AWWBRk07" for domain facebook.com, path /, expire 1599990224
< set-cookie: fr=1tGZFXUxpL87OCnxK..BdfLZR.Wn.AAA.0.0.BdfLZR.AWWBRk07; expires=Sun, 13-Sep-2020 09:43:44 GMT; Max-Age=31535999; path=/; domain=.facebook.com; secure; httponly
* Added cookie sb="UbZ8XcQR-3XnzQBAC3x4Cx1d" for domain facebook.com, path /, expire 1631526225
< set-cookie: sb=UbZ8XcQR-3XnzQBAC3x4Cx1d; expires=Mon, 13-Sep-2021 09:43:45 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponly
< cache-control: private, no-cache, no-store, must-revalidate
< pragma: no-cache
< strict-transport-security: max-age=15552000; preload
< vary: Accept-Encoding
< x-content-type-options: nosniff
< x-frame-options: DENY
< x-xss-protection: 0
< expires: Sat, 01 Jan 2000 00:00:00 GMT
< content-type: text/html; charset="utf-8"
< x-fb-debug: 2LA+3Be/2B1adUS/kyhklbKz6aOeHkdRA2hJF7BsBYJEv/5DgUXM5begMyO1P5Fmh42Bru0Nm5Hg6Ww+dul1ew==
< date: Sat, 14 Sep 2019 09:43:45 GMT

検証で作ったDockerfile

FROM ubuntu:18.04 as base-fetch
RUN apt-get update && apt-get install -y git

FROM ubuntu:18.04 as base-build
RUN apt-get update && apt-get install -y build-essential pkg-config autoconf libtool

FROM base-fetch as fetch-openssl
WORKDIR /root
RUN git clone --depth 1 -b openssl-quic-draft-22 https://github.com/tatsuhiro-t/openssl

FROM base-build as build-openssl
COPY --from=fetch-openssl /root/openssl /root/openssl
WORKDIR /root/openssl
RUN ./config enable-tls1_3 --prefix=/openssl
RUN make
RUN make install_sw

FROM base-fetch as fetch-nghttp3
WORKDIR /root
RUN git clone https://github.com/ngtcp2/nghttp3

FROM base-build as build-nghttp3
WORKDIR /root
COPY --from=fetch-nghttp3 /root/nghttp3 /root/nghttp3
WORKDIR /root/nghttp3
RUN autoreconf -i
RUN ./configure --prefix=/nghttp3 --enable-lib-only
RUN make
RUN make install

FROM base-fetch as fetch-ngtcp2
WORKDIR /root
RUN git clone https://github.com/ngtcp2/ngtcp2

FROM base-build as build-ngtcp2
WORKDIR /root
COPY --from=fetch-ngtcp2 /root/ngtcp2 /root/ngtcp2
WORKDIR /root/ngtcp2
RUN autoreconf -i
COPY --from=build-openssl /openssl/ /openssl
COPY --from=build-nghttp3 /nghttp3 /nghttp3
RUN apt-get update && apt-get install -y libev-dev
RUN ./configure PKG_CONFIG_PATH=/openssl/lib/pkgconfig:/nghttp3/lib/pkgconfig \
        LDFLAGS="-Wl,-rpath,/openssl/lib" \
        --prefix=/ngtcp2
RUN make
RUN make install

FROM base-fetch as fetch-curl
WORKDIR /root
RUN git clone --depth 1 https://github.com/curl/curl

FROM base-build as build-curl
RUN apt-get update && apt-get install -y libtool
COPY --from=fetch-curl /root/curl /root/curl
WORKDIR /root/curl
RUN ./buildconf
COPY --from=build-openssl /openssl /openssl
COPY --from=build-nghttp3 /nghttp3 /nghttp3
COPY --from=build-ngtcp2 /ngtcp2 /ngtcp2
RUN LDFLAGS="-Wl,-rpath,/openssl/lib" \
        ./configure --with-ssl=/openssl \
        --with-nghttp3=/nghttp3 \
        --with-ngtcp2=/ngtcp2
RUN make
RUN make install

FROM ubuntu:18.04 as executor
COPY --from=build-curl /etc/ld.so.conf.d/libc.conf /etc/ld.so.conf.d/libcurl.conf
COPY --from=build-curl /usr/local/lib/libcurl.so.4 /usr/local/lib/libcurl.so.4
COPY --from=build-curl /usr/local/bin/curl /usr/local/bin/curl
COPY --from=build-curl /openssl/lib/libssl.so.3 /openssl/lib/libssl.so.3
COPY --from=build-curl /openssl/lib/libcrypto.so.3 /openssl/lib/libcrypto.so.3
COPY --from=build-curl /nghttp3/lib/libnghttp3.so.0 /nghttp3/lib/libnghttp3.so.0
COPY --from=build-curl /ngtcp2/lib/libngtcp2.so.0 /ngtcp2/lib/libngtcp2.so.0
COPY --from=build-curl /ngtcp2/lib/libngtcp2_crypto_openssl.so.0 /ngtcp2/lib/libngtcp2_crypto_openssl.so.0
RUN ldconfig
CMD ["bash"]