Tech Ideas

C++,Linux,Algorithm,Crypto,Lisp,etc

Nginx下配置高性能,高安全性的https TLS服务

下文以nginx为例,介绍如何部署一个高性能,高安全性的https服务器。

并附送一个优化出来的openssl编译脚本,可以编译出一个高性能,高安全性的openssl库,您可以直接复制粘贴使用。

此处直接给出实践指导,后续再写文章解释tls协议的这些原理细节。

nginx下https配置的优化点,主要有:

  1. session ticket
  2. session id cache
  3. ocsp stapling
  4. http KeepAlive
  5. ECDHE等ciphersuite优化
  6. openssl 编译优化

一, nginx https的配置

先贴一下nginx配置,如下。

是根据mozilla的权威文档 ,和生成工具(选择 nginx,intermediate ) 生成的配置为基础,加入session ticket等配置的结果

tls_nginx.conf
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
27
28
29
30
31
32
33
34
35
36
37
server {
    listen 443 ssl;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;

    ssl_session_ticket_key /etc/nginx/conf.d/tls_session_ticket.key;
    ssl_session_tickets on;

    keepalive_timeout 75s;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # intermediate configuration. tweak to your needs.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/signed_cert_plus_intermediates;

    resolver 114.114.114.114;

    ....
}

二, 其中的几个配置项

1. /path/to/signed_cert_plus_intermediates

是你的证书链,就是ca签署之后发给你的文件,是一串这样的内容

tls_nginx.conf
1
2
3
4
5
6
7
8
9
10
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
...
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
2. /path/to/private_key

是你的私钥,一定要保密,最好chown+chmod限制只有http server可以读取!内容大致是:

tls_nginx.conf
1
2
3
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
3. /path/to/dhparam.pem

是dhe密钥协商的参数,生成方法:

     openssl  dhparam -out dhparam.pem 2048
4. /etc/nginx/conf.d/tls_session_ticket.key

是用来加解密session ticket的密码文件,这个文件的安全等级应该和私钥一样,最好chmod+chown限制只有http server能读取。 生成方法:

     openssl rand 48 > tls_session_ticket.key

最好定期(比如2天一次)轮换,配置文件里把新的key文件放在最前面,旧的在下面,如下

    ssl_session_ticket_key current.key;
    ssl_session_ticket_key previous.key;
5. ssl_trusted_certificate /path/to/signed_cert_plus_intermediates

ssl_trusted_certificate,是用来验证ocsp响应的各个ca证书+中级证书,和信任的ca根证书列表。当用来验证ocsp响应的时候,应该配置为你的ca根证书+和中级ca证书的列表,此处可以简单和ssl_certificate使用同一个证书列表文件。
其中当需要使用tls的客户端认证的时候(大多数https server都用不到客户端认证),需要指定信任的ca根证书列表文件, 这个文件在centos里面是/etc/ssl/certs/ca-bundle.trust.crt 这个文件。

配置完成之后,使用ssllabs的这个在线检查工具https://www.ssllabs.com/ssltest/analyze.html 做检查,里面提出的警告,都需要改正。

三, openssl编译优化

主流的https server,都是依赖openssl来提供tls协议,openssl本身代码复杂,概念繁多,最近对这方面做了研究,下面是一个深入分析过后的最优化编译配置,可以编译出一个高性能,高安全性的openssl版本,您可以直接复制粘贴使用。

openssl请使用最新的1.0.2a版本,这个版本有intel针对ecdh p256曲线的优化,编译脚本见本文末尾。

编译好之后,需要让nginx使用我们编译的这个openssl库,在centos下,可以用LD_LIBRARY_PATH的办法:

sudo vim /usr/lib/systemd/system/nginx.service

在其中添加一行Environment,如下:

[Service]
...
Environment=LD_LIBRARY_PATH=/usr/local/bin/openssl-1.0.2a_64_build/lib/
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
...

其中的路径,请自行修改。

还需要创建软连接,解决so库版本号的问题,如下

ln -s libcrypto.so.1.0.0 libcrypto.so.10
ln -s libssl.so.1.0.0 libssl.so.10

脚本中包含了一个cloudflare的patch,增加chacha20_poly1305 cipher,使用了这个patch之后,可以使用cloudflare的ciphers配置

File /home/windydays/code_work/blog/source/downloads/code/build_openssl.sh could not be found

Comments