Nginx 启用 HTTPS/3

Published: 2024-09-29

Tags: HTTPS

本文总阅读量

前置条件

系统版本:Ubuntu 20.04 Nginx 版本:1.18(稍后需要升级) 用来测试的服务:当前存在可用的 HTTPS/2 网站 OpenSSL:3.0.2(可选升级)

检查 Nginx 版本并升级

我的系统恰好是 Ubuntu 20.04 + Nginx 1.18,可以参考这篇文章升级 Nginx:Upgrading Nginx from version 1.18 to 1.25 (Ubuntu 20.04)

# 备份 Nginx 配置
$ sudo cp -r /etc/nginx /etc/nginx-backup

# 添加 Nginx Repository 
$ wget http://nginx.org/keys/nginx_signing.key 
$ sudo mv nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.gpg
# sudo apt-key add nginx_signing.key

$ echo "deb http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

# 更新软件列表
$ sudo apt update

# 安装最新的 Nginx
$ sudo apt install nginx

# 检查版本
$ nginx -v
nginx version: nginx/1.27.1

已升级到了 1.27 版本

Nginx 示例配置

没有特别需要说明的,字段含义可以问下 AI,修改配置后记得 nginx -s reload 加载配置

server {
    # HTTP/3
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;

    # HTTP/2
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name yasking.org;
    merge_slashes off;

    # 证书
    ssl_certificate /etc/letsencrypt/live/yasking.org-0001/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yasking.org-0001/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    # ssl_prefer_server_ciphers on;

    ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

    # O-RTT QUIC connection resumption
    ssl_early_data on;

    # Add Alt-SvC header to negotiate HTTP/3.
    add_header Alt-Svc 'h3=":443";ma=86400';

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    # 启用 HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
    add_header X-Content-Type-Options nosniff;

    # 日志配置
    access_log /var/log/nginx/yasking.access.log;
    error_log /var/log/nginx/yasking.error.log;

    root /usr/share/nginx/html;
    index index.html index.htm;
    location / {
        try_files $uri $uri/ =404;
    }
}

# 强制 HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name yasking.org;
    return 301 https://$server_name$request_uri;
}

升级 OpenSSL 版本(可选)

当前版本 3.0.2,当前最新是 3.3.2,不升级也可以,升级步骤如下

# 下载当前最新的 OpenSSL 程序源码
$ wget https://www.openssl.org/source/openssl-3.3.2.tar.gz

# 解压缩并生成编译配置
$ sudo tar -zxvf openssl-3.3.2.tar.gz -C /usr/src/
$ cd /usr/src/
$ sudo ln -s openssl-3.3.2 openssl
$ cd openssl
$ ./config --prefix=/usr/local/ssl

# 机器 CPU 不太行的话执行 sudo make -j 1 && sudo make install  
$ sudo make -j $(nproc) && sudo make install

# 新建 /etc/ld.so.conf.d/openssl-3.0.conf 添加一行 /usr/local/ssl/lib64,此处的 /usr/local/ssl 根据 ./config 的 --prefix 参数确定
$ cat /etc/ld.so.conf.d/openssl-3.0.conf
/usr/local/ssl/lib64

# 备份原 OpenSSL 可执行程序,创建新的链接
$ sudo mv /usr/bin/openssl /usr/bin/openssl_bak
$ sudo ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl

# 链接运行时的动态链接库
$ sudo ldconfig

# 查看库的安装情况
$ sudo ldconfig -v 

HTTPS/3 访问验证

Curl 命令

$ docker run -t --rm alpine/curl-http3 curl --http3 -I https://yasking.org:443

macOS Chrome 129

Windows Firefox 130

在火狐上有个叫「HTTP Version Indicator」的扩展,安装后可以显示 HTTP 协议版本

为什么不是 macOS 的 Firefox 测试?因为它一直显示 HTTP/2,清除缓存也没用,我暂不清楚原因

在线网站:https://http3check.net

在线网站:https://http3test.com/

最后

HTTP/3 虽然不是一个新技术,但也在快速发展和完善中,可能今天的配置和参数符合标准,后天浏览器就不认降级回 HTTP/2

云平台、各个基础组件库都需要陆续迭代支持,需要一个过程,本篇借助 Nginx 使得主域名支持通过 HTTP/3 协议访问

相比于一两年前,部署方便很多,Nginx 和 OpenSSL 都不用自己编译,安装新版即可,先这样

参考