距离TLS v1.2推出已过十年,今年8月1.3标准总算定稿,著名CDN厂商CloudFlare专门写有一篇博客做了介绍,可以有个整体的了解。主流代理服务器Nginx也及时跟上,在月底的时候正式发布了1.15.3版本,其中一项更新便是通过Google推出的OpenSSL分支BoringSSL增加了对TLS v1.3的支持1

在主流Linux发行版上是没有现成的BoringSSL包的,想要使用的话需要自行编译,这里以Ubuntu 16.04为例进行说明。

TLDR

完整编译脚本在 https://gist.github.com/jostyee/09ed7e99f8298dd253e15aa867447c9e

编译BoringSSL

准备编译环境

Ubuntu 16.04包管理器里的Go版本还在1.6,这里我们按照官方提供的方案更换到1.10。

1
2
3
4
5
$ sudo apt install -y build-essential uuid-dev dpkg-dev unzip cmake make
$ sudo add-apt-repository ppa:gophers/archive
$ sudo apt update
$ sudo apt install golang-1.10-go
$ export PATH=/usr/lib/go-1.10/bin:$PATH

卸载旧Nginx

1
2
$ sudo apt remove nginx
$ sudo apt autoremove

编译BoringSSL

 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
$ git clone https://boringssl.googlesource.com/boringssl
$ cd boringssl
$ mkdir build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/yee/boringssl/build
$ make
Scanning dependencies of target boringssl_gtest
[  1%] Building CXX object CMakeFiles/boringssl_gtest.dir/third_party/googletest/src/gtest-all.cc.o
...
Scanning dependencies of target ssl_test
[ 87%] Building CXX object ssl/CMakeFiles/ssl_test.dir/span_test.cc.o
[ 88%] Building CXX object ssl/CMakeFiles/ssl_test.dir/ssl_test.cc.o
c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-5/README.Bugs> for instructions.
ssl/CMakeFiles/ssl_test.dir/build.make:86: recipe for target 'ssl/CMakeFiles/ssl_test.dir/ssl_test.cc.o' failed
make[2]: *** [ssl/CMakeFiles/ssl_test.dir/ssl_test.cc.o] Error 4
CMakeFiles/Makefile2:2587: recipe for target 'ssl/CMakeFiles/ssl_test.dir/all' failed
make[1]: *** [ssl/CMakeFiles/ssl_test.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

因为是在512M小内存VPS上运行的,这里内存不足导致编译出错了,需要临时开启虚拟内存凑数。

1
2
3
4
5
6
7
8
9
$ sudo dd if=/dev/zero of=/var/swap.img bs=1024k count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 2.88782 s, 363 MB/s
$ sudo mkswap /var/swap.img
Setting up swapspace version 1, size = 1000 MiB (1048571904 bytes)
no label, UUID=51a23032-3012-41c3-87a3-d6f2ade5d0f9
$ sudo swapon /var/swap.img
swapon: /var/swap.img: insecure permissions 0644, 0600 suggested.

再次编译顺利通过

1
2
3
4
5
6
Scanning dependencies of target cfb
[ 99%] Building C object decrepit/cfb/CMakeFiles/cfb.dir/cfb.c.o
[ 99%] Built target cfb
Scanning dependencies of target des_decrepit
[ 99%] Building C object decrepit/des/CMakeFiles/des_decrepit.dir/cfb64ede.c.o
[100%] Built target decrepit_test

然后创建.openssl目录供Nginx使用,并且将BoringSSL的include目录软链过来,另外还需要拷贝加密厍文件到.openssl/lib

1
2
3
4
5
cd ..
mkdir -p .openssl/lib && cd .openssl && ln -s ../include .
cd ..
cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib
cd ..

最后运行下swapoff关闭刚才分配的虚拟内存。

编译Nginx

 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
$ curl http://nginx.org/download/nginx-1.15.3.tar.gz | tar -xz
$ cd nginx-1.15.3/
$ sudo ./configure --prefix=/usr/share/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
        --pid-path=/run/nginx.pid \
        --with-threads \
        --with-file-aio \
        --without-select_module \
        --without-poll_module \
        --without-mail_pop3_module \
        --without-mail_imap_module \
        --without-mail_smtp_module \
        --with-http_ssl_module \
        --with-http_v2_module \
        --with-http_realip_module \
        --with-http_gunzip_module \
        --with-http_gzip_static_module \
        --with-http_stub_status_module \
        --with-openssl=../boringssl

$ touch ../boringssl/.openssl/include/openssl/ssl.h # 不做这一步可能会在编译时出Error 127错误
$ sudo make && sudo make install

确认编译结果

1
2
3
4
5
6
$ sudo nginx -V
nginx version: nginx/1.15.3
built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10)
built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --with-threads --with-file-aio --without-select_module --without-poll_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --with-openssl=../boringssl

看到(compatible; BoringSSL) (running with BoringSSL)说明OK了。

修改Nginx配置文件

打开对TLS v1.3的支持设置,主要是下面两行:

1
2
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers '[TLS13-AES-128-GCM-SHA256|TLS13-CHACHA20-POLY1305-SHA256] TLS13-AES-256-GCM-SHA384 [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] ECDHE-RSA-AES256-GCM-SHA384';

测试

1
$ sudo /usr/sbin/nginx -t -c /etc/nginx/nginx.conf

如果没有问题就能成功跑起来了。CloudFlare用户使用浏览器请求[example.com]/cdn-cgi/trace,返回结果中应该显示http=h2

Troubleshooting

  • Nginx启动报错 [warn] the "ssl" directive is deprecated, use the "listen ... ssl" directive instead

    Nginx配置中ssl on在1.15版本中已经被废弃,删除重启即可

  • Nginx启动error日志出现 2018/08/29 21:40:41 [warn] 11787#11787: "ssl_stapling" ignored, not supported

    很不幸,Google在移植开发BoringSSL的过程中删减了很多他们自身不使用的特性,比如OCSP Stapling,只能从设置里将以下相关项去除

    1
    2
    
    ssl_stapling on;
    ssl_stapling_verify on;
    

参考

History

VersionActionTime
1.0Initial commitSep 6, 2018

  1. Feature: now TLSv1.3 can be used with BoringSSL. ↩︎