HSTS Preloading – 让你的域名「嵌入」主流浏览器,一同发行

有点标题党的味道,但确实有这种效果,比如我现在用的这个域名sorz.org目前可以在 ChromiumFirefox 的源代码中找到。理论上,它也会出现在 Safari 和新版的 IE 里[1]

当然「听起来好像很厉害」只是个副作用,其目的还是为了确保安全。

TL;DR – 如果你的网站也支持全站 HTTPS,可以考虑配妥 HSTS 后在此提交申请

(2015-11 更新)现在 Qualys 的 SSL Server Test 也会显示相关信息啦:
ssllabs-result-with-hsts

一切为了安全

现代浏览器在安全上真是做足了功夫。

HTTPS

SSL 协议在早在上世纪末就已提出[2]。目前广泛使用的 TLS 1.2 是它的改良版,在 2008 年正式发布[3]。他们可以在很大程度上,保证数据在 浏览器 与 网站服务器 间传输时的安全,保证他们不在传输过程中被监听或者修改。

但目前仍有大量网站是不提供 HTTPS (SSL/TLS)连接的 [4],或是只在部分页面提供。浏览器不知道哪些网站使用 HTTPS,用户也不一定知道。现在通常的做法是,浏览器先默认使用 HTTP 连接,如果服务器要求安全连接,再通过这个 HTTP 连接返回给浏览器一个「重定向」,让浏览器转而使用 HTTPS。

这样有一个问题,因为 HTTP 是不安全的,这个「重定向」就有可能被攻击者吞掉。然后攻击者一方面冒充服务器,使用 HTTP 与浏览器进行通讯;另一方面冒充浏览器,与服务器使用 HTTPS 建立连接。这就是所谓的 SSLstrip 攻击。

HSTS

为了解决这个问题,HTTP Strict Transport Security (HSTS, HTTP 严格传输安全) 孕育而出。这个 2012 年才发布的新玩意儿其实很简单,就是制订了一种方法,让服务器能够告诉浏览器:「我支持 HTTPS,今后使用它连接我」。

具体来说,它在增加了一个 HTTP 头 Strict-Transport-Security,里面指明网站至少支持 HTTPS 多长时间、是否包含子域名等。浏览器会缓存这条规则,今后即使是用户或者网页指定了http://,浏览器也会无视掉它,强制使用安全连接。

Preload List

但这无法阻止首次访问网站时受攻击(此时还没有 HSTS 规则的缓存呢),浏览器们并不满足于此,推出了 HSTS Prelod List(预加载列表?)。顾名思义,就是将使用 HSTS 的网站域名直接内置(hard-coded)进浏览器。只要是出现在列表中的域名,就统统使用 HTTPS 连接,让攻击者无缝可钻,安全性大提升。

部署

唔.. 介绍了这么多背景,进入正题,怎么做?首先当然是要做好全站的 HTTPS 支持,这个就略过不提了。然后是部署 HSTS。最后是提交申请,进入浏览器的 Preload List。

UPDATE 20150904: 如果你在使用 CloudFlare,进入 Dashborad,在 Crypto 找到并开启 HSTS 就可以了。

HSTS

添加 HSTS 支持其实很简单,修改一下 Web 服务器的配置,增加一个 HTTP 头就行[5]。随手 Google 到了一篇文章,大家可以参考一下。

举个例子,这个域名目前使用的是:

Strict-Transport-Security: max-age=15552000; includeSubDomains; preload

max-age=15552000告诉浏览器缓存这条规则 180 天;includeSubDomains对子域名也使用相同的规则;preload允许将这条规则内置进浏览器。

部署完毕后,可以用这个网站测试一下。如果存在其他安全相关问题,也会被检测出来。

Preload List

Duang! 现在可以提交申请啦(自备梯子):
https://hstspreload.appspot.com/

这个网站似乎是 Google 牵头做的,但不仅 Chrome,Firefox、Safari 和 IE 也都会包含这个列表。所以只要在这里提交一次就行啦。

提交前注意几点:

  • 需在全站启用 HTTPS(包括子域名),同时重定向所有 HTTP 流量至 HTTPS;
  • max-age必须大于 10886400 秒(18 周);
  • includeSubdomainspreload
  • 不能反悔的哦。

另外,他说这个申请是要经过人工审核的(not automatic nor assured … undergo a manual review),所以可能要花上几周的时间。具体到并入个浏览器代码中,可能需要更长的时间。

老实说,当初我看见「人工审核」便没报太大希望,提交后就忘了这事了。近几天才偶然发现已经申请通过并入了浏览器,才知道其实并没有什么门槛(虽然目前的列表只有两千行左右)。所以我也不知道我从申请到通过花了多久…

附注

[1] 会并入随 Windows 10 发布的那个 IE 上,MSDN 是这样说的。所以我是不是还可以更标题党一点,比如「与 Windows 一同发布」或者「嵌入 Windows」,233。
[2] Wikipedia – Transport Layer Security
[3] RFC 5246 The Transport Layer Security (TLS) Version 1.2
[4] 65% of top 1,000,000 websites by 2014. Source.
[5] 其实要完全符合标准的话,还要复杂一些。如果你也在使用 nginx,可以参考这条评论进行设置,会更规范一些。

