分类
Web

HSTS引发子域名HTTP强制跳转HTTPS

由于当前这台服务器带宽和流量比较充足,CN2线路质量还算可以,所以打算建一个子域名,专门用来中转下载。

域名使用的是本站的一个二级域名,但是建好后,却发现子域名始终强制跳转到https协议。经过排查和查询资料,发现原来是HSTS(HTTP Strict Transport Security)在作怪。当初在配置本站的ssl证书时,在nginx配置中加了这样一句话:

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

这句话在http响应头中添加一条Strict-Transport-Security信息,意思是告诉浏览器当前网站支持HSTS,即当使用HTTP协议访问本站时,将强制跳转到HTTPS协议。对于chrome浏览器来说,当发现网站支持HSTS时,会把这个域名加入浏览器内部维护的一个支持HSTS的网站列表中。这样,第二次使用HTTP访问这个网站时,将不经过服务器跳转,而是直接通过浏览器进行跳转,跳转的HTTP状态码是307。查询资料得知,这种跳转比301和302跳转更安全,而且由于少了一次服务器请求,还可以减轻服务器的压力。

很明显,在这个配置中includeSubDomains的意思是对子域名也进行跳转,所以才会出现新部署的子域名强制跳转HTTPS的问题。

找到了原因之后,本来想去掉includeSubDomains这一项,但一想,去掉之后,就只有裸域可以使用HSTS跳转了,对于www还是要用301跳转,不如干脆全部使用301好了。所以就禁用掉了主站的HSTS。在add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";前面加#注释掉。

禁用之后,清空浏览器缓存,刷新网站,果然可以了。只有主站使用301跳转HTTPS协议,子站仍然可以使用HTTP协议,问题解决。

补充知识:

chrome浏览器可以通过chrome://net-internals/#hsts页面的Query Expect-CT domain这一项来查询某网站是否被加入了chrome内部的HSTS网站列表。如果想删除,可以通过最下面的Delete domain security policies这一项来删除,输入域名,然后点击Delete按钮就好了。如下图:

chrome浏览器的HSTS配置页面