基于 OpenSSL 1.1.1 构建支持 TLS 1.3 的 Nginx 1.15 安装包

前言

UPDATE. 2018.08.31

TLS 的 RFC 已经正式更新,编号为 RFC 8446


注意:TLS 1.3 目前虽已定稿,但仍处于未被正式确立为 Internet standard 的草案标准阶段,其周边软件的支持可能发生快速的改变,本文所描述内容截止至2018年6月7日。

3月21日,TLS 1.3 草案正式定稿,最终版本为 draft28,详情见 Protocol Action: ‘The Transport Layer Security (TLS) Protocol Version 1.3’ to Proposed Standard (draft-ietf-tls-tls13-28.txt)
6月5日,nginx 发布新的主线版本1.15(其实和1.13.12相比几乎没有功能变化,修了一堆 bug)。
吃饱没事想试试 TLS 1.3 加上组内 keyless 项目的后续开发设计工作需要对 TLS 1.3 有一点了解,于是有了本文。

本文的描述基于 Ubuntu 16.04 和 Debian 8,至于 CentOS 可以参照一下去年 nginx 在1.13.0正式引入 TLS 1.3 draft18 支持时的文章 试玩 nginx mainline 1.13 的 TLSv1.3 | 星尘独奏曲

准备工作

目前 openssl 的 github master 分支即为 1.1.1-pre8,根据 TLS1.3 – OpenSSLWiki ,当前版本的 openssl 内建了draft26+ 的支持(注意不同草案版本之间的 TLS 1.3 未必是兼容的),如果要在 pre8 支持到 draft23,需要打一个 patch:https://github.com/hakasenyang/openssl-patch

由于 Debian 的打包策略(能分包就分包),nginx 被 Debian 拆成了一堆包,用起来非常难受,个人一直是使用 nginx.org 源,改包一般也在上游版本的基础上改。

当然,你也可以直接获取最新的 nginx.org 发布的源码,编译 nginx 的二进制后将 objs/nginx 覆盖 /usr/sbin/nginx ,只需要在 configure 时添加 --with-openssl=/path/to/openssl --with-openssl-opt=enable-tls1_3 然后正常 make install即可。

准备依赖并获取源码:

安装包的重构建

deb 构建系统相当复杂,如果要对源码结构进行修改,需要使用 quilt 等工具并生成 patch 记录下来,再严格一点的说,打包是需要 chroot 用“完全干净”的系统来构建的···(参见 Debian new maintainers guide),好在我们这次只需要改构建脚本不需要改 nginx 源码, debian/rules 文件相当于生成构建脚本的入口,编辑 rules 的 config.status.nginx: config.env.nginx部分,添加 CFLAGS 并修改 configure 选项

执行打包: dpkg-buildpackage -us -uc -j32(选项表示不签名代码,不签名 patch,至于并行任务开多少取决于编译机配置)

之所以添加 CFLAGS 是因为遇到了一个上游问题导致的编译报错信息,这一问题我在1.13.12和1.15.0都遇到了,看起来是 nginx.org 的打包脚本和 openssl 的开发分支兼容性有点问题,直接编译 openssl 并没有看到这个报错:

查之,https://github.com/openssl/openssl/issues/5955
openssl 开发者说:“No, we don’t want the missing initializers warning. We take advantage of the C guarantee about zero-init.” 翻译成人话:我们就是不关警告,不服你来写,so,没办法只能自己关了(再暴力一点可以 CFLAGS 添加 -Wno-error把所有 warning 都 disable 掉)

配置、检验、和当前浏览器兼容性

TLS 1.3 的 cipher suite 写法和 TLS 1.2 略有不同,主要原因猜测是 1.3 禁用了大量不安全的协议,如 key exchange 只允许 ECDHE 就不需要写明(和早期使用 RSA key exchange 时类似),因此写法变成形如 TLS_AES_128_GCM_SHA256,openssl 配置中写作 TLS13-AES-128-GCM-SHA256 (注意下划线和短横线的区别····)。

 

当前时间点,Chrome stable 66不支持 draft28(safari 和 firefox 也都不支持),但是 canary 69已经有支持,chrome://flags/#tls13-variant 可以修改浏览器支持的最高 TLS 版本,如果浏览器不支持 draft28,打开基于原版 openssl 编译的 nginx 的网站会无法协商到 TLS 1.3,顺便注意到 cloudflare 的测试页 https://tls13.cloudflare.com/ (丢人,还5xx了)使用 Chrome 66 也能协商到 TLS 1.3,应该是 cloudflare 又又又用了奇怪的 SSL 库,反正他们也不是第一次搞私货。

自从实习时开始了解 HTTPS 相关到现在也两年了,看着 OpenSSL 从1.0到1.1,看着 HTTP/2 从一个刚定稿的标准逐渐普及,也看着 TLS 1.3 从一个虚无缥缈的东西慢慢成型最终定稿,这是一个漫长的过程,期间也看见了腾讯微信基于1.3草案魔改的 mmTLS 这种“抢跑”般的东西的诞生,想必 TLS 1.3 被确立为推荐标准并普及开来也还有至少一年时间,大概这就是互联网曲折发展的冰山一角,感谢 Google、Cloudflare 等公司的“激进”推动新技术的普及,感谢 OpenSSL 等开源项目让新技术变成大众可以简单使用的东西,愿互联网在安全、开放、自由的道路上继续走下去。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.