/ 教程  

编译Nginx支持TLS1.3

前言

TLS1.2 发布于 2008 年 8 月,至今正好有 10 年,随着互联网安全越来越受到重视,新协议 TLS1.3 呼之欲出。值得一提的是,从第一份草案编写至今,已经有几年时间了,截止这篇文章编写,已经是第 28 份草案。在最近的 Chrome 版本更新中也逐步对 TLS1.3 进行支持,Chrome 65 开始默认开启 draft 23、Chrome 68 开始支持 draft 28

更新:TLS 1.3 标准已于 2018 年 8 月正式发布为 RFC 8446 ,距 TLS1.2 发布正好 10 周年

TLS1.3 对于 TLS1.2 有重大改写,既提高了安全性又提高了速度,以至于有争议称,应该把它叫做 TLS2.0

关于 TLS1.3 的科普可以看下面的页面

https://wiki.openssl.org/index.php/TLS1.3
https://zhuanlan.zhihu.com/p/28850798

之前我也写过 Nginx 的 https 的配置 https://zhih.me/nginx-http2-https/ ,当时是使用 TLS1.2 的

碰巧前几天发现 .ooo 可以免费用 1 年,就撸了一个 onmp.ooo 来做为我 onmp 项目的页面,把它搭在 4 刀年付的 virmach 上,顺便测试 TLS1.3

安装

我这里用的系统是 Debian 8

安装依赖

$ apt-get install git gcc make build-essential

下载源码

我们把源码全都放在一个地方,方便使用

$ mkdir -p /usr/src
$ cd /usr/src

克隆 OpenSSL

这里用的是 1.1.1 稳定版的源码,你要是想要最新的,可以去掉 -b 参数,之后打补丁的时候,记住补丁也要改成对应的

$ git clone -b OpenSSL_1_1_1-stable https://github.com/openssl/openssl.git openssl

下载 Nginx 1.15.5 的源码

$ wget https://nginx.org/download/nginx-1.15.5.tar.gz
$ tar zxvf ./nginx-1.15.5.tar.gz 

克隆 zlib

开启 gzip 要用到 zlib 库,这里使用的是 Cloudflare 优化的版本,比原版具有更高的压缩性能

$ git clone https://github.com/cloudflare/zlib.git zlib
$ cd zlib
$ make -f Makefile.in distclean

下载 PCRE

nginx rewrite 模块需要 pcre 库

$ cd /usr/src/
$ wget https://ftp.pcre.org/pub/pcre/pcre-8.42.tar.gz
$ tar zxvf ./pcre-8.42.tar.gz

给 OpenSSL 打补丁

补丁来自:https://github.com/hakasenyang/openssl-patch

此补丁的目的是让 OpenSSL 支持 TLS1.3 的 23,26,28 草案,以及 Final 版标准

$ cd /usr/src/
$ git clone https://github.com/hakasenyang/openssl-patch.git
$ cd /usr/src/openssl 
$ patch -p1 < ../openssl-patch/openssl-equal-1.1.1_ciphers.patch
$ patch -p1 < ../openssl-patch/openssl-1.1.1-chacha_draft.patch

给 Nginx 打补丁

补丁来自:https://github.com/kn007/patch

nginx 补丁

  • 添加SPDY支持。
  • 添加HTTP2 HPACK编码支持。
  • 添加动态TLS记录支持。

nginx_auto_using_PRIORITIZE_CHACHA 补丁

  • 支持时使用 SSL_OP_PRIORITIZE_CHACHA
$ cd /usr/src/
$ git clone https://github.com/kn007/patch.git nginx-patch
$ cd /usr/src/nginx-1.15.5
$ patch -p1 < ../nginx-patch/nginx.patch 
$ patch -p1 < ../nginx-patch/nginx_auto_using_PRIORITIZE_CHACHA.patch

其他编译配置

Nginx 默认会以 debug 模式编译,我们需要注释掉 /usr/src/nginx-1.15.5/auto/cc/gccCFLAGS="$CFLAGS -g" 这行,这样可以减少生成文件的大小

编译安装

$ cd /usr/src/nginx-1.15.5
$ ./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--modules-path=/usr/lib/nginx/modules \
--with-compat --with-file-aio --with-threads \
--with-http_v2_module \
--with-http_v2_hpack_enc \
--with-http_spdy_module \
--with-openssl=../openssl --with-http_ssl_module \
--with-pcre=../pcre-8.42 --with-pcre-jit \
--with-zlib=../zlib --with-http_gzip_static_module

$ make 
$ make install

Nginx 的可执行文件安装在 /usr/sbin/ ,Nginx 配置在 /etc/nginx/

配置

Nginx 已经安装上了,现在我们来配置网站,让它跑起来

