nginx开启HSTS让浏览器强制跳转HTTPS访问

在上一篇文章中咱们已经实现了本地node服务使用https访问了,看上一篇文章 效果能够看以下:html

可是若是咱们如今使用http来访问的话,访问不了。以下图所示:node

所以我如今首先要作的是使用nginx配置下,当用户在浏览器下输入http请求的时候使用nginx重定向到https下便可。所以咱们如今须要作一个简单的nginx重定向功能。想要深刻了解nginx重定向功能,能够看这篇文章nginx

所以在咱们的nginx中须要加以下重定向配置:chrome

server {
  listen xxx.abc.com;
  server_name xxx.abc.com;
  rewrite ^/(.*)$ https://$host$1 permanent;
}

所以nginx主要的配置代码以下:浏览器

server {
  listen xxx.abc.com;
  server_name xxx.abc.com;
  rewrite ^/(.*)$ https://$host$1 permanent;
}
server {
  listen       443 ssl;
  server_name  xxx.abc.com;

  ssl_certificate      cert/server.crt;
  ssl_certificate_key  cert/server.key;

  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;

  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers  on;

  location / {
    proxy_pass http://localhost:3001;
  }
}

如上配置后,咱们须要从新启动下nginx便可生效,咱们在浏览器下输入域名 http://xxx.abc.com 后 会自动重定向到 https://xxx.abc.com/ 了,咱们再来看下 咱们网络上的请求有2个请求,以下所示:缓存

