TLSv1.3 草案出来有很长一段时间了, Chrome, Firefox 以及 Cloudflare 的 CDN 也早加入了实验性支持, 所以就很想试试, 结果找了半天并没有找到解决方案, 很气. 直到后来无意看到 OpenSSL 的代码库 多了个 tls1.3-draft-18 的分支 就贼高兴, 折腾了半天之后终于成功给 NGINX 开启了 TLSv1.3.
注: NGINX 1.13.0 开始 正式支持 ssl_protocols 的 TLSv1.3 的选项. 在此之前 TLSv1.2 选项会自动使用 TLSv1.3.
OpenSSL 目前有 draft-18 分支, pre2 的 draft-23, pre7-pre8 的 draft-28, 以及 pre9+ 的 Final, 通过 tls1.h (include/openssl/tls1.h 第35行) 可以查看目前的 Draft…
从 Chrome 65 开始会默认开启并使用 TLSv1.3 Draft 23, 从 Chrome 68 开始支持 Draft 28 (Firefox Nightly 应该也支持), Chrome 70.0.35xx 开始支持 Final , 但同版本号 Linux 会默认使用 Final, 而 Windows 则使用 Draft 23, 很迷.
编译安装 依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 sudo apt update sudo apt install -y build-essential cmake autoconf automake libjemalloc-dev libatomic-ops-dev liblua5.1-dev libluajit-5.1-dev libgeoip-dev libmaxminddb-dev libpcre3-dev libxslt-dev libpam0g-dev mkdir ~/Swift && cd ~/Swiftwget https://nginx.org/download/nginx-1.17.6.tar.gz tar zxf nginx-1.17.6.tar.gz pushd nginx-1.17.6curl https://raw.githubusercontent.com/hakasenyang/openssl-patch/master/nginx_hpack_push_1.15.3.patch | patch -p1 popd pushd nginx-1.17.6curl https://raw.githubusercontent.com/hakasenyang/openssl-patch/master/nginx_strict-sni_1.15.10.patch | patch -p1 popd wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz tar zxf openssl-1.1.1d.tar.gz pushd openssl-1.1.1dcurl https://raw.githubusercontent.com/hakasenyang/openssl-patch/master/openssl-equal-1.1.1d_ciphers.patch | patch -p1 popd pushd openssl-1.1.1dcurl https://raw.githubusercontent.com/hakasenyang/openssl-patch/master/openssl-1.1.1d-chacha_draft.patch | patch -p1 popd git clone https://github.com/cloudflare/zlib.git pushd zlib./configure popd git clone --recursive https://github.com/eustas/ngx_brotli.git git clone https://github.com/aperezdc/ngx-fancyindex.git git clone https://github.com/simplresty/ngx_devel_kit.git git clone https://github.com/arut/nginx-dav-ext-module.git git clone https://github.com/leev/ngx_http_geoip2_module.git git clone https://github.com/sto/ngx_http_auth_pam_module.git git clone https://github.com/openresty/headers-more-nginx-module.git git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
编译 使用 --with-openssl=../openssl-*
来指定 OpenSSL 路径目前 OpenSSL 开启 TLS1.3 需要 加入 --with-openssl-opt=enable-tls1_3
TLSv1.3 is enabled by default in the latest development versions (there is no need to explicitly enable it). To disable it at compile time you must use the “no-tls1_3” option to “config” or “Configure”.
https://www.openssl.org/blog/blog/2018/02/08/tlsv1.3/
HTTP2 HPACK 需要加入 --with-http_v2_hpack_enc
其他参数自己按需控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 cd nginx-1.17.6./configure \ --with-cc-opt='-g -O3 -m64 -march=native -ffast-math -DTCP_FASTOPEN=23 -fPIE -fstack-protector-strong -flto -fuse-ld=gold --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-unused-parameter -fno-strict-aliasing -fPIC -D_FORTIFY_SOURCE=2 -gsplit-dwarf' \ --with-ld-opt='-lrt -L /usr/lib -ljemalloc -Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now -fPIC' \ --sbin-path=/usr/sbin/nginx \ --prefix=/usr/share/nginx \ --conf-path=/etc/nginx/nginx.conf \ --http-log-path=/var/log/nginx/access.log \ --error-log-path=/var/log/nginx/error.log \ --lock-path=/var/lock/nginx.lock \ --pid-path=/run/nginx.pid \ --modules-path=/usr/lib/nginx/modules \ --http-client-body-temp-path=/var/lib/nginx/body \ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ --http-proxy-temp-path=/var/lib/nginx/proxy \ --http-scgi-temp-path=/var/lib/nginx/scgi \ --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ --with-threads \ --with-file-aio \ --with-pcre-jit \ --with-http_v2_module \ --with-http_ssl_module \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_slice_module \ --with-http_geoip_module \ --with-http_gunzip_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_gzip_static_module \ --with-http_degradation_module \ --with-http_secure_link_module \ --with-http_stub_status_module \ --with-http_random_index_module \ --with-http_auth_request_module \ --with-stream \ --with-stream_ssl_module \ --with-stream_ssl_preread_module \ --with-stream_realip_module \ --add-module=../ngx_brotli \ --add-module=../ngx_devel_kit \ --add-module=../ngx-fancyindex \ --add-module=../nginx-dav-ext-module \ --add-module=../ngx_http_geoip2_module \ --add-module=../ngx_http_auth_pam_module \ --add-module=../headers-more-nginx-module \ --add-module=../ngx_http_substitutions_filter_module \ --with-zlib=../zlib \ --with-libatomic \ --with-openssl=../openssl-1.1.1d \ --with-openssl-opt='zlib -march=native -ljemalloc -Wl,-flto' \ --with-http_v2_hpack_enc make -j$(nproc --all) sudo objs/nginx -t sudo make install
配置 NGINX Strict SNI 仅可用在 http 块内
1 2 3 4 5 6 # 开启关闭 Strict SNI strict_sni on/off; # 开启关闭无效域名的检查 strict_sni_header on/off; # Strict SNI 最少需要两个 SSL 站点, 无所谓用什么证书. server { listen 443 ssl;}
配置完成后使用 Chrome 直接访问 https://ip-address
如果返回 ERR_SSL_UNRECOGNIZED_NAME_ALERT
则表示配置正确.
Brotli 在 http 块中加入
1 2 3 4 5 6 brotli on; brotli_static on; brotli_min_length 20; brotli_buffers 32 8k; brotli_comp_level 6; brotli_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/rss+xml application/atom+xml image/svg+xml;
TLSv1.3 ssl_protocols 中加入 TLSv1.3 (仅 NGINX 1.13.0 及以上, 低版本用 TLSv1.2 就行)
1 ssl_protocols TLSv1.2 TLSv1.3;
修改 ssl_ciphers ( openssl-patch 参考 )
1 ssl_ciphers [TLS13+AESGCM+AES128|TLS13+AESGCM+AES256|TLS13+CHACHA20]:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES;
Early data (0-RTT) (非必要)
1 2 3 ssl_early_data on; # 另外请添加 Early-Data 头告知后端, 防止重放攻击 proxy_set_header Early-Data $ssl_early_data;
最后 使用 sudo nginx -t
测试一下 确认无问题
浏览器支持 主流浏览器已支持 TLSv1.3 查看 TLSv1.3 支持表: Can I use… 另外 Chrome Canary 77.0.3834.0 已支持 Early-Data (0-RTT), 其他版本不清楚. 可以尝试打开 chrome://flags/#enable-tls13-early-data 看看目前使用的版本是否支持.
SSL Test 结果 SSL Test Result - dev.ssllabs.com
testssl.sh 测试方式
1 2 3 git clone --depth 1 https://github.com/drwetter/testssl.sh.git cd testssl.sh./testssl.sh --full https://your_domain