IIS - 开启HSTS让浏览器默认以HTTPS访问(强制跳转HTTPS)
在之前的文章中我介绍了如何通过配置 SSL 证书从而让网站实现 HTTPS 协议(点击查看),还介绍了如何通过 URL 重写实现 HTTP 重定向到 HTTPS 上(点击查看)。经过前面的配置后,不管用户输入的是哪种地址,最终会跳转到 HTTPS 上。
但这样做还是有存在个问题。由于我们采用的是 301/302 跳转方式来实现由 HTTP 到 HTTPS 的跳转,但是这个过程总是会使用到 HTTP ,因此容易发生劫持,受到第三方的攻击,就像下面这张图显示的那样。
为了解决这个问题,就需要用到 HSTS(HTTP 严格安全传输)。
一、HSTS 基本介绍
1,HSTS 简介
- HSTS(HTTP Strict Transport Security)是国际互联网工程组织 IETF 发布的一种互联网安全策略机制。
- 采用 HSTS 策略的网站将保证浏览器始终连接到该网站的 HTTPS 加密版本,不需要用户手动在 URL 地址栏中输入加密地址,从而减少会话劫持风险。
2,HSTS 原理
HSTS 主要是通过服务器发送响应头的方式来控制浏览器操作:
- 当客户端通过 HTTPS 发出请求时,服务器会在返回的 HTTP 响应头中包含 Strict-Transport-Security 字段。
- 浏览器接收到这样的信息之后,在一定期限内对该网站的任何请求都会以 HTTPS 发起,而不会以 HTTP 发起再由服务器重定向到 HTTPS。
3,HSTS 响应头格式
Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]参数说明:
- max-age(单位是秒):用来告诉浏览器在指定时间内,这个网站必须通过 HTTPS 协议来访问。也就是对于这个网站的 HTTP 地址,浏览器需要先在本地替换为 HTTPS 之后再发送请求。
- includeSubDomains(可选参数):如果指定这个参数,表明这个网站所有子域名也必须通过 HTTPS 协议来访问。
- preload(可选参数):一个浏览器内置的使用 HTTPS 的域名列表。
4,浏览器支持情况
(1)桌面浏览器
- Chrome:完美支持
- Firefox:完美支持
- Safari:Safari 7 起开始支持(2013年)
- IE:IE11 起开始支持(包括后面的 Edge)
- Opera:完美支持
(2)移动设备
- iOS:iOS 7.1 起开始支持
- Android:Android 4.4 起开始支持
二、HSTS部署
1,操作步骤
(1)由于 HSTS 策略只能在 HTTPS 响应中进行设置,所以首先我们还是要做个 http 到 https 的重定向。让用户第一次访问的时候会自动跳转到 https 地址上。具体方法参考下方这篇文章:
(2)接着我们要开启 IIS 的 HSTS 功能(以 IIS7 + 为例)。打开网站目录下的 web.config 这个文件,在相应的位置添加上针对 https 响应的 url 重写规则(高亮部分),并保存。
- max-age 我们这里设置为 365 天。
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <defaultDocument> <files> <add value="index.php" /> </files> </defaultDocument> <staticContent> <remove fileExtension=".htm" /> <remove fileExtension=".html" /> <mimeMap fileExtension=".html" mimeType="text/html;charset=utf-8" /> <mimeMap fileExtension=".htm" mimeType="text/html;charset=utf-8" /> <mimeMap fileExtension=".mp4" mimeType="application/octet-stream" /> </staticContent> <rewrite> <rules> <rule name="redirect to HTTPS" enabled="true" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="^OFF$" /> </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> <location path="favicon.ico"> <system.webServer> <staticContent> <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="31.00:00:00" /> </staticContent> </system.webServer> </location> </configuration>
2,测试
(1)我们打开浏览器,输入 www.hangge.com 回车。可以看到首次的 HTTP 请求仍然是通过 301 跳装到 HTTPS 上。
(2)但只要访问过这一次后,以后我们再进行 HTTP 请求,浏览器内部就会直接进行 307 跳转。这说明 HSTS 生效了。
三、HSTS 预载入列表(HSTS Preload List)
虽然 HSTS 可以很好的解决 HTTPS 降级攻击,但是对于 HSTS 生效前的首次 HTTP 请求,依然无法避免被劫持。浏览器厂商们为了解决这个问题,提出了 HSTS Preload List 方案。
1,HSTS Preload List 介绍
- 浏览器内置一份可以定期更新的列表,对于列表中的域名,即使用户之前没有访问过,也会使用 HTTPS 协议。
- 目前这个 Preload List 由 Google Chrome 维护,Chrome、Firefox、Safari、IE 11 和 Microsoft Edge 都在使用。
2,加入条件
如果要想把自己的域名加进这个预载入列表,需要满足以下条件:
(1)提供有效的证书。
(2)将所有 HTTP 流量重定向到 HTTPS。
(3)确保所有子域名都启用了 HTTPS,特别是 www 子域。
(4)输出 HSTS 响应头:
- max-age 至少需要 1 年(31536000 秒)。
- 必须指定 includeSubdomains 参数;
- 必须指定 preload 参数;
- 如果您正在从 HTTPS 站点提供额外的重定向,则该重定向必须仍具有 HSTS 标头(而不是其重定向到的页面)。
3,加入方法
当上面的条件满足后,我们可以通过下面这个地址申请加入预载入列表,或进行状态查询。
注意:
- 即便满足了上述所有条件,也不是一定就能进入 HSTS Preload List。
- 提交的申请并不是自动处理的,人工处理也许需要一周到几周。
- 即便你已经列入到这个列表,但是依旧需要几个月才能逐渐从 Chrome 的 canary 更新通道更新到 dev 、beta 等通道,直到最后的 stable 通道。
4,请确定是否要加入
如果你并不能确定你的网站从此以后一直使用 HTTPS,那还是不要加入的好。因为,加入后很难撤销,你可以要求撤销,但是这个数据重新更新到稳定版的 Chrome 同样需要几个月,而别的浏览器是如何处理这个撤销数据的,则无法保证。
换句话说,只有 HTTPS 骨灰粉才应该考虑加入。