HSTS VS 301 redirect

之前基于nginx为网站配置了HTTPS服务,配置过程中涉及到两个知识点:

  • 301 永久重定向
  • HTST(HTTP Transport Security Protocol)

本文主要是通过梳理一下相关概念,理清这两种配置的目的。

HTTPS

HTTPS,也称作HTTP over TLS,TLS的前身是SSL。HTTPS 相比 HTTP 提供了数据完整性、
数据隐私性和身份认证的功能。

SSL通信过程

  • 客户端发起一个HTTPS请求,提供客户端支持的加密算法和一个客户端随机数 client_random 给服务器
  • 服务器返回给客户端配置好公钥的证书和服务器随机数 server_random
  • 客户端验证公钥证书、比如是否在有效期内、域名是否匹配等;如果证书有效,客户端使用服务器提供的公钥加密加密随机数 premaster secret,发送给服务器
  • 服务器使用自己的私钥解密 premaster secret
  • 客户端和服务器将前面阶段的三个随机数,使用协商好的算法进行加密生成 master secret,后面双方通信使用这个对称密钥进行加密;

在nginx中的配置方法

  • 申请证书
  • 在nginx.conf中配置
      server {
          listen 443;
          server_name www.example.com; #填写绑定证书的域名
          ssl on;
          ssl_certificate /etc/nginx/sslconfig/1_www.example.com_bundle.crt;
          ssl_certificate_key /etc/nginx/sslconfig/2_www.example.com.key;
          ssl_session_timeout 5m;
          ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
          ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
          ssl_prefer_server_ciphers on;
          location / {
              root   html; #站点目录
              index  index.html index.htm;
              # proxy_pass http://$server_name:8920;
      }
    

中间人攻击(MitM)

中间人攻击(Man-in-the-middle attack,缩写:MITM)是指攻击者与通讯的两端分别建立独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制并进行数据篡改和嗅探。

  • 代理服务器(mitmproxy):代理服务器 在HTTP和HTTPS通信中担任中间人的角色,在和客户端通信时它伪装成服务器,在和服务器通信时伪装成客户端,对两边的通信内容进行解码。代理服务器会生成伪造证书欺骗客户端,要使客户端信任伪造证书而不发出警告,需要在客户端手动将代理服务器注册为受信任的 CA。
  • SSL剥离(SSLsplit):SSL剥离中,攻击者 SSLStrip 也是担任中间人的角色,中间人和服务器之间维持HTTPS连接,而和客户端维持HTTP连接,也就是将 HTTPS 降级为 HTTP。由于 HTTP 是明文传输的,因此攻击者可以窃取通信内容。
  • 会话劫持(Session Hijacking):攻击者通过窃取或预测有效的会话令牌来破坏会话令牌,以获得对Web服务器的未授权访问。常用的窃取Cookie/会话令牌的方法有会话嗅探和跨站点脚本攻击等。
  • 防御:对于实际生活中的信件沟通和线上的信息交流来说,中间人攻击都是很难防范的,一些小建议:
    • 不要忽视浏览器弹出的证书警告!你可能访问的是钓鱼网站或者假冒的服务器
    • 公共网络环境下(例如公共WiFi),没有HTTPS加密的敏感网站不要随便登录,一般不可信
    • 在任何网站上登录自己的账号前确保网址是走的HTTPS加密协议

HSTS

HSTS,即HTTP Strict-Transport-Security。 当站点通过 HTTPS 运行的时候,服务器通过返回一个响应头部 Strict-Transport-Security ,强制浏览器以后使用 HTTPS 进行通信。

Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload

一个网站接受一个 HTTP 的请求,然后跳转到 HTTPS ,用户可能在开始跳转前,通过没有加密的方式和服务器对话,这样存在中间人攻击潜在威胁,跳转过程可能被恶意网站利用来直接接触用户信息,而不是原来的加密信息。
HTST 是在初次通过访问 HTTPS 连接并返回安全头之后,浏览器记录下这些信息。有效期内,当浏览器再次试图通过 HTTP 与服务器建立连接只会返回307 Temporary Redirect ,浏览器禁止加载 HTTP 信息,并将连接重定向到 HTTPS 。一个测试的结果如下:

在nginx中配置响应信息

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

浏览器返回结果
307
200
注意 HTST 是通过 HTTPS 响应头设置的,如果使用 HTTP 则会被忽略。一种解决的策略是 preload HTST。HSTS预加载是把你的网站和或域名放在一个被认可的hsts列表上,这个列表实际上是内置在浏览器中的。Google提供了这个列表服务,并由Chrome、Firefox、Opera、Safari、IE11和Edge使用,可以将你的站点提交到官方的HSTS预加载列表。

301 redirect

HTTP 301 永久重定向说明请求的资源已经被移动到了由 Location 头部指定的url上,是固定的不会再改变,搜索引擎会根据该响应修正,在 SEO 中301跳转对网站的权重会产生影响。
我们注意到,我们已经在nginx中已经配置了return 301 https://$server_name$request_uri,将HTTP请求重定向到HTTPS。但是,在前面的浏览器测试结果中,通过HTTP访问并没有显示301永久重定向,而是307临时重定向。实际上,301 仍然是发生的,301是服务器层面上的重定向,而307是浏览器层面上的重定向。我们通过 httpstatus 进行测试,可以看到直观的结果:

我们已经说明了HSTS和301的作用,但是我们可能仍然有些困惑:

  • 为什么已经使用 301重定向,还要使用 HSTS ?
  • 为什么大多数网站使用301重定向,而不用预加载HSTS替代?

区别与联系

  • HSTS覆盖域名,而301 redirect针对特定的URL Path;
  • HSTS设计的意义是为了解决安全问题,而301更多是为了解决重定向问题,后来被广泛用在从 HTTP 升级到 HTTPS 的过程中,并对网站搜索权重造成影响;
  • HSTS起作用是在至少访问过一次HTTPS且证书验证成功的情况下,在安全性要求较高的情况下我们强制使用 HTTPS,这需要进行预加载或者强制重定向;如果攻击者一直阻止网站建立HTTPS连接,HTST将不起作用;
  • 目前大多数网站使用HSTS时是结合301 redirect使用的而不是预加载,这可能是出于兼容考虑;
  • HSTS相比301 redirect,在性能和安全上可能有一些优势。301缓存和其他请求一样都是保存在浏览器缓存中,重定向会消耗性能;而HSTS保留在另一个单独的缓存列表中,可以保留更长时间而不被浏览器清除;
  • 中间人攻击可能利用重定向的时机进行介入,而HSTS 可以有效应对SSL剥离(HTTPS降级)导致的安全问题,但是对于其他类型的中间人攻击可能不起作用。
  • HSTS 常和 HPKP(HTTP Public Key Pinning) 结合使用, HPKP 允许 HTTPS 网站指定其信任的证书,并指示浏览器不允许任何连接到由任何其他证书保护的站点。

总之,中间人攻击不可能简单地通过某一种策略来完全阻止,但是聊胜于无,HSTS 仍然是个可行的安全策略。


参考了一些博客和讨论,如有错误欢迎指正。

参考资料


  转载请注明: Blog HSTS VS 301 redirect

 上一篇
整理一些CSS的知识 整理一些CSS的知识
最近在翻《CSS权威指南》,一些零散的知识点平时不太注意,这里记录一下。 CSS属性displaydisplay指定了元素的显示类型,它包含两类基础特征,用于指定元素怎样生成盒模型——外部显示类型定义了元素怎样参与流式布局的处理,内部显示类
2019-06-02
下一篇 
【翻译】为什么我们需要写super(props) 【翻译】为什么我们需要写super(props)
原文链接Why Do We Write super(props)? 我听说Hooks是最近的热点。讽刺的是,我将从类组件的有趣之处开始这篇博客。这也不错吧! 对于高效地使用React来说,这些陷阱并不是非常重要。但是如果你想更加深
2019-05-15
  目录