Nginx 全局配置

把以下内容覆盖填入 /etc/nginx/nginx.conf

worker_processes auto;
pid /var/run/nginx.pid;

error_log  /var/log/nginx/error.log;

events {
  use epoll;
  multi_accept on;
  worker_connections 1024;
}

http {
    charset utf-8;
    include /etc/nginx/mime.types;
    default_type  application/octet-stream;

    access_log  /var/log/nginx/access.log;

    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 60;

    sendfile on;
    sendfile_max_chunk 256k; 
    aio threads;
    directio 512k;
    output_buffers 1 128k;

    gzip on; 
    gzip_vary on;
    gzip_proxied any;
    gzip_min_length 1k;
    gzip_buffers 4 8k;
    gzip_comp_level 2;
    gzip_disable  "msie6";
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;

    include /etc/nginx/vhost/*.conf;
}

Nginx 站点配置

我们已经在全局配置里设置了包含 /etc/nginx/vhost/ 目录下的 conf 文件

$ mkdir -p /etc/nginx/vhost

然后在 /etc/nginx/vhost/ 里创建站点配置,比如我的是 onmp.ooo.conf

server {
  listen 80;
  server_name onmp.ooo;
  root /wwwroot/onmp.ooo;
  location / {
    index  index.html;
  }
}

这样 HTTP 的站点配置就弄好了,不过还站点还没页面,我们把 Nginx 的欢迎也面给放进去

$ mkdir -p /wwwroot/onmp.ooo
$ cp /usr/local/nginx/html/index.html /wwwroot/onmp.ooo/
$ nginx

启动 Nginx 后 HTTP 页面就正常了,打开 onmp.ooo 就能看到 Welcome to nginx!

签发证书

配置 HTTPS 首先要有证书,我这里是使用 acme.sh 自动颁发 Let’s Encrypt 的证书

具体使用教程看我的另一篇教程 使用acme.sh获取免费SSL证书

当然,你要是已经有了 SSL 证书,直接看下面配置文件里证书存放的目录,直接放到里面去就行,其他操作一样的

HTTPS 站点配置

因为我给 OpenSSL 打的是 pre8_ciphers 补丁,所以 ssl_ciphers 配置文件如下,如果你打的是别的补丁,则需要查看 https://github.com/hakasenyang/openssl-patch 给的配置

server {
  listen      80;
  server_name onmp.ooo;
  return 301 https://onmp.ooo$request_uri;
}

server {
  listen 443 ssl http2;
  server_name onmp.ooo;

  root /wwwroot/onmp.ooo;

  ssl_certificate       /etc/nginx/ssl/onmp.ooo.cer;
  ssl_certificate_key   /etc/nginx/ssl/onmp.ooo.key;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers '[TLS13+AESGCM+AES128|TLS13+AESGCM+AES256|TLS13+CHACHA20]:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES';
  ssl_ecdh_curve X25519:P-256:P-384;
  ssl_prefer_server_ciphers on;

  ssl_session_cache shared:SSL:50m;
  ssl_session_timeout 1d;
  ssl_session_tickets on;

  ssl_stapling on;
  ssl_stapling_verify on;

  resolver 119.29.29.29 8.8.8.8 valid=300s;
  resolver_timeout 10s;

  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

  location / {
    index  index.html;
    http2_push /style.css;
  }

  location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico)$ {
    expires 30d;
  }

  location ~ .*\.(js|css)?$ {
    expires 15d;
  }

  location ~ /.git/ {
    deny all;
  }
}

以上就是完整的站点配置文件,覆盖 /etc/nginx/vhost/onmp.ooo.conf 后,使用 nginx -s reload 重载 Nginx 再打开站点就能看到 HTTPS 的页面了

验证

在 Chrome 65 或更新的版本中,打开开发者工具的 Security 菜单,就能在里面看到 站点是否以 TLS1.3 连接

chrome

或者可以到 SSL Server Test:https://www.ssllabs.com/ssltest/index.html 进行测试

ssllabs

我只开启了 TLSv1.2 TLSv1.3 的支持,如果需要,你可以自己增加其他协议的支持

后话

人们的生活已经离不开网络,所以网络安全在现在和未来都至关重要,曾经很多站长都以 HTTPS 影响站点速度为由,又或者说 SSL 证书昂贵,拒绝配 HTTPS,而随着技术的迭代升级,配置 HTTPS+HTTPS2 能提高网站速度,而 SSL 不仅可以免费获取,还可以使用命令自动获取自动更新,在我看来已经没有理由不配置 HTTPS 了,所以希望各位站长,都赶紧上车吧

本文章发表于底噪博客 https://zhih.me , 转载请注明