最近两年,越来越多的网站开始使用 HTTPS 来替代 HTTP ,升级 HTTPS 已经是大势所趋。由于 HTTP 协议是不加密传输的,也就是用户跟你的网站之间传递数据是直接裸奔,有可能在途中被截获,破解传递的真实内容,所以使用不加密的 HTTP 的网站是不安全的。所以, Google 的 Chrome 浏览器将在 2017 年 1 月开始,标记使用不加密的 HTTP 协议的网站为不安全。

让网站支持 HTTPS 并不难,甚至可以免费做到,但想要部署的安全通常是不容易的。虽然很多站点都逐步升级了 HTTPS,但是有些仅仅是简单配置支持,只是表面安全,实际可能存在缺陷或者隐藏漏洞。今天总结一下 HTTPS 配置的最佳实践的一些建议。

banner-bg-evssl

HTTPS 证书选择

HTTPS 证书如果按照类型来分,可以分为域名验证证书(DV)、组织验证证书(OV)、扩展验证证书(EV),不同类型申请时需要验证的内容不同,花费的时间也不同。这里不做具体普及。

证书有免费和付费两种,这里主要说免费的,常用免费证书主要有:

  • 与百度云、腾讯云、阿里云合作的赛门铁克签署的证书,一年免费,申请和使用都很简单,一年到期重新申请即可。
  • 现在很火的 Let’s Encrypt,今年它还支持了通配符证书申请,可以说是非常亲民。但是缺点就是证书有效期只有90天,当然这个可以通过技术实现自动续期。对于我们这些小站,可以说是很不错的选择了。

HTTPS 最佳配置实践的一些建议

OpenSSL版本

首先要了解自己服务器的OpenSSL版本号,如果你是用的nginx可以通过nginx -V查看版本号,也可以通过openssl version查看(适用于非自己通过openssl源码编译的)。

推荐的OpenSSL版本如下:

  1. OpenSSL 1.0.2用户需更新到1.0.2h 以上。
  2. OpenSSL 1.0.1用户需更新到1.0.1t 以上。
  3. OpenSSL官方已停止对 0.9.8和 1.0.0 两个版本的升级维护,请使用这两个版本的用户将其升级至1.0.2h版本以上。

OpenSSL 1.0.1以下不支持tls1.2 升级前请做好测试

使用安全的协议

SSL/TLS 系列中有五种协议:SSL v2,SSL v3,TLS v1.0,TLS v1.1和TLS v1.2。

  • SSL v2 是不安全的,不能使用。此协议版本非常糟糕,即使它们位于完全不同的服务器(DROWN 攻击)上也可以用来攻击具有相同名称的RSA 密钥和站点。
  • 当与 HTTP(POODLE 攻击)一起使用时,SSL v3 是不安全的,当与其他协议一起使用时,SSL v3 是弱的。它也是过时的,不应该被使用。
  • TLS v1.0 也是不应该使用的传统协议,但在实践中通常仍然是必需的。其主要弱点(BEAST)在现代浏览器中得到缓解,但其他问题仍然存在。
  • TLS v1.1 和 v1.2 都没有已知的安全问题,只有 v1.2 提供了现代的加密算法。

注意: 2017年6月30号PCI安全标准委员会官方发表博文将于2018年6月30号(最晚)禁用早期SSL/TLS,并实施更安全的加密协议(TLS v1.1或更高版本,强烈建议使用TLS v1.2)以满足PCI数据安全标准的要求,从而保护支付数据。

所以,目前来看TLS v1.2应该作为您的主要协议,现在TLS1.3已经出来了,未来主流应该是TLS v1.2 + TLS v1.3。

nginx配置代码如下:

ssl_protocols   TLSv1.1 TLSv1.2 TLSv1.3;

使用 HSTS (HTTP Strict Transport Security)

指示浏览器只使用 HTTPS 连接到目标服务器。这可以防止一些潜在的中间人攻击,包括 SSL 剥离,会话 cookie 窃取(如果没有被 适当保护)。如果遇到任何与证书相关的错误,它还可以阻止浏览器连接到网站。当浏览器访问一个设置相应 HTTP header 的 HTTPS 网站时,HSTS 将被激活。

HSTS 有一个固定期限,由 max-age 字段值控制。这个值可以是静态的,也可以是相对于将来某个特定日期的,你可以设置成 SSL 证书的过期时间。

建议设置 HSTS header 长的生命周期,最好是半年及以上(即不能小于15552000)。

nginx配置如下:

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

选择安全的加密套件

为了安全通信,您必须首先确定您正在与所需方(而不是通过将窃听的其他人)直接沟通并安全地交换数据。在 SSL 和 TLS 中,密码套件定义了如何进行安全通信。

有几个过时的加密原语必须避免:

  • 匿名 Diffie-Hellman(ADH)套件不提供身份验证。
  • NULL 密码套件不提供加密。
  • 导出密码套件在连接中协商时不安全,但也可以针对更喜欢更强大的套件(FREAK攻击)的服务器使用。
  • 弱密码(通常为 40 和 56 位)的套件使用可以轻松破坏的加密。
  • RC4 是不安全的。
  • 3DES 缓慢而虚弱。

推荐的nginx配置:

ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256::!MD5;

更多安全加固策略

请参考文章HTTPS 安全最佳实践(二)之安全加固

nginx配置Demo

server {
    listen       443 ssl http2; # 开启http2
    server_name  www.test.com; # 站点域名
    root         /path_to_webroot; # 网站目录
    index        index.html;

    ssl on;
    ssl_certificate "/path_tocert/server.crt";
    ssl_certificate_key "/path_tocert/server.key";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256::!MD5;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

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

    error_page 404 /404.html;

}
server{
    listen 80;
    server_name www.test.com;
    rewrite ^(.*)$  https://$server_name$1 permanent;
}

HTTPS 安全监测工具

参考资料