Nginx配置HTTPS和HSTS

HTTPs是运行在SSL/TLS之上的HTTP协议,具有内容防篡改、重放等特点,让你的网站更加安全,避免中间人攻击——比如某些运营商的网页劫持。

签发证书

让你的网站支持HTTPS访问,首先必须找机构签发一个有效证书。常见的免费证书有Let’s encrypt以及Symantec的免费证书。

以Symantec的免费证书为例,在阿里云上有专门的免费证书签发服务。如果链接不可用,先登录阿里云,找到SSL 证书(应用安全)(可以在产品与服务中搜索),选择购买证书,找到Symantec的免费型DV SSL(如果找不到多切换几下标签就可以看到),然后点击购买。之后回到上级页面补全域名信息。

接下来的步骤需要证明域名的所有人是你,有两种方式:

  • 下载fileauth.txt文件到指定网站路径
  • 修改DNS的TXT记录

随便选择一种方式验证成功之后,就可以下载到压缩的证书文件,解压之后包括一个pem文件和一个key文件。

Nginx配置

注意域名和证书是一一对应的,否则HTTPS不可能配置成功。找到nginx.conf中对应域名的配置, 参照如下示例进行配置:

server {
listen 443;
server_name yourdomain;
ssl on;
root html;
index index.html index.htm;
ssl_certificate cert/215054962890537.pem;
ssl_certificate_key cert/215054962890537.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}

端口改为监听443,设置 ssl on,正确配置ssl_certificatessl_certificate_key的文件路径;然后重启Nginx,这时候应该就OK了。

如果想让http自动跳转https, 可以加一段301永久重定向:

server {
listen 80;
server_name yourdomain;
return 301 https://$server_name$request_uri;
}

这种配置在一般情况已经足够安全,但还不是足够安全,因为http到https的这一个重定向仍然可以被中间人劫持,如图所示:

为了解决这种问题,HSTS应运而生。HSTS的全称是HTTP Strict-Transport-Security,它是一个Web安全策略机制(web security policy mechanism)。

HSTS最早于2015年被纳入到ThoughtWorks技术雷达,并且在2016年的最新一期技术雷达里,它直接从“评估(Trial)”阶段进入到了“采用(Adopt)”阶段,这意味着ThoughtWorks强烈主张业界积极采用这项安全防御措施,并且ThoughtWorks已经将其应用于自己的项目。

HSTS最为核心的是一个HTTP响应头(HTTP Response Header)。正是它可以让浏览器得知,在接下来的一段时间内,当前域名只能通过HTTPS进行访问,并且在浏览器发现当前连接不安全的情况下,强制拒绝用户的后续访问要求。

HSTS的原理很简单,就是告诉浏览器强制使用HTTPS,而不是请求到服务端再重定向,示例如下:

配置语法如下:

Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload

其中max-age代表过期时间,单位是秒,includeSubDomains代表是否包含子域名,preload代表是否预加载一批安全域名。只要是在有效期内,浏览器都将直接强制性的发起HTTPS请求。

具体行为表现为307内部跳转,在Response Headers中的Location返回https域名:

细心的用户会发现这里还是要请求一次服务端,否则浏览器也不会自动启动HSTS配置。没错,这里仍然存在一定的安全风险,HSTS本身给的解决方案是在浏览器中内置一个HSTS的域名列表,这些域名浏览器会自动强制HTTPS访问。

而在Nginx中,配置HSTS非常简单,只需在server段中加上一行:

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

有两点需要注意:

  • 配置测试时尽量配置较短的max-age,因为如果HTTPS配置失败,而HSTS配置成功,那么在max-age配置时间范围内你将不能访问网站(除非在浏览器端删除指定的HSTS,以chrome为例,访问 chrome://net-internals/#hsts 找到 Delete domain security policies 可以删除HSTS域名)
  • 如果只是对顶级域名配置HSTS,那么就要去掉includeSubdomains这项内容,否则所有二级域名也会强制访问HTTPS

参考文章

https://www.jianshu.com/p/caa80c7ad45c