Nginx配置HTTPS与HSTS
2017-09-14 16:28:51 +08 字数:1852 标签: Nginx HTTPS以下以一个不存在的域名example.qidong.name为例,展示在Nginx中配置HTTPS与HSTS的过程。 本文代码追求可读性,减少一些无关的配置,仅供参考。
当然,首先假设你已经有了私钥(example.key)与证书(example.pem)文件。
Nginx配置SSL/TLS ¶
如果了解原理,理解思路就会很简单。
从HTTP到HTTPS,逻辑上相当于在应用层和传输层之间,额外增加一个安全层。 对一个Web应用、网站来说,从HTTP到HTTPS,它本身可以不做任何修改、甚至可以完全不知情。
HTTPS的默认端口是443,给Nginx新增一个443端口的监听。
并且,在其中开启ssl on
,添加相应配置。
最后,仍然用root
或proxy_pass
等方式,把请求交给真正需要响应的地方。
server {
listen 443;
listen [::]:443;
server_name example.qidong.name;
ssl on;
ssl_certificate /etc/nginx/ssl/example.pem;
ssl_certificate_key /etc/nginx/ssl/example.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
location / {
proxy_pass http://localhost:12345;
}
}
新增上面的配置后,Nginx支持https://example.qidong.name/
形式的访问。
并且最终通过反向代理,把网络请求交给服务器里12345
端口。
两个listen
,是同时对IPv4和IPv6进行监听,统一支持。
不过,这时如果访问http://example.qidong.name/
,仍然是允许的。
如果要确保安全性,限定必须使用HTTPS来访问,有两种办法。
一是完全不提供http://example.qidong.name/
的访问,不在80端口监听、响应example.qidong.name。
这种方法用得比较少,因为考虑到旧的链接、浏览器自动补全HTTP等因素,会导致网页不可达,令用户困惑。
所以,通常用的是第二种方案。 利用重定向,让HTTP的链接自动跳转为HTTPS。
HTTP重定向到HTTPS ¶
server {
listen 80;
listen [::]:80;
server_name example.qidong.name;
return 301 https://$server_name$request_uri;
}
添加、或修改以上代码,即可让用户访问http://example.qidong.name/
时,
自动跳转到https://example.qidong.name/
。
有些情况下,SSL/TLS这一层,是包在Nginx外的,
比如,某些非常自动化处理HTTPS配置与证书的商业环境。
或者,也可以理解成外面还有一层Nginx,自动做了前面ssl on
的处理,但不能手动改配置。
在这些环境下,Nginx对外提供的80端口,就必须兼备跳转到HTTPS和提供内容两个功能。
以下代码,通过http_x_forwarded_proto
进行识别,分别处理。
关键在if
那三行。
server {
listen 80;
listen [::]:80;
server_name example.qidong.name;
if ($http_x_forwarded_proto = 'http') {
return 301 https://$host$request_uri;
}
location / {
proxy_pass http://localhost:12345;
}
}
HSTS ¶
SSL剥离攻击是中间人攻击的一种,由Moxie Marlinspike于2009年发明。 他在当年的黑帽大会上发表的题为《New Tricks For Defeating SSL In Practice》的演讲中将这种攻击方式公开。 SSL剥离的实施方法是阻止浏览器与服务器创建HTTPS连接。
HTTP重定向到HTTPS,仍然是有安全隐患的,那就是SSL剥离攻击。 因此而发展起来的应对,则是HSTS。
在Nginx上,要添加HSTS的支持非常简单。
只需要在443的监听中,添加一行add_header
。
其中,max-age=31536000
,就是有效期一年。
server {
listen 443;
server_name example.qidong.name;
ssl on;
...
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
...
}
}
一些优化 ¶
keepalive_timeout 70;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
这些都是关于HTTPS,Nginx提供的优化手段。 关于cache、timeout,大概是以空间换时间、用缓存降流量,尽量避免多次请求、反复验证。 而stapling,则是优化证书验证的有效方法。
浏览器在建立HTTPS链接时,会先在线验证CA证书的有效性,阻塞SSL/TLS的握手,拖慢整体响应速度。 这就是OCSP,全称Online Certificate Status Protocol,译为在线证书状态协议。 而OCSP stapling,就是让服务端来进行OCSP,并且缓存证书颁发机构的响应,让浏览器跳过在线检查。 本来一次HTTPS请求,正常是浏览器、服务器、证书颁发机构的三角关系,优化后,大部分情况下变成了浏览器和服务器的双边关系。
相比HTTP,HTTPS对服务器的性能开销剧增。 但如果做好一些优化,可以缓解不少。
另外,还有安全方面的优化。 SSL协议总体不安全,全面弃用。 而TLS协议的安全性,则依赖于ciphers。
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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
这是孤见过最长的ciphers列表,应该能更安全一些吧。 虽然看不懂,但是好厉害的样子!
SSL测试 ¶
一切配置完毕后,可以去ssllabs。 输入域名,一次点击,可以进行多方面的测试。