如上请求能够看到,浏览器首先会向网站发起一次http请求(http://xxx.abc.com), 在获得一个重定向响应后,再会发起一次https请求并获得最终的响应内容。对用户来说,它的操做是透明的,用户体验也是不错的,可是在https连接以前会存在一次明文的http请求和重定向。那么攻击者能够以中间人的方式劫持http请求。来进行后续的攻击。好比窃听数据。篡改请求或响应、跳转到钓鱼网站等操做。所以http请求是不够安全的,因此最近几年全部的网站都要以https来访问的。安全

那么以劫持http请求并跳转到钓鱼网站类为列子,来看看大体的劫持流程是以下这个样子的。服务器

操做步骤以下:
1. 浏览器会发起一次http请求(好比http://xxx.abc.com). 发出请求后,攻击者会以中间人的身份来劫持该http请求。
2. 攻击者劫持该http请求后,会把当前请求转发给钓鱼网站(好比 http://xxx.yyy.com)。
3. 钓鱼网站会返回假冒的网页内容。
4. 最后攻击者把假冒的网页内容返回给浏览器。网络

如上http请求根本就没有重定向到https网站到,而是攻击者直接劫持了http请求,最终把钓鱼网站返回给浏览器了。所以若是直接http重定向的话,会存在一次http请求明文的问题,所以直接使用http重定向是不安全的,所以就出现了HSTS来解决这个问题。下面咱们来认识下HSTS吧。session

2. 认识下HSTS

如上使用重定向的方式,把http重定向到https存在安全性问题,由于在重定向https以前会存在一次http明文的请求,那么攻击者很容易劫持http请求,所以如今咱们想当用户浏览器发起http请求的时候,浏览器直接转换成https请求。而后经过https请求页面,这样的话,攻击者就通常很难进行攻击了。咱们能够请看以下示意图,以下所示:

步骤能够理解为以下:

1. 用户在浏览器输入 http://xxx.abc.com 的时候,浏览器知道该域名须要使用https来进行通讯。
2. 所以浏览器直接向网站发起https请求(好比https://xxx.abc.com) 这样的。
3. 网站返回响应的内容。

那么如今的问题就是说,浏览器怎么知道该域名须要使用https呢?所以这个时候咱们出现了HSTS了。

HSTS是啥?

HSTS的全称是 HTTP Strict-Transport-Security. 它是国际互联网工程组织IETF发布的一种互联网安全策略机制。采用HSTS策略的网站将保证浏览器始终连接到该网站的https加密版本。不须要用户手动在URI地址栏中输入加密地址,来减小会话被劫持的风险。

HSTS的基本语法以下:

Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]

max-age 是必须的参数,它是一个以秒为单位的数值,它表明着HSTS Header的过时时间,通常设置为1年,即 31536000秒。
includeSubDomains 是可选参数,若是设置该参数的话,那么意味着当前域名及其子域名均开启HSTS的保护。
preload是可选参数,只有当你申请将本身的域名加入到浏览器内置列表的时候才须要使用到它。

下面咱们先来看下百度的也是这样处理的,咱们先在浏览器URI输入 http://www.baidu.com/ 后回车,浏览器会自动转化成 https://www.baidu.com/ 这样的请求了,可是咱们使用chrome浏览器看网络下的请求能够看到以下会发送2次请求,以下所示:

第二次是https请求,以下所示:

咱们能够看到如上,第一次请求状态码是307,而且请求头有这样的标识 "Provisional headers are shown", 具体的含义能够理解为浏览器拦截了该请求,而且该请求并无发送出去。所以浏览器发现该域名须要使用https来请求,因此就发了第二次https请求了。

nginx下配置HSTS

在nginx配置文件上设置HSTS响应头部,代码以下:

add_header Strict-Transport-Security "max-age=172800; includeSubDomains"

所以nginx的配置以下:

server {
  listen xxx.abc.com;
  server_name xxx.abc.com;
  rewrite ^/(.*)$ https://$host$1 permanent;
}
server {
  listen       443 ssl;
  server_name  xxx.abc.com;
  add_header Strict-Transport-Security "max-age=172800; includeSubDomains";
  ssl_certificate      cert/server.crt;
  ssl_certificate_key  cert/server.key;

  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;

  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers  on;

  location / {
    proxy_pass http://localhost:3001;
  }
}

而后nginx配置保存,而后重启。

当我重启后,第一次使用https方式访问个人网站,nginx会告诉客户端浏览器,之后若是用户输入的是http,也要让浏览器以https来访问个人nginx服务器,以下所示:

可是若是nginx重启后,第一次使用http访问的话,虽然跳转了,可是并无使用HSTS了,由于要跳转到https,才会使用HSTS。可是当我再输入http了就会有307状态码,而且有 "Provisional headers are shown" 这样的提示。

理解HSTS Preload List

HSTS虽然能够解决HTTPS的降级攻击,可是对于HSTS生效前首次的http请求,依然是没法避免http请求被劫持的问题,好比咱们第一次浏览器清除缓存,而后第一次使用http请求的话,第一次http也是明文传输的,当跳转到https后会使用HSTS的,之后只要浏览器缓存不清除的话,nginx不重启的话,都会使用HSTS保护的。所以为了解决第一次http请求的问题,浏览器厂商们为了解决这个问题,提出了 HSTS Preload List 的方案,内置一份能够按期更新的表,对于列表中的域名,即便用户以前没有访问过,也会使用https协议请求的。

目前这个Preload List由Google Chrome维护,Chrome、Firefox、Safari、IE 11和Microsoft Edge都在使用。若是要想把本身的域名加进这个列表,首先须要知足如下条件:

1. 拥有合法的证书(若是使用SHA-1证书,过时时间必须早于2016年);

2. 将全部HTTP流量重定向到HTTPS;
3. 确保全部子域名都启用了HTTPS;
4. 输出HSTS响应头:
5. max-age不能低于18周(10886400秒);
6. 必须指定includeSubdomains参数;
7. 必须指定preload参数;

即使知足了上述全部条件,也不必定能进入HSTS Preload List,更多信息能够查看:https://hstspreload.org/。

经过Chrome的chrome://net-internals/#hsts工具,能够查询某个网站是否在PreloadList之中,还能够手动把某个域名加到本机Preload List。

HSTS缺点

HSTS并非HTTP会话劫持的完美解决方案。用户首次访问某网站是不受HSTS保护的。这是由于首次访问时,浏览器还未收到HSTS,因此仍有可能经过明文HTTP来访问。

若是用户经过HTTP访问HSTS保护的网站时,如下几种状况存在降级劫持可能:

1. 之前从未访问过该网站。
2. 最近从新安装了其操做系统。
3. 最近从新安装了其浏览器。
4. 切换到新的浏览器。
5. 删除浏览器的缓存。
6. 最近没访问过该站而且max-age过时了。
那么解决该问题的方法,可使用上面介绍的 HSTS Preload List 方法。

支持HSTS浏览器

目前主流浏览器都已经支持HSTS特性,具体可参考下面列表:

Google Chrome 4及以上版本Firefox 4及以上版本Opera 12及以上版本Safari从OS X Mavericks起Internet Explorer及以上版本

相关文章
相关标签/搜索