Skip to content

Commit

Permalink
Merge pull request #35 from macbre/http3
Browse files Browse the repository at this point in the history
HTTP/3 support
  • Loading branch information
macbre authored May 19, 2021
2 parents 4f4a71c + 92a2188 commit 15e768c
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 27 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/dockerimage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:

Expand Down Expand Up @@ -55,4 +54,12 @@ jobs:
grep --fixed-strings '<p>It works!</p>' /tmp/h2
docker run --rm --network host ymuski/curl-http3 \
curl -v --insecure https://localhost:8889 --http3 2>&1 | tee /tmp/h3
grep --fixed-strings '< HTTP/3 200' /tmp/h3
grep --fixed-strings '< server: nginx' /tmp/h3
grep --fixed-strings '< alt-svc: h3-27=":8889"; ma=86400, h3-28=":8889"; ma=86400, h3-29=":8889"; ma=86400' /tmp/h3
grep --fixed-strings '<p>It works!</p>' /tmp/h3
docker logs test_nginx
44 changes: 24 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG NGINX_VERSION=1.19.10
ARG NGINX_VERSION=1.19.6

# https://github.com/google/ngx_brotli
ARG NGX_BROTLI_COMMIT=9aec15e2aa6feea2113119ba06460af70ab3ea62
Expand Down Expand Up @@ -47,6 +47,9 @@ ARG CONFIG="\
--with-compat \
--with-file-aio \
--with-http_v2_module \
--with-http_v3_module \
--with-openssl=/usr/src/quiche/deps/boringssl \
--with-quiche=/usr/src/quiche \
--add-module=/usr/src/ngx_brotli \
"

Expand All @@ -62,6 +65,7 @@ RUN \
gcc \
libc-dev \
make \
patch \
openssl-dev \
pcre-dev \
zlib-dev \
Expand All @@ -80,10 +84,11 @@ RUN \
cmake

COPY nginx.pub /tmp/nginx.pub
WORKDIR /usr/src/

RUN \
echo "Compiling nginx $NGINX_VERSION with brotli $NGX_BROTLI_COMMIT" \
&& mkdir -p /usr/src/ngx_brotli \
echo "Compiling nginx $NGINX_VERSION with brotli $NGX_BROTLI_COMMIT ..." \
&& mkdir /usr/src/ngx_brotli \
&& cd /usr/src/ngx_brotli \
&& git init \
&& git remote add origin https://github.com/google/ngx_brotli.git \
Expand All @@ -97,19 +102,23 @@ RUN \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --import /tmp/nginx.pub \
&& gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz \
&& mkdir -p /usr/src \
&& tar -zxC /usr/src -f nginx.tar.gz
&& tar -zxC /usr/src -f nginx.tar.gz \
&& echo "Fetching quiche and applying the patch..." \
&& cd /usr/src \
&& git clone --recursive https://github.com/cloudflare/quiche \
&& cd /usr/src/nginx-$NGINX_VERSION \
&& patch -p01 < /usr/src/quiche/extras/nginx/nginx-1.16.patch

RUN \
cd /usr/src/nginx-$NGINX_VERSION \
&& ./configure $CONFIG --with-debug \
&& make -j$(getconf _NPROCESSORS_ONLN) \
&& mv objs/nginx objs/nginx-debug \
&& mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so \
&& mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so \
&& mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so \
&& mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so \
&& ./configure $CONFIG \
echo "Setting up rust ..." \
&& curl https://sh.rustup.rs -sSf | sh -s -- -y -q \
&& export PATH="$HOME/.cargo/bin:$PATH" \
&& rustc --version \
&& cargo --version \
\
&& echo "Building nginx ..." \
&& cd /usr/src/nginx-$NGINX_VERSION \
&& ./configure $CONFIG --build="quiche-$(git --git-dir=/usr/src/quiche/.git rev-parse --short HEAD)" \
&& make -j$(getconf _NPROCESSORS_ONLN)

