HTTP/3 是基于 QUIC 协议的新一代 HTTP 协议,具有高性能和可靠性的特点。Nginx 从 1.25.0 版本开始正式支持 HTTP/3。在基于源码编译安装 Nginx 时,增加 --with-http_v3_module 参数即可开启 HTTP/3 支持。

1 编译与配置 Nginx 支持 HTTP/3


首先下载 nginx 最新稳定版源码:

wget https://nginx.org/download/nginx-1.30.0.tar.gz
tar -zxvf nginx-1.30.0.tar.gz
cd nginx-1.30.0


然后解压进入 nginx 源码目录,编译安装 Nginx。示例:

# 安装依赖
sudo apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g-dev openssl-dev

# 配置编译参数。注意:这里的 openssl 路径需要替换为实际的路径,openssl 版本需大于 3.5.1
/configure \
  --prefix=/usr/local/nginx \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_v3_module \
  --with-http_stub_status_module \
  --with-stream \
  --with-stream_ssl_module \
  --with-openssl=/path/to/openssl

# 编译与安装
make test # 测试
make
make install


接着配置 Nginx 站点启用 HTTP/3。示例:

http {
    server {
        # 配置域名
        server_name lzw.me www.lzw.me;

        listen 443 ssl;
        listen [::]:443 ssl; # ipv6 支持

        # 启用 QUIC 以启用 HTTP/3
        listen 443 quic reuseport;
        listen [::]:443 quic reuseport;

        # 配置 SLL 证书
        ssl_certificate /path/to/certificate.crt;
        ssl_certificate_key /path/to/private.key;

        # 添加 alt-svc header,告知访问客户端战站点已启用 HTTP/3
        add_header Alt-Svc 'h3=":443"; ma=86400';

        location / {
            root /var/www/html;
            index index.html;
        }
    }
}


以上即是开启 HTTP/3 的基本配置。

2 Nginx 多站点配置支持 HTTP/3 问题


当同一台服务器按照上述方法配置了多个站点时,nginx 配置重载会报如下错误:

nginx: [emerg] duplicate listen options for 0.0.0.0:443


2.1 报错根源:HTTP/3 的监听逻辑特殊性


与基于 TCP 的 HTTP/1.1 和 HTTP/2 不同,HTTP/3 采用 UDP 协议传输数据。在 Nginx 中,UDP 端口的监听规则更为严格:**同一个 IP 和端口组合(如 0.0.0.0:443),**quic **和** reuseport **等高级监听选项只能在一个** server **块中声明一次**。

如果您为每个域名单独配置 listen 443 ssl http2 quic reuseport;,Nginx 会认为这些高级选项重复绑定,从而抛出 duplicate listen options 错误。这并非 Nginx 的设计缺陷,而是 UDP 协议的特性要求——单个 QUIC 监听器即可通过 SNI(服务器名称指示)自动区分不同域名的流量。

2.2 解决方案一:合并 Server 块(最简单易懂,但配置耦合)


如果多个站点的配置逻辑相似(如使用同一套 SSL 证书、基础路由规则一致),可以将所有域名合并到同一个 server 块中。这种方式不仅能避免监听冲突,还能简化配置维护。

**配置示例**:

server {
    # 标准 HTTPS 监听(TCP,兼容 HTTP/2 和 HTTP/1.1)
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # HTTP/3 监听(UDP,仅需声明一次)
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;

    # 定义所有需要启用 HTTP/3 的域名
    server_name example.com www.example.com blog.example.com;

    # SSL 证书配置(支持通配符证书或多域名证书)
    ssl_certificate     /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    # 强制启用 TLS 1.3(HTTP/3 协议要求)
    ssl_protocols TLSv1.3;

    # 告知客户端支持 HTTP/3(关键响应头)
    add_header Alt-Svc 'h3=":443"; ma=86400';

    # 通用路由配置
    location / {
        root /usr/share/nginx/html;
        index index.html;

        # 可选:根据域名区分根目录
        if ($host = 'blog.example.com') {
            root /var/www/blog;
        }
    }
}


**配置要点:**

1. 监听指令唯一性:quic 和 reuseport 仅在 UDP 监听中声明一次,TCP 监听保持常规配置。
2. 多域名绑定:通过 server_name 同时绑定多个域名,Nginx 会自动根据请求域名分发流量。
3. Alt-Svc 响应头:必须添加该头部,告知浏览器当前站点支持 HTTP/3,否则浏览器不会主动发起 HTTP/3 请求。

