黑阈服务器,实际上有两台。国内的 AWS,使用 Amazon Linux 2,基于 CentOS 7;另外一台在国外,直接就是 CentOS 7。
2017 年 4 月发布的 Nginx 1.13.0 起支持 TLSv1.3,但是,当然需要底层 OpenSSL 支持。后期,也支持谷歌的 BoringSSL。
要支持 TLSv1.3 其实比较简单,只需要升级 OpenSSL 即可。在 CentOS 8 中,OpenSSL 已经升级到 1.1.1。如果直接使用 rpmbuild 来构建,由于 ABI 兼容性问题,无法直接使用。但是非常友好的是,nginx 可以直接使用参数 --with-openssl
来指定 openssl 路径。于是,修改 nginx.spec
,加上 --with-openssl
参数,打包,安装,开启支持,终于 ssllabs.com 显示支持 TLSv1.3 了。
但是,问题来了,没有动态为 Android 设备优化 cipher 啊。比如在没有 AES-NI 支持的情况下,ChaCha20 会友好一些;但是如果有 AES-NI 支持,直接使用 AES-128-GCM 就会快很多。这点,可以找个 Android 低端测试分别访问 https://www.google.cn 然后检查 TLS 属性即可检查。
一翻搜索之后,发现 BorringSSL 在 2014 年 6 月起,引入 Equal preference cipher groups 概念。之前的话,Cipher 优先级只能是一个,现在可以同时有多个,就能达到如果设备支持 AES-NI,则使用 AES-GCM,如果不支持,使用 ChaCha20。
好的,开干,使用 BoringSSL 编译。咦,怎么无法链接?一看,没开 -fPIC
选项呢。(中间当然还有略微复杂的,如何跳过 tests 编译。)好,开干,终于一切都支持了。
咦,怎么不支持 OCSP stapling?呃,BoringSSL 本身就不支持这个东西。那,还是切回 OpenSSL 好了。
在 OpenSSL 下,怎么才能达到对移动设备不支持 AES-NI 的情况下,直接使用 ChaCha20,而如果支持,则使用 AES-GCM 呢?一翻搜索,OpenSSL Issue 541 提到这个,而在 Issue 4436,则加进了这个支持,使用新的属性 SSL_OP_PRIORITIZE_CHACHA
。但是,Nginx 并不使用这个值。所以,只需要改动 Nginx,设置这个值即可。
又是一翻编译,终于达成目标。
咦,怎么 BoringSSL 下,浏览器使用 AES-128-GCM,而 OpenSSL 下,浏览器使用 AES-256-GCM 呢?又是一翻搜索,发现无法指定 TLSv1.3 的 Cipher 顺弃,而这个,呃,在 OpenSSL 中是写死的。所以,继续改吧。
最终,子非的改动清单如下:
openssl 中,在
include/openssl/ssl.h
中,把TLS_DEFAULT_CIPHERSUITES
定义中的TLS_AES_256_GCM_SHA384
与TLS_AES_128_GCM_SHA256
顺序对调。nginx.spec
中,去掉对 openssl 的依赖(毕竟真的不再依赖系统 OpenSSL),同时,编译参数加入--with-openssl
路径,以及设置SSL_OP_PRIORITIZE_CHACHA
属性(位于src/event/ngx_event_openssl.c
中)。
欢迎使用低端设备上的浏览器,高端设备上的浏览器,以及电脑版浏览器,当然还有 ssllabs.com 测试黑阈服务器 jianyv.com
。