转载自本人博客:https://dev.tail0r.com/ssl-optimization/
如果你配置SSL只是为了网站的网址前有一把锁的标志,那不如直接送你把锁好了。
别想了,这句话不是哪个安全专家说的,是我说的(逃)
今天写一篇文章记录一下自己 SSL 的配置优化过程。以下设置均为 Nginx 的配置。
Forward Secrecy(前向加密)
forward secrecy 也称之为 perfect forward secrecy,或者 PFS。称之为完美远期加密。是在HTTPS基础上进一步保护用户电脑同服务器之间的加密通讯。
其解决的一个安全场景就是,如果服务器同用户间的加密通讯内容被窃听,也被储存下来,这些被加密的内容虽然当时无法被解密,被破解,但是当日后,服务器的SSL密钥被取得后(不管是何种原因被取得密钥),这些过往的内容是可以用这个密钥来解密的。这样虽然时效性可能差些,但是仍然是会有被破解的危险存在。
而采用 完美远期加密 的 SSL 或者 HTTPS 通讯,加密钥匙只是短暂性的,而且不能从服务器的 SSL 密钥中推算出来,这样即使日后 SSL 密钥被第三方取得,过去和未来的 HTTPS 通讯仍然安全,窃听者始终无法破解所窃听的内容(以目前的技术而言)。
目前只有用 ephemeral Diffie-Hellman 的算法才算是完美远期加密。
配置方法
在终端运行(建议把这个 Diffie-Hellman 参数文件和证书放在一起):
openssl dhparam -out dh4096.pem 4096
一些人认为,4096 比特过长了,会给系统的处理器带来不必要的负担;但是就现在的计算能力而言,这似乎值得一试。这个值可以自行更改。建议 2048。
在 Nginx 的配置文件中加入:
ssl_dhparam dh4096.pem;
之后restart (NOT reload) Nginx。
HSTS(HTTP Strict Transport Security,严格传输安全)
HSTS 简单说就是在一定时间内强制客户端使用 HTTPS 访问页面。原理如下:
- 在服务器响应头中添加
Strict-Transport-Security
,可以设置max-age
- 用户访问时,服务器种下这个头
- 下次如果使用 HTTP 访问,只要
max-age
未过期,客户端会进行内部跳转,可以看到 307 Redirect Internel 的响应码(注意是客户端浏览器相应的,这里给服务器省下了一次 302 跳转) - 变成 HTTPS 访问源服务器
这个过程有效避免了中间人对 80 端口的劫持。但是这里存在一个问题:如果用户在劫持状态,并且没有访问过源服务器,那么源服务器是没有办法给客户端种下 Strict-Transport-Security 响应头的(都被中间人挡下来了)。如何解决?请自行谷歌 HSTS preload。
需要注意的是,只有启用 preload 之后才是严格意义上安全的 HTTPS。否则都可能在最薄弱环节被攻破。比如:
- 允许 SSL 连接但不强制从 HTTP 跳转到 HTTPS,用户访问 HTTP 被劫持
- 部署了 HSTS,但用户第一次访问是 HTTP 的,Strict-Transport-Security 的响应头没有作用的机会,还是被劫持
不过,即使你启用了 preload 也不是 100% 高枕无忧了,一旦客户端被恶意软件安装了恶意的根证书,这些措施就都没有用了。所以不要轻易安装根证书,不要随意安装可疑软件(尤其在 Windows 上)。比如,Google 曾在
2015 年报告说 CNNIC (中国互联网络信息中心)签发的一个中级 CA 签发了一个伪造的 Google 证书,从而导致 Google 和 Mozilla 在其产品中取消了对 CNNIC 后继签发的证书信任。