HTTPS+HTTP/2+HSTS+Perfect-Forward-Secrecy相关配置

一. 简单设置

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

1
2
3
4
5
6
7
listen 443 ssl http2 default_server;
server_name yatesun.com;
index index.html index.htm index.php;
error_page 404 https://yatesun.com;
root /path/to/root;
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;

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

完美前向保密可以确保“即便一个信息受危及,也不会拖累其他信息受危及;并确保没有一个秘密值会导致多个消息受危及。”参考

我们需要生成安全性足够强的Diffie-Hellman参数。一些人认为,4096比特过长了,会给系统的处理器带来不必要的负担,但是就现在的计算能力而言,这似乎值得一试。

1
openssl dhparam -out yate4096.pem 4096

编辑文件perfect-forward-secrecy.conf,参考

1
2
3
4
5
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=31536000; includeSubdomains";

编辑nginx.conf,在http{}最后加入参考

1
include perfect-forward-secrecy.conf;

三、开启HSTS(HTTP Strict Transport Security)

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

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

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

四、添加perload list

其中,在header的Strict-Transport-Security中加入preload后,还是有可能出现第一次无法访问的可能性,其次,像阿里云等国内云服务器对80端口访问的未备案域名查得很严。如果浏览器从未访问过该域名,那么依然有可能在第一次连接的时候就遭到阻断或SSL剥离攻击。
那么我们可以在HSTS preload list中,向Chrome提交域名,未来几个星期,新版Chrome发布的时候,域名将内置在preload list中,服务器将预先知道我的域名是有HTTPS的,会在发送请求前,自动将HTTP转换为HTTPS。
HSTS compatibility matrix中可以看到所有支持这个preload list的浏览器,其中还包括Firefox, Safari, IE 11 and Edge。
目前,yatesun.com已经加入了HSTS preload list,在transport_security_state_static.json的7672行中已经包括了如下数据:

1
{ "name": "yatesun.com", "include_subdomains": true, "mode": "force-https" },

在Google Chrome 50的正式版本中,yatesun.com已内置到浏览器的HSTS domain中,主流浏览器的用户在浏览器中输入http://yatesun.comyatesun.com*.yatesun.com时,将会直接发送HTTPS请求。这时候,即便关闭80端口,依然能访问到网站,从而解决了被阻断或SSL剥离攻击。