2017 年 7 月 23 日 修改自:Yate Sun 孙亚特

一. 简单设置

可以在 nginx.conf 中加入以下代码开启 HTTP/2,同时设置常用的域名证书为 default_server,这样设置的目的是防止客户端在不支持 SNI 的情况下,直接使用默认证书的时候,nginx 依然能够通过 HTTPS 解析到你的服务器。防止由于多证书存在于同一台服务器而导致未知错误的可能性。开启 HTTPS 时,需同时指出 openssl 的密钥及其公钥,作为普通用户,千万不能像 12306 一样,自己给自己签发 HTTPS 证书。需要使用经过可信的第三方 CA 签发的证书,其中也有很多免费的。

listen 443 ssl http2 default_server;
server_name www.airscr.com;
index index.html index.htm index.php;
error_page 404  https://www.airscr.com;
root  /path/to/root;
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;

二. 完美前向保密(Perfect Forward Secrecy)

  1. 完美前向保密可以确保“即便一个信息受危及,也不会拖累其他信息受危及;并确保没有一个秘密值会导致多个消息受危及。” 参考
  2. 我们需要生成安全性足够强的 Diffie-Hellman 参数。一些人认为,4096比特过长了(下面的例子是 2048 比特的),会给系统的处理器带来不必要的负担;但是就现在的计算能力而言,这似乎值得一试。
openssl dhparam -out dhparam.pem 2048

  1. 编辑文件 perfect-forward-secrecy.conf 参考
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;
ssl_dhparam yate4096.pem;
add_header Strict-Transport-Security "max-age=15552000";

  1. 编辑 nginx.conf, 在 http{} 最后加入 参考
include perfect-forward-secrecy.conf;

三、开启 HSTS (HTTP Strict Transport Security)

在 nginx 配置文件中,加入下面一行,便可以告知浏览器,我要强制客户端使用 HTTPS 访问页面。其中 max-age 为有效时间,只要这个时间未过期,浏览器请求时,将会 307 Redirect Internel 到 HTTPS 页面。与 301 和 302 重定向不同,307 不允许跳过「证书错误」进行访问。

add_header Strict-Transport-Security "max-age=15552000";

有意思的是,开启了 HSTS 以后,在 SSL LABS 上便能得到A+了,而仅仅开启FS时,在 SSL LABS 上只可以得到 A。

四、添加 perload list

其中,在 header 的 Strict-Transport-Security中加入 preload 后,还是有可能出现第一次无法访问的可能性,其次,像阿里云等国内云服务器对 80 端口访问的未备案域名查得很严。如果浏览器从未访问过该域名,那么依然有可能在第一次连接的时候就遭到阻断或SSL剥离攻击。

add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; preload";
​

那么我们可以在 HSTS preload list 中,向 Chrome 提交域名,未来几个星期,新版 Chrome 发布的时候,域名将内置在preload list中,服务器将预先知道我的域名是有 HTTPS 的,会在发送请求前,自动将 HTTP 转换为 HTTPS。

HSTS compatibility matrix 中可以看到所有支持这个 preload list 的浏览器,其中还包括 Firefox, Safari, IE 11 和 Edge。