在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在上一篇文章中我们已经实现了本地node服务使用https访问了,看上一篇文章效果可以看如下: 但是如果我们现在使用http来访问的话,访问不了。如下图所示: 因此我现在首先要做的是使用nginx配置下,当用户在浏览器下输入http请求的时候使用nginx重定向到https下即可。因此我们现在需要做一个简单的nginx重定向功能。 因此在我们的nginx中需要加如下重定向配置: 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请求并跳转到钓鱼网站类为列子,来看看大致的劫持流程是如下这个样子的。 操作步骤如下: 如上http请求根本就没有重定向到https网站到,而是攻击者直接劫持了http请求,最终把钓鱼网站返回给浏览器了。因此如果直接http重定向的话,会存在一次http请求明文的问题,因此直接使用http重定向是不安全的,因此就出现了HSTS来解决这个问题。下面我们来认识下HSTS吧。 2. 认识下HSTS 如上使用重定向的方式,把http重定向到https存在安全性问题,因为在重定向https之前会存在一次http明文的请求,那么攻击者很容易劫持http请求,因此现在我们想当用户浏览器发起http请求的时候,浏览器直接转换成https请求。然后通过https请求页面,这样的话,攻击者就一般很难进行攻击了。我们可以请看如下示意图,如下所示: 步骤可以理解为如下: 1. 用户在浏览器输入 http://xxx.abc.com 的时候,浏览器知道该域名需要使用https来进行通信。 那么现在的问题就是说,浏览器怎么知道该域名需要使用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秒。 下面我们先来看下百度的也是这样处理的,我们先在浏览器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; 即便满足了上述所有条件,也不一定能进入HSTS Preload List,更多信息可以查看:https://hstspreload.org/。 通过Chrome的chrome://net-internals/#hsts工具,可以查询某个网站是否在PreloadList之中,还可以手动把某个域名加到本机Preload List。 HSTS缺点 HSTS并不是HTTP会话劫持的完美解决方案。用户首次访问某网站是不受HSTS保护的。这是因为首次访问时,浏览器还未收到HSTS,所以仍有可能通过明文HTTP来访问。 如果用户通过HTTP访问HSTS保护的网站时,以下几种情况存在降级劫持可能: 1. 以前从未访问过该网站。 支持HSTS浏览器 目前主流浏览器都已经支持HSTS特性,具体可参考下面列表: Google Chrome 4及以上版本 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持极客世界。 |
请发表评论