Skip to content

docker nginx 支持 http3

nginx v1.25.4 现在还是实验性支持,不建议在生产环境上使用

http3 书籍

免费书籍 https://http3-explained.haxx.se/zh

来源:

http3 是什么

HTTP/3 是超文本传输协议(HTTP)的最新版本,它进一步提升了 Web 通信的效率和性能。HTTP/3 主要的变化在于它不再使用 TCP(传输控制协议)作为底层传输层协议,而是使用 QUIC(快速 UDP 互联网连接),这是基于 UDP(用户数据报协议)的一个新协议。这种转变解决了 HTTP/2 中依然存在的一些性能瓶颈,尤其是在处理网络延迟和包丢失时的效率问题。

HTTP/3 的关键特性包括:

  1. 快速连接建立:QUIC 协议支持更快的连接建立时间,因为它可以将加密和传输握手合并为一个步骤,减少了往返时间。

  2. 改进的多路复用:与 HTTP/2 相比,HTTP/3 的多路复用不受 TCP 连接中的线头阻塞问题影响。这意味着单个丢失的数据包只会影响相关的流,而不会延迟整个 TCP 连接中的所有流。

  3. 内置加密:QUIC 自身包含了 TLS 加密,不再需要 TCP 和 TLS 的多重握手,这简化了加密过程并提高了安全性。

  4. 连接迁移:QUIC 允许连接在 IP 地址变化后仍然可以继续,这对移动设备来说非常有用,因为它们在移动过程中可能会从 Wi-Fi 切换到蜂窝网络。

  5. 前向纠错:QUIC 还包括了前向纠错机制,这可以在某些情况下减少因数据包丢失而重新传输的需求。

HTTP/3 的这些改进旨在为用户提供更快、更可靠的 Web 体验,特别是在移动和高延迟的网络环境下。许多现代浏览器和网站已开始支持 HTTP/3,以利用其性能优势。

nginx http3 模块官网介绍

https://nginx.org/en/docs/http/ngx_http_v3_module.html

英文原文

The ngx_http_v3_module module (1.25.0) provides experimental support for HTTP/3.

This module is not built by default, it should be enabled with the --with-http_v3_module configuration parameter.

An SSL library that provides QUIC support such as BoringSSL, LibreSSL, or QuicTLS is recommended to build and run this module. Otherwise, when using the OpenSSL library, OpenSSL compatibility layer will be used that does not support early data.

翻译成中文

nginx
ngx_http_v3_module 模块(1.25.0 版)提供了对 HTTP/3 的实验性支持。

此模块默认不会构建,应使用 --with-http_v3_module 配置参数来启用。

建议使用提供 QUIC 支持的 SSL 库,如 BoringSSL、LibreSSL 或 QuicTLS 来构建和运行此模块。否则,若使用 OpenSSL 库,将使用不支持预加载数据的 OpenSSL 兼容层。

nginx http3 例子

nginx
http {
    log_format quic '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" "$http3"';

    access_log logs/access.log quic;

    server {
        # for better compatibility it's recommended
        # to use the same port for http/3 and https
        listen 8443 quic reuseport;
        listen 8443 ssl;

        ssl_certificate     certs/example.com.crt;
        ssl_certificate_key certs/example.com.key;

        location / {
            # used to advertise the availability of HTTP/3
            add_header Alt-Svc 'h3=":8443"; ma=86400';
        }
    }
}

如何使用 docker 编译并支持 http3

github macbre/nginx-http3:latest https://github.com/macbre/docker-nginx-http3

目前 docker 中 这个macbre/nginx-http3:latest开源的镜像用的人比较多

  1. 下载 仓库源码 https://github.com/macbre/docker-nginx-http3/archive/refs/heads/master.zip

  2. 把 run-docker.sh 拷贝一份,重命名为 run-docker.ps1

run-docker.sh

sh
#!/bin/sh
docker run --rm \
  -p 0.0.0.0:8888:80 \
  -p 0.0.0.0:8889:443/tcp \
  -p 0.0.0.0:8889:443/udp \
  -v "$PWD/tests":/static:ro \
  -v "$PWD/tests/modules.conf":/etc/nginx/main.d/modules.conf:ro \
  -v "$PWD/tests/perl_rewrite.conf":/etc/nginx/conf.d/perl_rewrite.conf: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 \
  \
  -v "$PWD/tests/njs.conf":/etc/nginx/conf.d/njs.conf:ro \
  -v "$PWD/tests/njs":/opt/njs:ro \
  \
  -v "$PWD/tests/localhost.crt":/etc/nginx/ssl/localhost.crt:ro \
  -v "$PWD/tests/localhost.key":/etc/nginx/ssl/localhost.key:ro \
 --name test_nginx \
  -t macbre/nginx