HSTS Preloading – 让你的域名「嵌入」主流浏览器,一同发行》上有34条评论

      1. ghost

        现在我的站有个很蛋疼的问题就是有一个Simple Local Avatars插件完全不知道怎么改,勉强读了遍源代码好像是遍历id然后函数返回路径的,连http的影子都看不到,php又是小白层面的,不知道大神有没有点办法Orz
        另外在火狐的安全日志里我读到个很有趣的东西:

        We limit the list to hosts that send a large max-age under the assumption that these sites will not revert to non-HSTS status. However, this may become necessary. Suppose ownership of a domain on the preload list is transferred and the new owner decides to no longer use HSTS. The HSTS spec allows the site to send a header with the directive “max-age=0″. This indicates that HSTS should not be enforced for that host, and the browser would honor this. The preload list must replicate this behavior.
        To accomplish this task, we introduce the concept of “knockout” entries in our HSTS implementation. When the browser receives an HSTS header with “max-age=0″, a knockout entry is stored that overrides the corresponding entry in the preload list. The knockout entry essentially says, “We have no HSTS information regarding this host.” As a result, the browser behaves as if the host were not on the preload list.

        这样的话如果我是中间人那伪造个时间为0的HSTS,列表什么的不是都没用了么

        回复
        1. Null 文章作者

          抱歉我也不会 PHP.. 不过如果用了 HSTS 的话,所有 HTTP 请求都会自动被转为 HTTPS,所以 HTML 里的链接是 HTTP 这个并无大碍..

          那个,你要成为中间人不容易啊,他们的 knockout 想必也是必须要检查证书链甚至 Public key pins 的吧…

    1. Null 文章作者

      呃我看了一下,PC 上 Firefox 和 Chrome 虽然都有 mixed content 的警告,不过实际上都是用 HTTPS 请求的..
      Chrome 显示一个 304 Internal Redirect 和一个 HTTPS 请求,Firefox 直接显示 HTTPS 请求…
      挺奇怪的,想来不应该提示 mixed content 了啊,不知道是出于什么特别的考虑还是一个 bug。

      回复
  1. ghost

    呃……我PC上的Firefox请求显示的还真是http……
    https://dn-ghostblog-img.qbox.me/img/http-avatar.png
    但是抓包又看不出哪里有问题,不知道是我学艺不精还是真的只是浏览器抽风……
    https://dn-ghostblog-img.qbox.me/file/http-or-https.pcapng
    (应该不会暴露什么密码cookie之类的吧www)
    都是重度折腾患者么(逃
    ——————————————————————————————————————-
    还有就是问一下你的站开HSTS之后怎么防D的,以前我都是DNSPod那里预设www的NS记录到加速乐,必要的时候暂停www的A记录然后解析到加速乐那边的,但是HSTS之后就不能这么干了,证书不匹配还不能用http不能添加例外Orz

    回复
      1. ghost

        还真有能支持https的CDN啊#(惊哭)
        那是不是得把证书私钥什么的全部上交到CDN,不然怎么通过校验的……
        ———————————————————————————————
        网络那里连个图片请求都没找到OTZ

        回复
        1. ZE3kr

          我现在用 UPYUN 的二级域名的 CDN,就能免费 HTTPS,不要证书(是共享证书)。CloudFlare CDN 的 Fixable SSL 能让不支持 HTTPS 的服务支持 HTTPS,就是中国速度有些慢,KeyCDN 的话能用共享证书,也能自定义证书(就需要上传证书了)。

          我的网站也搞了 HSTS,那个绿色小锁真的很高大上。

  2. ghost

    唔……突然想到一个更蛋疼的事情就是如果有人买到了一个已经加入HSTS Preload,为了让这个域名能正常使用还得一直挂着https的服务然后把HTST头的时间弄成0来广播取消,不然一旦有新访客就会看到一个大大安全警告的还不能忽略……
    (不对啊一直挂着https还取消什么劲wwww)

    回复
      1. ghost

        ……看到了,但是因为嵌套层数限制并不能回复orz
        感觉把自己私钥传到别人服务器上不是很靠谱,要是出了点xx事可是赖不掉的…电子签名的不可抵赖性啊=.=!

        回复
  3. ZE3kr

    传证书并没有什么。而且只要你绑定的是别人的IP或者是CNAME,他们依然可以通过文件验证的方式给申请到一个证书。建议给CDN单独一个域名,单独的证书最安全。

    回复
    1. ghost

      呃,提交一条评论就看见了,果然是缓存坑
      Only whole domains can be submitted because the interaction of cookies, HSTS and user behaviour is complex and we believe that only accepting whole domains is simple enough to have clear security semantics and usually the correct choice for sites.

      If you are serving an additional redirect from your HTTPS site, that redirect must still have the HSTS header (not the page it redirects to).
      (博主有空的话帮忙加个块引用标签,俺有点强迫症

      回复
  4. ghost

    又一次缓存毁一生……收到邮件看不到人*2
    没记错的话要求是一级域名也带HSTS响应,响应包含includeSubDomains和preload。早就加入了来着…

    回复
    1. ZE3kr

      哈哈,缓存这个问题我也注意到了,你就直接在URL后面加“?” 然后加一段随机码,就是无缓存了(显然站长的缓存机制并不忽略query……

      回复
  5. Pingback引用通告: 全站开启 HSTS! – HKK's Diary

发表评论

电子邮件地址不会被公开。 必填项已用*标注