HSTS概览
本文详细介绍了HSTS的概念、作用、工作原理、以及如何设置HSTS。同时,结合HTTPS和HSTS安全机制,提高数据通信的安全。
HTTP与HSTS
用户在访问某个HTTPS网站时,往往在浏览器中直接输入网站域名,如:www.example.com
,而不是输入完整的URL,如:https://www.example.com
,但浏览器依然能正确的使用HTTPS发起请求。这种客户体验多亏了服务器和浏览器之间的互相协作。
那这一切是否就是安全的呢? 其实不然。由于在建立起HTTPS连接之前存在一次明文的HTTP请求和重定向,使攻击者可以以中间人的方式劫持这次请求,从而进行后续的攻击(如:窃听数据、篡改请求和响应、跳转到钓鱼网站等)。
那么如何避免HTTPS建立连接之前的那次明文的HTTP请求和重定向,从而防止被中间人攻击,规避风险呢?有没有可能当浏览器发起HTTP请求时,浏览器将其转换为HTTPS请求,直接略过上述的HTTP请求和重定向呢?这就需要启用HTTP Strict Transport Security(HSTS)机制了。
什么是HSTS
HTTP Strict Transport Security(HSTS)是一种Web安全策略机制(web security policy mechanism)。
HSTS最早于2015年被纳入到ThoughtWorks技术雷达,并且在2016年的最新一期技术雷达里,它直接从**评估(Trial)阶段进入到采用(Adopt)**阶段,这意味着ThoughtWorks强烈主张业界积极采用这项安全防御措施,并已经将其应用于自己的项目。
HSTS最为核心的是HTTP响应头(HTTP Response Header),其格式为:
Strict-Transport-Security: max-age=XXX; includeSubDomains; preload
这表明,在接下来的一段时间内,浏览器只要向当前域名或其子域名发送HTTP请求,其通信必须采用HTTPS来发起连接。其中:
- max-age是必填参数,是一个以秒为单位的数值,它代表着HSTS响应头的过期时间,通常设置为一年,即31536000秒。
- includeSubDomains是可选参数,如果包含它,则意味着当前域名及其子域名均开启HSTS保护。
- preload是可选参数,只有当你申请将自己的域名加入到浏览器内置列表时,才需要使用到它。关于浏览器内置列表,参阅本文下方更多信息章节。
HSTS作用
HSTS的作用是强制客户端(如:浏览器)使用HTTPS与服务器创建连接,用户无需手动在URL地址栏中输入HTTPS,浏览器始终保持HTTPS链接访问网页。
同时,在启用HSTS安全机制后,它可以做到:
- 浏览器强制拒绝不安全的链接
在没有HSTS保护下,当浏览器发现当前连接不安全时,浏览器会警告用户,但是却又允许用户继续不安全的访问。但在启用HSTS保护下,当浏览器发现当前连接不安全时,除了会警告用户外,它还将彻底阻止用户继续访问此网站。如下图所示:
- 设置HSTS Preload List ,全面防御攻击
当浏览器没有当前网站的HSTS信息,或者是第一次访问当前网站时,依然需要一次明文HTTP请求和重定向才能切换到HTTPS,以及刷新HSTS信息,而这一瞬间可能给攻击者留下可乘之机。针对此安全隐患,HSTS也有应对办法。那就是在浏览器里内置一个列表,只要是在这个列表里的域名,无论何时、何种情况,浏览器都只使用HTTPS发起连接。这个列表由Google Chromium维护,FireFox、Safari、Internet Explorer等主流浏览器均在使用。
HSTS工作原理
其工作原理主要是通过服务器,发送响应头的方式来控制浏览器操作:
- 客户端(如:浏览器)通过HTTPS发出请求时,服务器会在返回的HTTP响应头中包含
Strict-Transport-Security
字段。 - 浏览器接收到这样的信息之后,在一定期限内,对当前域名下的任何请求都只能以HTTPS发起访问请求,而不会以HTTP发起再由服务器重定向到HTTPS。
详细的工作流程图如下所示:
注意:更多有关max-age参数的有效期问题,参阅本文下方更多信息章节。
如何配置HSTS
你可以根据自身实际情况,选择在哪里设置HSTS,例如:反向代理服务器、应用服务器、应用程序框架,以及应用程序中自定义Header 。常见的是在Nginx、Apache、IIS下的配置文件中配置。
-
在Nginx服务器中添加下列指令进行配置:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
注意:在生产环境下使用HSTS机制时,建议先将max-age参数的值设置小一些(如:若干分钟),检查HSTS是否能正常工作,网站能否正常访问,然后再逐步将时间延长(如:一周/一个月),并在这个时间范围内继续检查HSTS是否正常工作,最后才改到一年。这是因为当网站证书有问题时,一旦浏览器接收到HSTS Header ,那么用户将在有HSTS效期间内,直到证书错误被修复,或者用户主动清除浏览器缓存为止,都无法访问到你的网站。
-
Apache下的配置:
- 在
httpd.conf
文件中加载headers模块:LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
- 在
VirtualHost 0.0.0.0:443
中添加下面代码行:Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
- 重启Apache服务器。
- 在
-
IIS下的配置:
在web.config
文件中添加下列命令行进行配置:<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="HTTP to HTTPS redirect" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="off" ignoreCase="true" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule> </rules> <outboundRules> <rule name="Add Strict-Transport-Security when HTTPS" enabled="true"> <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" /> <conditions> <add input="{HTTPS}" pattern="on" ignoreCase="true" /> </conditions> <action type="Rewrite" value="max-age=31536000" /> </rule> </outboundRules> </rewrite> </system.webServer> </configuration>
更多信息
Max-age参数有效期如何计算,到期后怎么办?
因为HSTS Header存在于每个响应中,随着用户和网站的交互,这个有效时间时刻都在刷新。再加上有效期通常都被设置成一年,所以只要用户的前后两次请求之间的时间间隔没有超过一年,则基本上不会出现安全风险。更何况,就算超过了有效期,但是只要用户和网站再进行一次新的交互,用户的浏览器又将开启有效期为一年的HSTS保护。
如何申请将域名添加到浏览器内置列表中?
当你的网站满足以下条件后,可以在HSTS Preload List 官网上提交申请:
- 拥有一个有效的证书
- 在同一台主机上提供重定向响应,且接收重定向过来的HTTPS请求
- 所有子域名均使用HTTPS
- 在根域名的HTTP响应头中,加入HSTS Header,并满足:
- 有效期不得少于18周(10886400秒)
- 必须包含includeSubDomains参数
- 必须包含preload参数
如何查询域名已经成功加入到浏览器内置列表中?
从提交申请到完成审核,成功加入到内置列表 ,需要等待几天到几周不等的时间。可通过官网,或者在Chrome地址栏里输入chrome://net-internals/#hsts
查询状态。
支持HSTS机制的浏览器有哪些?
目前,支持HSTS的浏览器清单如下所示:
- Google Chrome 4.0.211.0及以上版本
- Firefox 4及以上版本
- Opera 12及以上版本
- Safari OS X Mavericks及以上版本
- Internet Explorer (Windows 10 预览版)及以上版本