关于https的HSTS协议

关于https的HSTS协议

HTTP Strict Transport Security
即 http 严格传输安全

举个例子

大部分网站如果支持 https 协议,一般的访问流程如下

  1. 用户输入 abc.com 后, 默认会以 http 协议访问网站服务器;
  2. 服务器随后响应 http 302, 告诉用户以 https 方式请求;

但因为服务器响应的这个 302 是明文的 http 包;
于是攻击者就可以中途拦截并篡改为 重定向到 恶意网站, 比如 newabc.com 或 abc1.com;
或者是篡改为 http 协议, 造成了用户 ssl 连接失败。

解决办法

服务器和客户端进行一个约定,以后的请求都走 https 加密协议, 不要再发 http 请求;
如果有关于我的 http 路径,请自动转换为 https 后再发起请求;

问题一: 约定如何告知客户端

答: 当客户端成功访问服务器的任意一次请求后, 服务器响应一个报文头,告知此约定;

问题二: 约定是否有有效期

答: 为了避免以后如域名交易或确实需要 http 通信的场景, 约定是需要一个有效期的;
由服务器的响应头内一并告知有效期;

问题三: 用户历史首次访问此服务器,并不知晓此约定,于是发起了http请求;如何避免服务器第一次响应的这个约定和302重定向不被篡改

答: 在用户第一次访问之前就提前告知用户;
办法一: 浏览器内置名单, 即 预载入列表;
服务器提前主动告知浏览器厂家将名单加入列表, 属于硬编码到浏览器中;
缺点是更新记录只能等待浏览器新版本更新;

google 维护了一个"HSTS preload list"的站点域名和子域名, 会分发给主流浏览器
可以向 https://hstspreload.appspot.com 提交申请;

办法二: 在 dns 内添加扩展, 域名解析时就确定此约定;
缺点: 支持度不高

开启 HTST 后的附带效果

原来的 https 证书如果校验错误, 用户可以在浏览器上忽略警告继续访问的。
但既然有约定加深了信任, 则浏览器便不能再忽略后续的证书错误, 以加强防护能力。
避免中间人篡改证书;

遗留问题

如果操作系统的时间被篡改到 约定 时间之后, 下此访问就会是 http 明文请求;
当然这就属于操作系统安全的问题了。


开启方法

简单来说就是,服务器的响应头需要包含 Strict-Transport-Security 字段;

例如:
Strict-Transport-Security: max-age=63072000; includeSubDomains

max-age 的含义是失效时间,此处设置为 2 年, 每次访问都会进行更新时间;

注意: 非加密传输时, hsts 字段无效;

开启效果

  1. 用户首次 http 访问时, 需要使用 302 重定向到 https
  2. 用户访问一次该 https 页面后, 浏览器便存有记录;
  3. 用户之后访问该 http 页面时, 直接在键入 URL 后, 浏览器便自动转为 https, 不再需要服务器再重定向;
    注意: 此时是浏览器内部发生的 307 重定向

web服务器配置开启

nginx

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

apache2

1
2
3
4
LoadModule headers_module modules/mod_headers.so
<VirtualHost xxxxName:443>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
</VirtualHost>

Lighttpd 设置方法

1
2
3
4
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
    setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload")
}
Licensed under CC BY-NC-SA 4.0
转载或引用本文时请遵守许可协议,知会作者并注明出处
不得用于商业用途!
最后更新于 2022-05-03 00:00 UTC