nginx最近更新挺频繁的,其中TLS 1.3和是HTTP/2 Server Push是两个比较有意思的特性。前者可以有效的减少握手次数,降低延迟,尤其在恢复会话时候可以将握手开销降低到 0-RTT,后者则可以通过服务器主动推送资源,可以认为是在资源预加载之上更进一步的「资源主动加载」,有效提高网页性能和用户体验。
考虑到平时自己需要比较频繁的测试不同的nginx的新版本,但是又不想破坏机器本地已经安装好的nginx环境,因此我决定制作一个nginx docker镜像。需要说明的是,dockerhub官方是有一个nginx镜像的,但我们希望自己定制nginx版本和需要开启的模块,因此该镜像并不符合需求。
这里以开启TLS 1.3为例制作一个以ubuntu:16.04
为基础镜像的 nginx dockerm镜像。顺便把上次在Ubuntu 14.04开启nginx http2支持的方法中埋的坑填了?
nginx开启TLS 1.3的前置条件
- nginx >= 1.13.0
- openSSL >= 1.1.1 alpha
openSSL版本有几点点需要注意:
- 以前可以使用分支tls1.3-draft-18编译支持TLS 1.3,
但是现在已经merge到1.1.1版本中了,因此,这里不再推荐使用. 使用openSSL 1.1.1编译nginx会触发nginx的一个config bug:tls1.3-draft-18
编译nginxundefined reference to 'pthread_atfork'
, 解决办法可以参见这里以及nginx mailing list, 这里暂时回退到使用tls1.3-draft-18. - 不要尝试使用tls1.3-draft-19编译nginx, 使用Chrome 64测试无法在nginx 1.13.9上成功开启TLS 1.3, 应该跟Chrome对draft版本的支持有关系。
- 2018-03-14更新:升级到Chrome 65以后,发现默认支持为TLS 1.3 Draft 23, 后面顺带连通config bug一起解决了再更新。
- openSSL目前最新版本是OpenSSL_1_1_1-pre2, 还不是stable版本,因此,不要在生产环境中使用。
Dockerfile
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 |
FROM ubuntu:16.04 LABEL maintainer="liudanking@gmail.com" RUN apt-get update # dependency RUN set -x \ && apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev unzip git -y RUN apt-get install wget # module nginx-ct RUN set -x \ && wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.3.2.zip \ && unzip nginx-ct.zip # module ngx_brotli RUN set -x \ && git clone https://github.com/google/ngx_brotli.git \ && cd ngx_brotli \ && git submodule update --init # openssl 1.3 RUN set -x \ && git clone -b 'OpenSSL_1_1_1-pre2' --single-branch --depth 1 https://github.com/openssl/openssl.git openssl #&& git clone -b tls1.3-draft-18 --single-branch https://github.com/openssl/openssl.git openssl # build and install nginx RUN set -x \ && wget -c https://nginx.org/download/nginx-1.13.9.tar.gz \ && tar zxf nginx-1.13.9.tar.gz \ && cd nginx-1.13.9 \ && ./configure --add-module=../ngx_brotli --add-module=../nginx-ct-1.3.2 --with-openssl=../openssl --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module \ && make \ && make install CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] |
Nginx 开启 TLS1.3
一个完整的配置模板参考如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
server { listen 443 ssl http2; server_name localhost; ssl_certificate /usr/local/nginx/conf/ssl/chained.pem; ssl_certificate_key /usr/local/nginx/conf/ssl/domain.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305-D:ECDHE-RSA-CHACHA20-POLY1305-D:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384; ssl_prefer_server_ciphers on; location / { root html; index index.html index.htm; } } |
主要新增两个修改:
ssl_protocols
添加TLSv1.3
.ssl_ciphers
加入TLS13_
为前缀的密码套件。
完整项目地址:docker-nginx
验证TLS 1.3
- Chrome: 将 chrome://flags/ 中的 Maximum TLS version enabled 改为 Enabled (Draft).
如果你刚刚升级到了Chrome 65,选项中开启TLS1.3有三个选项:Enabled(Experiment 2), Enabled(Draft 22), Enabled (Draft 23). 同时很遗憾的告诉你,本文中使用的是Draft 18编译nginx,因此无法配合Chrome 65无法开启TLS1.3,请下面介绍Firefox的开启方法测试TLS1.3?
- Firefox: 将 about:config 中的 security.tls.version.max 改为 4.
以Chrome 64为例,如果开启成功后Protocol显示TLS 1.3
:
你也可以访问tls.liudanking.com来测试自己的浏览器是否已经成功开启TLS 1.3.