RUN \
Expand All @@ -120,11 +129,6 @@ RUN \
&& mkdir -p /usr/share/nginx/html/ \
&& install -m644 html/index.html /usr/share/nginx/html/ \
&& install -m644 html/50x.html /usr/share/nginx/html/ \
&& install -m755 objs/nginx-debug /usr/sbin/nginx-debug \
&& install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so \
&& install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so \
&& install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so \
&& install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so \
&& strip /usr/sbin/nginx* \
&& strip /usr/lib/nginx/modules/*.so \
\
Expand All @@ -150,7 +154,7 @@ ARG NGINX_VERSION
COPY --from=base /tmp/runDeps.txt /tmp/runDeps.txt
COPY --from=base /etc/nginx /etc/nginx
COPY --from=base /usr/lib/nginx/modules/*.so /usr/lib/nginx/modules/
COPY --from=base /usr/sbin/nginx /usr/sbin/nginx-debug /usr/sbin/
COPY --from=base /usr/sbin/nginx /usr/sbin/
COPY --from=base /usr/share/nginx/html/* /usr/share/nginx/html/
COPY --from=base /usr/bin/envsubst /usr/local/bin/envsubst
COPY --from=base /etc/ssl/dhparam.pem /etc/ssl/dhparam.pem
Expand Down
49 changes: 44 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
## What is this?

Stable and up-to-date [nginx](https://nginx.org/en/CHANGES) with [Google's `brotli` compression](https://github.com/google/ngx_brotli) and [Grade A+ SSL config](https://ssl-config.mozilla.org/)
Stable and up-to-date [nginx](https://nginx.org/en/CHANGES) with [QUIC + HTTP/3 support](https://developers.cloudflare.com/http3/), [Google's `brotli` compression](https://github.com/google/ngx_brotli) and [Grade A+ SSL config](https://ssl-config.mozilla.org/)


## How to use this image
As this project is based on the official [nginx image](https://hub.docker.com/_/nginx/) look for instructions there. In addition to the standard configuration directives, you'll be able to use the brotli module specific ones, see [here for official documentation](https://github.com/google/ngx_brotli#configuration-directives)

```
docker pull macbre/nginx-brotli:1.19.10
docker pull macbre/nginx-brotli:1.19.6-http3
```

Please refer to [the list of image tags](https://hub.docker.com/_/nginx/) as there more recent nginx versions there (but without http3 support).

## What's inside

```
$ docker run -it macbre/nginx-brotli nginx -V
nginx version: nginx/1.19.10
nginx version: nginx/1.19.6 (quiche-567cc5e)
built by gcc 10.2.1 20201203 (Alpine 10.2.1_pre1)
built with OpenSSL 1.1.1k 25 Mar 2021
built with OpenSSL 1.1.1 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-compat --with-file-aio --with-http_v2_module --add-module=/usr/src/ngx_brotli
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-compat --with-file-aio --with-http_v2_module --with-http_v3_module --with-openssl=/usr/src/quiche/deps/boringssl --with-quiche=/usr/src/quiche --add-module=/usr/src/ngx_brotli --build=quiche-567cc5e
```

## SSL Grade A+ handling
Expand All @@ -33,3 +35,40 @@ Please refer to [Mozilla's SSL Configuration Generator](https://ssl-config.mozil

* `.conf` files mounted in `/etc/nginx/main.d` will be included in the `main` nginx context (e.g. you can call [`env` directive](http://nginx.org/en/docs/ngx_core_module.html#env) there)
* `.conf` files mounted in `/etc/nginx/conf.d` will be included in the `http` nginx context

## QUIC + HTTP/3 support

<img width="577" alt="Screenshot 2021-05-19 at 16 31 10" src="https://user-images.githubusercontent.com/1929317/118840921-baf7d300-b8bf-11eb-8c0f-e57d573a28ce.png">

Please refer to `tests/https.conf` config file for an example config used by the tests. And to Cloudflare docs on [how to enable http/3 support in your browser](https://developers.cloudflare.com/http3/firefox).

```
server {
# quic and http/3
listen 443 quic reuseport;
# http/2
listen 443 ssl http2;
server_name localhost; # customize to match your domain
# you need to mount these files when running this container
ssl_certificate /etc/nginx/ssl/localhost.crt;
ssl_certificate_key /etc/nginx/ssl/localhost.key;
# Enable all TLS versions (TLSv1.3 is required for QUIC).
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
# 0-RTT QUIC connection resumption
ssl_early_data on;
# Add Alt-Svc header to negotiate HTTP/3.
add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400';
location / {
# your config
}
}
```

Refer to `run-docker.sh` script on how to run this container and properly mount required config files and assets.
3 changes: 2 additions & 1 deletion run-docker.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/bin/sh
docker run --rm \
-p 0.0.0.0:8888:80 \
-p 0.0.0.0:8889:443 \
-p 0.0.0.0:8889:443/tcp \
-p 0.0.0.0:8889:443/udp \
-v "$PWD/tests":/static:ro \
-v "$PWD/tests/static.conf":/etc/nginx/conf.d/static.conf:ro \
-v "$PWD/tests/https.conf":/etc/nginx/conf.d/https.conf:ro \
Expand Down
14 changes: 14 additions & 0 deletions tests/https.conf
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
server {
# quic and http/3
listen 443 quic reuseport;

# http/2
listen 443 ssl http2;

server_name localhost;

# openssl-generated pair for local development
# https://letsencrypt.org/docs/certificates-for-localhost/
ssl_certificate /etc/nginx/ssl/localhost.crt;
ssl_certificate_key /etc/nginx/ssl/localhost.key;

# Enable all TLS versions (TLSv1.3 is required for QUIC).
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

# 0-RTT QUIC connection resumption
ssl_early_data on;

# Add Alt-Svc header to negotiate HTTP/3.
add_header alt-svc 'h3-27=":8889"; ma=86400, h3-28=":8889"; ma=86400, h3-29=":8889"; ma=86400';

location / {
root /static;

Expand Down

0 comments on commit 15e768c

Please sign in to comment.