用HSTS进一步增强网站安全性

由于 Let's Encrypt 等免费证书的存在,各位站长都可以很容易的加固自己的网站。然而 HTTPS 不是万能药,并不是加入 HTTPS 支持就万事大吉了。

譬如说,就算你加入了 HTTPS 支持,要如何让用户使用 HTTPS 连接呢?包括笔者在内,估计没有人会手工输入那个奇怪的 https:// 协议头,而浏览器总是会把无协议头的网址默认当做 http 协议。于是,当用户输入了你网址的域名回车的时候,用户的电脑就和你的服务器建立了非安全的连接。有人说他们已经配置服务器当用户使用 HTTP 协议连接时重定向至 HTTPS,但这样并不完全解决问题:就算返回的是一个 301 重定向,未加密就是未加密,中间人可以为所欲为,比如读取用户上传的请求头,篡改服务器返回的 301 地址到别的网站等。

必须由一种机制强制用户使用 HTTPS 协议连接服务器,这就是 HSTS 的作用。

什么是 HSTS

HTTP严格传输安全(英语:HTTP Strict Transport Security,缩写:HSTS)是一套由互联网工程任务组发布的互联网安全策略机制。网站可以选择使用 HSTS 策略,来让浏览器强制使用 HTTPS 与网站进行通信,以减少会话劫持风险。

对于启用 HSTS 的网站,浏览器会做到以下几点:

  1. 强制使用 HTTPS 协议连接。对于不安全的访问协议,浏览器会在内部将其重定向至 HTTPS 协议。包括并不限于

    1. 用户没有输入协议头
    2. 用户输入了 http:// 协议头
  2. 当浏览器发现服务器证书错误,强制阻止用户建立连接

如何启用 HSTS

添加返回头:

Strict-Transport-Security: max-age=<过期时间>; includeSubDomains

其中 includeSubDomains 是可选的,表示给当前域名下的子域名也启用 HSTS 支持。

值得注意的是:客户端必须与服务器建立安全连接时(当使用 HTTPS 协议连接并且无证书错误) Strict-Transport-Security 头才会被浏览器认可。这是因为非安全连接下中间人可以添加或者删除这个头,在建立真正安全的连接时一切都是不可信的。

如果要提前关闭 HSTS,可以使用类似清除 Cookie 的做法:

Strict-Transport-Security: max-age=0; includeSubDomains

同样需要建立安全连接才会生效。

预加载 HSTS

前面提到,HSTS 是服务器返回给浏览器的一个返回头,并且只会在建立安全连接时才会生效。那么就引出了另一个问题:如果用户从未访问过你的网站,而在第一次访问就被劫持了怎么办?

所以问题在于,除非客户端与服务器建立过连接,否则浏览器不知道服务器是否支持 HTTPS 请求,更不知道该站点是否想要启用 HSTS。谷歌想出了一个办法:把想启用 HSTS 的所有站点的域名预先写进浏览器代码不就好了。这就是 Preloading Strict Transport Security

谷歌维护了一个名为 HSTS Preload List Submission网站,专门用于申请让浏览器给各站点内置开启 HSTS 支持。申请预加载 HSTS 需要站点满足更为严格的条件:

  1. 提供一个有效的证书。
  2. 如果你的站点同时启用了 HTTP 支持(监听 80 端口),必须把 HTTP 重定向到同一域名的 HTTPS 网址(例如将 http://domain.com 重定向到 https://www.domain.com 是不可以的)
  3. 所有子域名也必须启用 HTTPS 连接
  4. 返回一个满足以下条件的 HSTS 头

    1. max-age 至少需要 18 个月(大于等于 10886400 秒)
    2. 必须指定 includeSubDomains
    3. 必须指定 preload(preload 是谷歌给 HSTS 头添加的扩展值)
    4. 如果这个域名会重定向到另一个域名,前面的域名也必须添加 HSTS 头(例如 https://domain.com 重定向到 https://www.domain.com,前者需要添加 HSTS 头)

满足这些条件后,你就可以在其官方网站上给你的域名申请预加载 HSTS。如果申请通过,等待一段时间后你的域名就会被 Hard code 到浏览器内部了。不仅是 Chrome,IE、Edge、Firefox 都会采用。可以用这个网站检测你域名是否支持预加载 HSTS。

PS:EOI 的顶级域名 eoitek.com 同样支持预加载 HSTS,不来转转么?

你可能感兴趣的:(hsts,安全,https,nginx)