2.3 解决方案二:独立 Server 块


**特别注意:该方案仅理论参考,个人实际配置实践时发现,会导致所有站点在基于 H3 请求时都变成访问配置了 quic reuseport 的站点!!!**

如果您的多个站点配置差异较大(如使用不同 SSL 证书、独立的日志规则或复杂路由),可以保留独立的 server 块,但需严格遵循监听规则:仅在一个 server 块中声明 quicreuseport,其他站点仅保留基础监听配置。

**配置示例**

主站点(承载 QUIC 监听器)

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # 仅在主站点声明 HTTP/3 监听
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;

    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.3;

    add_header Alt-Svc 'h3=":443"; ma=86400';

    location / {
        root /var/www/example.com;
        index index.html;
    }
}


副站点(无需声明 QUIC 监听)

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # 注意:此处不要添加 quic 和 reuseport 参数
    server_name blog.example.com;

    ssl_certificate     /etc/nginx/ssl/blog.example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;
    ssl_protocols TLSv1.3;

    # 副站点也必须添加 Alt-Svc 响应头
    add_header Alt-Svc 'h3=":443"; ma=86400';

    location / {
        root /var/www/blog.com;
        index index.html;
    }
}


**配置要点:**

1. 监听器唯一性:仅在主站点的 server 块中声明 quic reuseport,其他站点仅保留 TCP 监听。
2. SNI 自动分发:Nginx 的 QUIC 监听器会自动根据请求的 SNI 信息,将流量转发到对应的 server 块,无需额外配置。
3. 全局 Alt-Svc:所有站点都必须添加 Alt-Svc 响应头,否则浏览器只会对主站点发起 HTTP/3 请求,副站点仍会使用 HTTP/2。

3 配置 HTTP/3 后的关键检查


1. 防火墙配置


HTTP/3 使用 UDP 443 端口,务必确保服务器防火墙开放该端口:

- Ubuntu/UFW:sudo ufw allow 443/udp
- CentOS/Firewalld:sudo firewall-cmd --permanent --add-port=443/udp && sudo firewall-cmd --reload
- 云服务器:在云服务商的安全组规则中,添加 UDP 443 端口的入站许可。

2. 配置验证


修改配置后,先测试语法正确性,再重载 Nginx:

# 测试配置语法sudo nginx -t

# 重载配置(无需重启服务)sudo systemctl reload nginx`

3. HTTP/3 可用性验证


- 浏览器验证:打开 Chrome 开发者工具 → Network 面板 → 刷新页面 → 查看 "Protocol" 列,若显示 h3 则表示 HTTP/3 已生效。
- 命令行验证:使用支持 HTTP/3 的 curl 版本测试:
curl -I --http3 https://example.com
若返回 HTTP/3 200 状态码,则说明配置成功。

4 常见问题解答


Q:为什么副站点没有使用 HTTP/3?


A:请检查副站点是否添加了 Alt-Svc 响应头。浏览器需要通过该头部判断站点是否支持 HTTP/3,否则会默认使用 HTTP/2。

Q:可以为不同站点配置不同的 HTTP/3 端口吗?


A:可以,但不推荐。HTTP/3 默认使用 443 端口,使用非标准端口会增加用户端的配置复杂度,且大多数浏览器优先尝试 443 端口的 HTTP/3 连接。

Q:Nginx 1.30.0 之前的版本支持多站点 HTTP/3 吗?


A:Nginx 1.25.0 开始原生支持 HTTP/3,但 1.30.0 之前的版本可能存在一些兼容性问题,建议升级到最新稳定版。

5 总结


Nginx 1.30.0 多站点 HTTP/3 配置的核心是理解 UDP 监听的特殊性:**单个 QUIC 监听器即可处理多个域名的流量**。通过合并 server 块或保留单个 QUIC 监听器的方式,即可轻松解决 duplicate listen options 报错。

无论选择哪种方案,都需确保所有站点添加 Alt-Svc 响应头,并开放 UDP 443 端口。HTTP/3 带来的低延迟体验,将为您的用户带来更流畅的访问体验,同时提升网站的核心竞争力。 (AI生成)

**相关参考:**

- https://quic.nginx.org
- https://www.echo.cool/docs/middleware/nginx/nginx-advanced-features/nginx-http3-support/