狐狸的小小窝

我是小狐狸~欢迎来我的小窝!
就是炫 狐狸小窝施工记

Use CECPQ1 On Your Website with Nginx & BoringSSL

Deprecated / 已弃用

In 2016, the experimental use in Chrome ended and it was planned to disable CECPQ1 in a later Chrome update.

CECPQ1的实验已经结束,目前的chrome stable已经移除了对其的支持。


What is CECPQ1

CECPQ1 是谷歌提出的一种“后量子时代”的密钥交换算法。

所谓的后量子时代算法,大意是说该算法难以被将来可能出现的量子计算机轻易破解。
而目前常用的非对称加密/密钥交换算法的安全性大多依赖于大数分解以及逆推椭圆曲线的难度。而这些问题可能对于量子计算机来说可以轻松解决。故而需要一种新的加密原理来对抗量子计算机的威胁。

当然将来能不能制造出大型的量子计算机并破解现有的加密算法依旧是个未知数。不过谷歌在前段时间开始已经在自己的 chrome 以及服务器上启用了该密钥交换算法,使用 Chrome 54+ 访问谷歌的服务,可以看到类似下图的结果:
CECPQ1 on Google

其中的“CECPQ1_ECDSA”即表明了其采用了 CECPQ1 密钥交换 + ECDSA 签名算法。

当然纯粹是好玩,我也装修了一下我的小窝,让它也支持了这种厉害的算法~
CECPQ1 on Noisyfox

不过由于我的证书是 RSA 签名的,故图中采用的是“CECPQ1_RSA”而不是 ECDSA。

如果你也想让自己的网站支持这种算法,那么就跟着狐狸我一步一步来配置你的网站吧~


教程环境

  • Ubuntu 14.04.4 LTS
  • nginx-1.10.1
  • BoringSSL

由于目前仅有 BoringSSL 支持 CECPQ1 算法,故我们需要自行采用 BoringSSL 来编译 nginx。

对于 Debian 用户,以及 Ubuntu 14.04 之前的用户,可以采用BoringNginx项目来一键编译、安装。

对于 Ubuntu 14.04 及以后的用户,由于 Ubuntu 采用了 Systemd 替换了 upstart,故 BoringNginx 脚本会出问题。同时 BoringNginx 要求脚本必须在非 root 用户下执行,这对于大部分习惯用 root 用户来配置服务器的用户来说十分不便,故需采用手动编译、安装。


编译 BoringSSL & Nginx

注:该部分教程参考了 Jerry Qu 《使用 BoringSSL 优化 HTTPS 加密算法选择》一文,在此表示感谢。

首先建立一个文件夹,并下载 Nginx 和 BoringSSL 源码。

Nginx 从 1.7.4 开始支持 BoringSSL,这里我使用的是最新的稳定版 Nginx:

mkdir nginx && cd nginx
wget http://nginx.org/download/nginx-1.10.1.tar.gz
tar xzf nginx-1.10.1.tar.gz

git clone https://boringssl.googlesource.com/boringssl

现在你的 nginx 文件夹里应该会有这两个子目录:

boringssl/
nginx-1.10.1/

接下来还需要做一些准备工作:

# 安装编译 BoringSSL 所需的 Golang 和 cmake
sudo apt-get install golang cmake

# 安装编译 Nginx 所需的工具和依赖库
sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev

# 忽略编译过程中的 Warning(不加这个,编到一半会因为 Warning 太多无法继续)
export CFLAGS="-Wno-error"

随后编译 BoringSSL:

# 进入 BoringSSL 源码根目录
cd boringssl

# 创建 build 目录并编译,完成后回到 BoringSSL 源码根目录
mkdir build && cd build && cmake ../ && make && cd ../

# 创建 .openssl 目录,并将库文件和编译后的文件放进去
mkdir -p .openssl/lib && cd .openssl && ln -s ../include . && cd ../
cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib

cd ../

