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

在上一篇文章中我们已经实现了本地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请求并跳转到钓鱼网站类为列子,来看看大致的劫持流程是如下这个样子的。

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

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

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及以上版本

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

    HTTPS简介 HTTPS(Hyper Text Transfer Protocol Secure),是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的.HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议.Https使用的默认端口是443.更多HTTPS原理可以参考阮一峰老师的文章:http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html SSL证书 证书类

  • 详解nginx使用ssl模块配置支持HTTPS访问

    背景: 项目开发中用到了微信小程序,但是服务器配置URL必须是HTTPS,所以需要通过配置nginx的SSL模块来支持HTTPS访问,也就是说,要做一个网站域名为 dmsdbj.com 要求通过HTTPS://dmsdbj.com进行访问. SSL英文名为Secure Socket Layer,安全套接字层.SSL是一种数字证书,它使用ssl协议在浏览器和web server之间建立一条安全通道,数据信息在client与server之间的安全传输. 本篇博客是对这个操作步骤的详解. 前提: 1.

  • nginx强制使用https访问的方法(http跳转到https)

    需求简介 基于nginx搭建了一个https访问的虚拟主机,监听的域名是test.com,但是很多用户不清楚https和http的区别,会很容易敲成http://test.com,这时会报出404错误,所以我需要做基于test.com域名的http向https的强制跳转 我总结了三种方式,跟大家共享一下 nginx的rewrite方法 思路 这应该是大家最容易想到的方法,将所有的http请求通过rewrite重写到https上即可 配置 server { listen 111:80; serve

  • nginx配置ssl证书实现https访问的示例

    一,环境说明 服务器系统:ubuntu16.04LTS 服务器IP地址:47.89.12.99 域名:bjubi.com 二,域名解析到服务器 在阿里云控制台-产品与服务-云解析DNS-找到需要解析的域名点"解析",进入解析页面后选择[添加解析]按钮会弹出如下页面: 主机记录这里选择@,记录值就是服务器ip地址,确认. 三,申请ca证书 在阿里云控制台-产品与服务-安全(云盾)-CA证书服务(数据安全),点击购买证书, 选择"免费版DV SSL",点击立即购买: 然

  • nginx配置ssl实现https访问的步骤(适合新手)

    前言 刚刚部署完服务器后的我满怀欣喜地访问自己的网站,看哪都哪满意.但是兴奋感一过发现,诶,为什么浏览器左上角会提示不安全?想了想,不行,我也要搞个https来,我也要上锁! HTTP协议以明文方式发送内容,不提供任何方式的数据加密.为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密. 申请证书 在这里,我直接申请腾讯云的免费证书.这里需要注意下,这亚洲诚信机构颁发的免费证书只能一个域名使用,子域名那些需要另外申请

  • 详解NGINX访问https跳转到http的解决方法

    问题:浏览器打开https://www.jb51.net/aaa.html,然后跳转到http://www.jb51.net/aaa.html 网站架构:用户--https--->nginx代理---http---->tomcat/nginx+php nginx待遇发给后端的请求是http协议,后端程序跳转获取到的协议是http,返回一个redirect(http header中带Location:http://www.jb51.net/aaa.html),浏览器收到location,跳转到了

  • nginx使用ssl模块配置支持HTTPS访问的方法

    默认情况下ssl模块并未被安装,如果要使用该模块则需要在编译nginx时指定–with-http_ssl_module参数. 需求: 做一个网站域名为 www.localhost.cn 要求通过https://www.localhost.cn进行访问. 10.10.100.8 www.localhost.cn 实验步骤: 1.首先确保机器上安装了openssl和openssl-devel #yum install openssl #yum install openssl-devel 2.创建服务

  • 详解Nginx配置SSL证书实现Https访问

    背景 由于项目需求,安全起见,需要将之前的http接口访问变成https访问,所以需要配置SSL证书.项目的架构是这样的: 基本架构是硬负载(ReadWhere)+ 软负载(Nginx)+ Tomcat集群,现在的问题是SSl证书要配置在哪里,直接配置在硬负载上?还是分别配置在Nginx和Tomcat上?还是其他的配置方法呢? 首先在硬负载上配置放弃了,然后通过在网上查找资料,发现可以只在Nginx上配置证书,就是说Nginx接入使用Https,而Nginx与Tomcat之间使用Http进行衔接

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

    在上一篇文章中我们已经实现了本地node服务使用https访问了,看上一篇文章效果可以看如下: 但是如果我们现在使用http来访问的话,访问不了.如下图所示: 因此我现在首先要做的是使用nginx配置下,当用户在浏览器下输入http请求的时候使用nginx重定向到https下即可.因此我们现在需要做一个简单的nginx重定向功能. 因此在我们的nginx中需要加如下重定向配置: server { listen xxx.abc.com; server_name xxx.abc.com; rewri

  • Nginx下Frp强制重定向为https配置详解

    迫于家里的路由将300M的带宽强行降到80M的速度,所以入手了一个3205U的软路由,果真没有令人失望,速度飞起O(∩_∩)O哈哈~ 当然,由于宽带没有公网IP所以DDNS就不能使用,转而使用frp,在折腾的过程中踩到了一些坑,所以记录下来,希望能帮助有需要的同学. frps.ini(服务端配置) [common] bind_port = 5443 kcp_bind_port = 5443 vhost_http_port = 8080 vhost_https_port = 4443 # Frp的

  • laravel 解决强制跳转 https的问题

    路由要从http redirect 到 https,可以改 nginx/apache 配置.如果不想在web server中做这些修改配置,可以尝试在laravel框架中解决 在网上里看到的一个方案是 写一个 全局中间件,将所有的请求转换成 https [利用$request->scure() 来判断 和 转化] 不过我发现这个做法在直接访问首页的时候并不能实现转化 (route为 " / " 的时候) 然后换了方法: 1.在 app/Providers/AppServicePr

  • Pytest中skip skipif跳过用例详解

    前言 pytest.mark.skip可以标记无法在某些平台上运行的测试功能, 或者您希望失败的测试功能希望满足某些条件才执行某些测试用例,否则pytest会跳过运行该测试用例 实际常见场景:跳过非Windows平台上的仅Windows测试,或者跳过依赖于当前不可用的外部资源(例如数据库)的测试 @pytest.mark.skip 跳过执行测试用例,有可选参数reason:跳过的原因,会在执行结果中打印 #!/usr/bin/env python # -*- coding: utf-8 -*-

  • Python实现强制复制粘贴的示例详解

    目录 前因后果 流程思路 代码展示 效果展示 前因后果 公司有人阳了,今天在家上班,突然小姨子就问我有没有baidu文库会员,想下载点东西,我心想这还要会员?用Python不是分分钟的事情! 然后我非常自信的告诉她不用会员随便下载,结果她顺势想来我家,还问我她姐姐在不在家,趁我一个人在家过来想干嘛?本着男孩子一个人在家要好好保护自己的原则,于是我过段拒绝了她! 兄弟们我做的对吗? 咱们来开始今天的内容,咱们不仅要强制复制粘贴,还要自动保存到world文档,就问你刑不刑! 需要的模块 reques

  • Android Activity的跳转与传值详解

    Android Activity的跳转与传值详解 Activity跳转与传值,主要是通过Intent类来连接多个Activity,以及传递数据. Intent是Android一个很重要的类.Intent直译是"意图",什么是意图呢?比如你想从这个Activity跳转到另外一个Activity,这就是一个意图.Intent类在Android系统中的作用很大,在此不详细说了,后面有文章介绍! Activity跳转,无返回结果 这是最简单的Activity跳转方式.从一个Activity启动

  • linux下防火墙开启某个端口号及防火墙常用命令使用(详解)

    1.永久性生效,重启后不会复原 开启:chkconfigiptables on 关闭:chkconfigiptables off 2.即时生效,重启后复原 重启防火墙 方式一:/etc/init.d/iptables restart 方式二:service iptables restart 关闭防火墙: 方式一:/etc/init.d/iptables stop 方式二:service iptables stop 启动防火墙 方式一:/etc/init.d/iptables start 方式二:

  • 兼容浏览器的js事件绑定函数(详解)

    因为javascript中所有对象都集成与Object,那么只有给Object原型添加一个事件绑定函数,就不需要在处理绑定事件的时候,每次写一长串代码,直接调用即可.在代码中添加红色部分代码,直接便可以在代码中直接调用 <div id="mydiv" style="cursor:pointer; background-color:#F00">nihaoa</div> <script language="javascript&q

  • vue2.0项目实现路由跳转的方法详解

    一.安装 1.安装路由vue-router: npm install vue-router vue项目的依赖文件node_modules存在vue-router依赖,说明安装成功 2.vue项目引入vue-ruoter: 二.应用 1.路径配置(页面跳转): 方法一:如果切换的页面不多,可以直接在main.js文件内配置. 方法二:如果切换的页面较多,可以建一个专门用于路由的js文件,里面配置路径. 1)router.js配置文件 2)main.js里引入router.js路由文件 2.组件里调

  • react-router 重新加回跳转拦截功能详解

    目录 前言 事件经过 v6 之前的版本如何拦截 v6.7.0+ 如何拦截 吐槽 前言 路由的跳转拦截,在一些表单页中尤为常见.场景:用户输入了一些信息后但未提交,为了防止用户误点击某个跳转链接导致所填的表单信息丢失,跳转之前会弹出一个提示,如 “信息未提交,请确认是否离开” 等字样. 事件经过 在 react-router v6 之前有提供一个 <Prompt /> 组件来拦截路由的跳转.而在 v6 中却不支持此功能了!社区一片哀嚎,经查在 v6 实验阶段是有此功能的,但在 v6.0.0 be

随机推荐