要将这个用于运行 Docker 容器的 Bash 脚本转换为 PowerShell 脚本,我们需要做一些调整,主要是在参数和环境变量处理上。这里是一个相应的 PowerShell 版本的脚本:

run-docker.ps1

powershell
docker run --rm `
  -p 0.0.0.0:8888:80 `
  -p 0.0.0.0:8889:443/tcp `
  -p 0.0.0.0:8889:443/udp `
  -v "${PWD}/tests:/static:ro" `
  -v "${PWD}/tests/modules.conf:/etc/nginx/main.d/modules.conf:ro" `
  -v "${PWD}/tests/perl_rewrite.conf:/etc/nginx/conf.d/perl_rewrite.conf: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" `
  `
  -v "${PWD}/tests/njs.conf:/etc/nginx/conf.d/njs.conf:ro" `
  -v "${PWD}/tests/njs:/opt/njs:ro" `
  `
  -v "${PWD}/tests/localhost.crt:/etc/nginx/ssl/localhost.crt:ro" `
  -v "${PWD}/tests/localhost.key:/etc/nginx/ssl/localhost.key:ro" `
 --name test_nginx `
  -t macbre/nginx-http3

主要更改点:

  1. 分隔符:PowerShell 使用反引号 (`) 作为换行符,而不是 Bash 中的反斜杠 (\)。
  2. 环境变量:在 PowerShell 中,环境变量用 ${PWD} 来引用,与 Bash 的 $PWD 相似,但是更明确地表达变量的界定。
  3. 字符串:路径和参数用双引号包围,这是 PowerShell 中处理字符串的通常做法。
  4. 镜像名称macbre/nginx改成macbre/nginx-http3,免得在本地重新编译镜像(如果网络环境允许可以自己去尝试编译 Dockerfile)。

这个脚本保持了原始 Bash 脚本的功能,将它在 Docker 中运行的 Nginx 配置按照相同的方式映射到相应的文件和端口。

运行 run-docker.ps1 脚本

运行 docker 容器

powershell
.\run-docker.ps1
powershell
C:\Users\Administrator\Desktop\nginx-course\nginx-http3\docker-nginx-http3-master> .\run-docker.ps1
2024/04/28 16:36:59 [warn] 1#1: "ssl_stapling" ignored, issuer certificate not found for certificate "/etc/nginx/ssl/localhost.crt"
nginx: [warn] "ssl_stapling" ignored, issuer certificate not found for certificate "/etc/nginx/ssl/localhost.crt"

查看运行状态

bash
docker ps -a

alt text

浏览器访问 https://localhost:8889

alt text

使用 curl 测试 http3

当使用 curl 来访问使用自签名证书的 HTTPS 网站时,你需要使用 -k--insecure 选项来明确告诉 curl 忽略 SSL 证书验证错误。这在开发和测试环境中很常见,但请注意在生产环境中这是不推荐的做法,因为它会使连接易受中间人攻击。

shell
.\curl.exe -I --http3 -k https://localhost:8889/

这里的 -I 选项是为了只获取 HTTP 响应头,--http3 是指定使用 HTTP/3 协议,-k--insecure 是为了忽略证书安全警告。

alt text

使用浏览器测试

测试你的浏览器是否支持 http3 https://quic.nginx.org/

alt text

如果不支持,chrome 以下方式打开

注意需要关闭你的 VPN 网络,否则你的浏览器可能一直都是 http2

  1. 需要打开 chrome 的 quic 配置,chrome 地址栏中输入下面的地址
chrome://flags/#enable-quic
  1. Experimental QUIC protocol 修改为 Enabled

  2. 重新加载浏览器

alt text

如何使用最新版本的 curl

GitHub issues https://github.com/macbre/docker-nginx-http3/issues/100#issuecomment-1611115316

  1. 下载安装 curl

最新 curl Windows 官网:https://curl.se/windows/

直接点击下载 Windows https://curl.se/windows/dl-8.7.1_7/curl-8.7.1_7-win64-mingw.zip

  1. 使用命令获取请求头信息
powershell
.\curl.exe --http3 -I https://docs.ffffee.com:8443
powershell
PS C:\Users\Administrator\Downloads\curl-8.7.1_7-win64-mingw\curl-8.7.1_7-win64-mingw\bin> .\curl.exe --http3 -I https://docs.ffffee.com:8443
HTTP/3 200
server: nginx/1.25.4
date: Tue, 23 Apr 2024 04:34:49 GMT
content-type: text/html
content-length: 846
last-modified: Mon, 22 Apr 2024 04:00:43 GMT
etag: "6625e0eb-34e"
cache-control: no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0
accept-ranges: bytes