在Nginx启用Chacha20和ALPN

Note: 从OpenSSL 1.1.0开始,chacha20与ALPN默认被支持,因此不再需要按照本文另行操作,除非你使用的版本低于Ubuntu 18.04 或其他发行版对应的在18年左右之前发布的版本。

博客启用HTTPS也应该有一年多了,最近闲的无聊的时候F12发现自己网站的HTTP2没了(博客服务器一直是用的Nginx的mainline版本),寻思咋回事儿的时候发现谷歌从Chrome 51开始强行要求ALPN(Application Layer Protocol Negotiation,应用层协议协商)才能开HTTP2。然而搜遍谷歌给出的结果是OpenSSL 1.0.2才支持ALPN,这就搞得Server端用Ubuntu 14.04的我比较尴尬了(1.0.1版)。

当时我心里第一反应是WQNMLGB的OpenSSL……CHACHA20在实验版本才有就算了,ALPN支持也这么坑。。。。。(只是吐槽,不带恶意,毕竟这东西在开源世界还是帮了不少忙的。)

然后思来想去,反正14.04上的OpenSSL已经这个鬼样子了,我还是自己动手编译支持吧,顺便把Chacha20丢进去。

那么问题来了:ALPN和CHACHA20好处都有啥?说对了就给他

首先,上面提到了,ALPN对后面版本的Chrome来说是开启HTTP2协议的必要条件。HTTP2对比Http 1.1做出了比较多的改动,比如Server Push,服务端根据客户端的请求推测他后面会请求的资源,然后一并推送给客户端,这样一来可以减少客户端请求次数。其次,头部压缩减少了传输体积,优化传输效率。

其次,对于CHACHA20加密,CHACHA20是一种流加密方式,并且旨在提供256位高强度的加密,对移动设备的兼容性更好(毕竟PC上有AES-NI指令集可以处理AES加密,然而手机上面并没有)。之前有一篇测试曾对比过三星移动设备使用AES和CHACHA20加密的速度的对比,在同样大小的密文解密情况下,CHACHA20的效率是AES的4倍左右。

所以说了这么多,开工开工。

(对于使用Ubuntu/Debian的同学,如果不想看下文的话,可以参考这份脚本—》链接

由于OpenSSL目前生产环境还不支持CHACHA20,因此使用LibreSSL替代。

先下载LibreSSL,这里使用2.4.1版本,然后make:

wget http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.4.1.tar.gz -O libressl.tar.gz
tar zxf libressl.tar.gz
cd libressl*

./configure --prefix=/usr LDFLAGS=-lrt
make

mkdir -p .openssl/lib
cp crypto/.libs/libcrypto.a ssl/.libs/libssl.a .openssl/lib
cd .openssl && ln -s ../include ./
cd lib && strip -g libssl.a && strip -g libcrypto.a
cd ../../../

至于为啥不install,毕竟你系统里面还有其他需求OpenSSL的,万一install完出问题那就不好说了。

然后下载Nginx,这里我使用1.10.1的源代码。configure的配置来自于Nginx官方源的配置,但是去掉了GeoIP和Perl支持。

在配置之前,为了保证configure的完整性,避免报错,你可能需要安装下面几个东西:

apt-get update
apt-get install libxslt1-dev libxml2-dev zlib1g-dev libpcre3-dev libgd-dev -y --force-yes

然后configure

tar zxf nginx.tar.gz 

cd nginx*

./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' --with-openssl=《LibreSSL的绝对路径,比如/opt/nginx/libressl-2.4.1》 --with-ld-opt="-lrt"

touch下Header File,避免被Nginx 重新编译,然后make

touch /opt/nginx/libressl-2.4.1/.openssl/include/openssl/ssl.h
make

接下来,是make install 还是继续其他的操作,取决在你自己了。对于之前已经安装过的同学,执行make install的话会替换掉之前你安装的版本。因此这步请注意下选择。

我这里是make install替换原版本。

然后,如果你是全新安装,你需要把这份文件丢到/etc/init.d里面,然后执行下面的语句,以确保Nginx开机自动运行

sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

wget https://raw.githubusercontent.com/sunflyer/EasyUbuntu/master/nginx.init -O /etc/init.d/nginx

sudo chmod +x /etc/init.d/nginx #安装启动脚本

sudo update-rc.d -f nginx defaults #设置开机自启动

最后运行 nginx -V看看?

nginx version: nginx/1.10.1
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
built with LibreSSL 2.4.1
TLS SNI support enabled

修改你的ssl_cipher配置为下述:(这个是CloudFlare的SSL配置)

EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5:!MEDIUM:!LOW

然后测试下连接。

chacha chacha2

至此大功告成。

One thought on “在Nginx启用Chacha20和ALPN

发表回复

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