HTTP是明文的超文本传输协议,传输过程中容易被第三方拦截获取并加以利用。因此,HTTPS通过在HTTP下增加SSL层,实现HTTP的安全访问,能够加密浏览器与服务器交流时传输的内容。

根据百度安全指数的统计,百度在2015年3月将搜索服务全站HTTPS化以来,HTTPS正被越来越多的网站和企业使用。但是发现,进行正确的HTTPS配置和安全部署情况并不乐观,安全指数分析了全网13288198个网站,其中有1089693个网站使用了HTTPS,占比8.2%。使用HTTPS的网站中有1080884个网站存在配置或安全问题,占比99.19%。

中国互联网网站HTTPS使用和安全情况:

中国互联网网站HTTPS使用和安全情况-http1

中国互联网网站HTTPS使用和安全情况-http2

基本的SSL配置

一般情况下,使用SSL证书需要配置以下基本配置项

server {
        listen   80;
        #对443端口配置ssl和spdy
        listen 443 ssl spdy;
        #spdy能够以以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。
        server_name www.domain.com; #填写绑定证书的域名
        ssl on;#开启ssl
        ssl_certificate baidu.crt; #ssl公钥
        ssl_certificate_key baidu.key;#ssl私钥
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #只启用 TLS 系列协议
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE:!kEDH;#SSL套件配置,具体因证书而异
        location / {
            root   html; #站点目录
            index  index.html index.htm;
        }
   }

HTTPS优化配置

以上的配置项,只要配置无误,足以实现HTTPS小绿锁。但是很多网站不愿引入HTTPS的原因,除了它的配置麻烦,还有配置HTTPS后的网站访问速度会有少幅降低,但是HTTPS并非不能优化加载速度。

     #配置SSL缓存
ssl_session_cache shared:SSL:20m; #缓存池  缓存大小设置为 20M,大概能放下 80000 个会话
ssl_session_timeout  5m;  #缓存时间
     #启用 OCSP,使浏览器更快的获取证书撤销状态
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/startssl_trust_chain.crt;

HSTS头部署

HTTP严格传输安全(HTTP Strict transport security,HSTS),配置浏览器对整个域名空间使用HTTPS来加密,它具备以下优点:

  1. HSTS可以禁止浏览器使用无效证书(浏览器的默认策略是让用户决定是否放行,而用户往往因为不能区分无效是因为配置问题还是攻击而选择继续访问从而导致遭受网络攻击)

  2. HSTS对以下情况可以仍然保持HTTPS通信:

    用户保存了原始网站的书签

    不安全的Cookie

    HTTPS 剥离攻击

    网站内容混布,但需配合CSP(内容安全策略)

    HSTS头部署

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

只需要一段配置项,就能实现HSTS的头部署。

HSTS的功效,简而言之,它能使 Web 服务器告知浏览器绝不使用 HTTP 访问,在浏览器端自动将所有到该站点的 HTTP 访问替换为 HTTPS 访问。

但是随之带来一个问题,大多数用户,包括浏览器,首次访问网站仍然使用的虽说80端口,也就是这一次的访问,很有可能存在被攻击的可能。

幸运的是,谷歌维护了一个预载入列表给 Chrome 使用,这个列表会硬编码到 Chrome 浏览器中。后来,Firefox、Safari、 IE 11 和 Edge等主流浏览器都采用这个列表吧。

当你满足下面这几种条件,就能申请加入HSTS预载入列表,它会将你的域名内置到新版本的浏览器中,当用户访问HSTS预载入列表中的网站时,会直接使用HTTPS协议而非80协议。

  • 有效的证书;
  • 将所有 HTTP 流量重定向到 HTTPS;
  • 确保所有子域名都启用了 HTTPS,特别是 www 子域;
  • 输出 HSTS 响应头:
    • max-age 至少需要 18 周(10886400 秒);
    • 必须指定 includeSubdomains 参数;
    • 必须指定 preload 参数;

HSTS预载入列表加入地址(自备梯子):

https://hstspreload.appspot.com/

需要注意的是,除非是骨灰级的HTTPS用户,不然没必要加入HSTS预载入列表,因为,加入后很难撤销,你可以要求撤销,但是这个数据重新更新到稳定版的 Chrome 同样需要几个版本的迭代,而别的浏览器是如何处理这个撤销数据的,更是无法保证。

HPKP头部署

互联网的信任机制完全依赖于CA(证书颁发机构)厂商颁发的证书,而任意一个CA厂商都可以签发任意一个域名的证书,导致攻击者可以从CA厂商(可以参考CA厂商入侵史)开始入手。因此需要使用白名单的方式来选择信任的CA,公钥扎钉public key pinning技术的出现,可以允许你强制指定签发证书的CA,只有指定的CA为你的域名签发的证书才能使用。 目前该技术有三种实现方式,DANE(基于DNSSEC)、HTTP公钥扎钉和TACK(证书密钥可信保证),HTTP公钥钉扎是使用最多的。

首先需要使用Shell命令根据已有证书获取两个有效的pin-sha256(需要替换命令的文件名):

从已知的密钥对(*.key)生成:

openssl rsa -in lvtao.net_ssl.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

从已知的证书申请文件(*.csr)生成:

openssl req -in lvtao.net.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

从已知的证书(*.crt)生成:

openssl x509 -in lvtao.net_bundle.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

将证书生成的两个密钥,一个作为默认,另外一个作为备用,写入HPKP头,并配置最大过期时间,就能实现HPKP的头部署。

HTTP Public Key Pinning(HPKP)的格式如下:

Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubdomains][; report-uri="reportURI"]

实际HPKP配置例子:

#HPKP头部署
add_header Public-Key-Pins 'pin-sha256="DbqocEhMLF5ODJNP4WGefWkUwpR3BqKhdCHgjOi0yRs="; pin-sha256="DbqocEhMLF5ODJNP4WGefWkUwpR3BqKhdCHgjOi0yRs="; max-age=2592000; includeSubDomains';

同样只需要一段配置项,就能实现HPKP的头部署。

可通过“百度安全指数”测试网站是否达到HTTPS最佳安全部署实践:

https://bsi.baidu.com/topic/https.html?qq-pf-to=pcqq.group

同时它会尝试寻找你系统中可能存在风险的HTTPS漏洞,并提供完整的修复方案。

资料参考来源:

HTTPS最佳安全部署实践

作为 HTTPS 的骨灰粉,怎么可以不加入 HSTS 预载入列表

HTTPS安全部署:HSTS头部署

Public-Key-Pins:配置 HPKP(Public Key Pinning Extension for HTTP)

HTTPS安全部署:HPKP头部署