然后就可以用 BoringSSL 来编译 Nginx 了:

# 进入 Nginx 源码根目录
cd nginx-1.10.1

# 指定使用 BoringSSL 作为 SSL 库
# 这里的参数比原文要多了许多,是为了兼容采用 apt 安装的 Nginx 的配置
./configure --with-openssl=../boringssl \
--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 \
--lock-path=/run/lock/subsys/nginx \
--user=www-data \
--group=www-data \
--with-threads \
--with-file-aio \
--with-ipv6 \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_slice_module \
--with-http_stub_status_module \
--without-select_module \
--without-poll_module \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module

# 修改时间,避免 Nginx 再次编译 BoringSSL
touch ../boringssl/.openssl/include/openssl/ssl.h

然后就可以开始编译 Nginx 了, 直接执行:

make

一切正常的话,即可在 objs 目录里找到编译好的 Nginx。
执行:

cd objs
./nginx -V

应该可以看到类似这样的输出:

nginx version: nginx/1.10.1
built with OpenSSL 1.0.2 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
configure arguments: --with-openssl=../boringssl --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 --lock-path=/run/lock/subsys/nginx --user=www-data --group=www-data --with-threads --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_slice_module --with-http_stub_status_module --without-select_module --without-poll_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module

表明编译成功了。下面我们要将该 Nginx 安装至系统中。


安装 Nginx with BoringSSL

由于配置服务需要一些额外的知识,因此为了简单起见,我采用了 使用 apt 安装原版 Nginx 然后替换可执行文件 的方式来简化安装和服务的配置。这也是为什么在上文中我建议使用和 apt 安装的 Nginx 相仿的配置来编译自己的 Nginx。

首先用 apt 来安装原版 Nginx:

# 从 Ubuntu 16.04 开始系统自带源的 nginx 就是1.10 版本的
apt-get install nginx

或者

# 先添加 Nginx 官方软件源
add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx

然后替换原版 Nginx 为我们自己编译的版本:

# 先停止 Nginx 服务
service nginx stop

# 备份原版可执行文件
cp /usr/sbin/nginx  ./nginx.bak

# 替换 Nginx 可执行文件
cp nginx /usr/sbin/nginx

# 删除 Nginx 默认的 modules, 否则可能启动时报二进制不兼容的错误
rm /etc/nginx/modules-enabled/*

这样一来,就成功的将系统中的 Nginx 替换为我们自己编译的版本,同时又保留了原版的服务控制方式,非常方便。


配置 Cipher Suite

在这里假定你已经知道如何配置 Nginx + SSL 了,如果不会,请百度或者谷歌一下。

为了启用 CECPQ1 算法,需要配置正确的 Cipher Suit:

ssl_ciphers "[CECPQ1-ECDSA-AES256-GCM-SHA384|CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256]:[CECPQ1-RSA-AES256-GCM-SHA384|CECPQ1-RSA-CHACHA20-POLY1305-SHA256]:[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305-SHA256]:[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305-SHA256]:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:RSA-AES128-GCM-SHA256:RSA-AES256-GCM-SHA384:RSA-AES128-SHA:RSA-AES256-SHA:RSA-3DES-EDE-SHA";
ssl_prefer_server_ciphers on;

其中最先出现的几个以“CECPQ1”开头的算法就是本文提到的算法。
关于该 Cipher Suite 的格式和意思,也请参考《使用 BoringSSL 优化 HTTPS 加密算法选择》一文。

同时我们编译出的 Nginx 是支持 HTTP/2 以及 ALPN 的,在你的配置里写上:

listen 443 ssl http2;

即可启用最新最炫酷的 h2 啦!
(当然谷歌又弄了个 QUIC 协议,目前不太容易在 Nginx 上实现,残念。)


 结束

这篇教程到这里就结束啦~如果各位读者老爷发现有什么错误或不当之处,还请回复指正~

也欢迎各位共同探讨相关技术~

5 Comment

发表评论

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

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据