【虚拟机-网关】如何在使用应用程序网关和 Nginx 的环境下实现强制 HTTPS 跳转
背景介绍
大家在使用 Nginx 部署网站时,实现 HTTP 到 HTTPS 的强制跳转是非常容易的事情,一般可以使用rewrite
命令或者使用返回自定义 301 页面的方法对 HTTP 请求进行 HTTPS 重定向。如果大家把 Nginx 服务器部署在 Azure 应用程序网关后端时,会发现如果原封不动的采取原先的方法进行重定向就无法正常工作。
本文通过讲述 Azure 应用程序网关的工作原理,向大家介绍一种在使用应用程序网关和 Nginx 的环境下实现强制 HTTPS 跳转的方法。
应用程序网关工作原理
Azure 应用程序网关采用的是类似于反向代理服务器的工作方式,客户端直接访问应用程序网关的公网地址而无法感知后端实际的服务器。当应用程序网关接收到客户端的请求之后,它会以自身实例在虚拟网络内部的地址作为源地址对后端池内部的服务器发起新的请求来获取数据,再将获取的数据通过原先跟客户端建立的连接返回给客户端。
如上图所示,我们部署了三台 Nginx 服务器在应用程序网关后端。应用程序网关部署在 AppGw 子网之内,Nginx 服务器部署在 Nginx 子网之内。应用程序网关本质上是由多个虚拟机实例组成的群集,默认情况下建立的应用程序网关包含两个实例,每个实例都会占用子网内的一个地址,如上图所示实例 -0 占用地址 192.168.0.4,实例 -1 占用地址 192.168.0.5。当客户端对应用程序网关发起请求时,Azure 前端的负载均衡器会将请求发送到对应的应用程序网关实例,应用程序网关上面的服务会以实例本身的内网地址向后端服务器发起新的请求。比如客户端的请求被发送到实例 -0,该实例会以 192.168.0.4 作为源地址对后端服务器发起请求。
应用程序网关转发机制
由于应用程序网关向后端服务器发起的请求改变了客户端请求的源地址,所以从 TCP 层面来讲,客户端的信息会丢失,但是从 HTTP 层面来讲这个信息并未丢失。这主要是因为应用程序网关会在 HTTP 包头内部添加 X-Forwarded 字段来记录客户端访问的源 IP、源端口、访问协议和请求的目的地址端口。
假设我们成功部署下面的环境,应用程序网关前端开启 80 端口走 HTTP 协议, 443 端口走 HTTPS 协议(同时完成 SSL 卸载),后端只开启 80 端口走 HTTP 协议(目前中国区 Azure 应用程序网关在后端只支持 HTTP 协议)。
当客户端通过 80 端口使用 HTTP 协议访问时,如果我们从后端服务器上面抓包,我们可以看到 HTTP 包头的 X-FORWARDED-PROTO 为 HTTP, X-FORWARDED-PORT 为 80,同时也会在 X-Forwarded-For 部分记录访问者的源 IP 和源端口(实际 IP 以 x.x.x.x 代替)。
Frame: Number = 32, Captured Frame Length = 649, MediaType = ETHERNET
+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-17-FA-00-73-C4],SourceAddress:[44-03-A7-A4-3F-41]
+ Ipv4: Src = 192.168.0.4, Dest = 192.168.1.4, Next Protocol = TCP, Packet ID = 32620, Total IP Length = 635
+ Tcp: Flags=...AP..., SrcPort=58266, DstPort=HTTP(80), PayloadLen=595, Seq=518190070 - 518190665, Ack=447095254, Win=515 (scale factor 0x8) = 131840
- Http: Request, GET /
Command: GET
+ URI: /
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Upgrade-Insecure-Requests: 1
X-FORWARDED-PROTO: http
X-FORWARDED-PORT: 80
X-Original-URL: /
X-Forwarded-For: x.x.x.x:64397
X-ARR-LOG-ID: 3f7b9b21-a862-4b62-a850-dc378bc3c843
HeaderEnd: CRLF
当客户端通过 443 端口使用 HTTPS 协议访问时,从下面的抓包可以看到应用程序网关完成了 SSL 卸载之后仍然是通过 HTTP 80 端口来访问后端服务器,但是会在 HTTP 包头的 X-FORWARDED-PROTO 记录原始访问是 HTTPS 请求以及原始访问是请求服务器的 443 端口。
Frame: Number = 36, Captured Frame Length = 700, MediaType = ETHERNET
+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-17-FA-00-73-C4],SourceAddress:[44-03-A7-A4-3F-41]
+ Ipv4: Src = 192.168.0.4, Dest = 192.168.1.4, Next Protocol = TCP, Packet ID = 15961, Total IP Length = 686
+ Tcp: Flags=...AP..., SrcPort=57271, DstPort=HTTP(80), PayloadLen=646, Seq=375761782 - 375762428, Ack=1033546289, Win=511
- Http: Request, GET /
Command: GET
+ URI: /
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Upgrade-Insecure-Requests: 1
X-FORWARDED-PROTO: https
X-FORWARDED-PORT: 443
X-Original-URL: /
X-Forwarded-For: x.x.x.x:64390
X-ARR-SSL: 2048|256|CN=FredTest|CN=FredTest
X-ARR-LOG-ID: e93508a5-5242-4f0d-a778-84630f71541b
HeaderEnd: CRLF
通过上面的分析,我们可以看到客户端的 HTTP 和 HTTPS 请求到达后端服务器都是 HTTP 请求,但是应用程序网关会在 HTTP 包头的 X-FORWARDED-PROTO 和 X-FORWARDED-PORT 中对这两种请求加以区分。
配置 Nginx 实现强制 HTTPS 转换
在未使用应用程序网关的场景下,我们一般可以在 Nginx 配置里使用类似于下面的 rewrite 命令来重定向客户端的 HTTP 请求。
server {
listen 80;
server_name www.abc.com
rewrite ^/(.*) https://$host$1 permanent;
}
但是在使用应用程序网关的场景下会发生问题,因为 Nginx 服务器本身虽然将这个请求重写为 HTTPS 请求,但是当新的 HTTPS 的请求再次经过应用程序网关到达后端服务器时又会变为 HTTP 请求从而导致死循环。解决此问题的办法就是需要在后端服务器上来判断客户的原始请求时 HTTP 还是 HTTPS,当客户的原始请求是 HTTP 时进行重定向,而当客户的原始请求是 HTTPS 时不进行重定向。通过前面的分析,我们已经知道可以通过 HTTP 包头的 X-FORWARDED-PROTO 来判断客户端的实际请求,而 Nginx 又会将字段 X-FORWARDED-PROTO 的值保存在变量 $http_x_forwarded_proto 中,这样我们就可以加入类似下面的判断语句来实现强制 HTTPS 跳转了。
server {
listen 80;
server_name www.abc.com
if ($http_x_forwarded_proto = 'http')
{
rewrite ^/(.*) https://$host$1 permanent;
}
}
通过这样的设置,当访问网站时我们可以看到服务器端返回了 301 并请求跳转到 HTTPS。
客户端再次通过 HTTPS 访问时,服务端不再返回 301 而是返回 200 表示访问成功。
【虚拟机-网关】如何在使用应用程序网关和 Nginx 的环境下实现强制 HTTPS 跳转的更多相关文章
- 利用宏定义实现C++程序在Unix和Win32环境下的通用性
[转] 1.1. 宏定义软件的代码,从跨平台的角度来看,可以分为平台相关的和平台无关的.采用C/C++编写的软件,在进行移植时,平台无关的的代码基本上不需要做大的改动,但平台相关的代码需要做很大的调整 ...
- Azure-如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(二)
问题描述 经过如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(一)中的排查步骤,可以判断出是由于 Web 服务器自身问题导致的响应异常. 那么可以在 IIS ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:1、服务端:注册中心、网关(提供可运行程序下载)。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- 深入Java微服务之网关系列1:什么是网关
前言 近来,在想着重构一个新的产品.准备采用微服务的技术解决方案,来搭建基础设施框架.网关,是一个必不可少的组件.那么,网关到底是什么? 其又有什么特点或者特性,成为微服务必不可少的组件呢?今天, ...
- [移动网关]2G环境下资源下载有一定概率失败,客户端日志显示收到403错误
2G环境下资源下载有一定概率失败,客户端日志显示收到403错误 问题现象: 测试同学在使用联通号码在移动网络环境下,访问连接得到的response_code出现是403,导致资源读取失败表情显示异常. ...
- 微服务架构学习与思考(11):开源 API 网关02-以 Java 为基础的 API 网关详细介绍
微服务架构学习与思考(11):开源 API 网关02-以 Java 为基础的 API 网关详细介绍 上一篇关于网关的文章: 微服务架构学习与思考(10):微服务网关和开源 API 网关01-以 Ngi ...
- 西门子S7-200 SMART在win10环境下,使用虚拟机进行网络通信问题一二
原来的笔记本光荣退休,新买了小米笔记本17150.有个项目需要使用西门子S7-200 SMART,结果碰到了很多悲催的事情,新系统下的各种问题. 先贴下计算机配置,如下: 阶段一:安装问题 (1)在w ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:5、微服务应用程序发布到Docker部署(下)。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...
- Linux环境下部署完JDK后运行一个简单的Java程序
前言 前一篇文章详细讲解了如何在Windows环境下安装虚拟机+Linux系统,并且成功部署了JDK. 不过部署完JDK之后,我们判断部署是否成功的依据是看"java -version&qu ...
随机推荐
- 连接带密码的access数据库
在网上找了很多都不靠谱,稀里哗啦的弄一堆连接字符串,很不优雅. 这个方法很简单: 1.在“连接”这页中,下方有“输入登录数据库的信息”用户名:admin,并在下面选择“空白密码” 2.在“所有”这页的 ...
- 《Java多线程编程核心技术》读后感(九)
当interrupt方法遇到wait方法 当线程呈wait()状态时,调用线程对象的interrupt()会出现InterruptedException异常 package Third; public ...
- DOM,date,字符串
ECMAscript Dom doc Bom Browerwindow --窗口. location --地址栏. history --历史. document --文档. statue --任务栏& ...
- A Beginner's Guide to HTTP and REST
http://code.tutsplus.com/tutorials/a-beginners-guide-to-http-and-rest--net-16340 Hypertext Transfer ...
- ue4 1官网编程指南总结
https://docs.unrealengine.com/latest/CHN/index.html 中编程指南 快速入门 actor生命周期 FloatingActor.h #pragma onc ...
- hdu1166(线段树单点更新&区间求和模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:中文题诶- 思路:线段树单点更新,区间求和模板 代码: #include <iost ...
- 剑指Offer的学习笔记(C#篇)-- 矩形覆盖
题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 一 . 解题思路 这个貌似就是普通的跳台阶问题. 二 . 代 ...
- JDBC连接数据以及详细的ResultSet结果集解释
一.数据库连接 (前面为jdbc的其他参数,文章下部分为ResultSet详解) ResultSet rs = st.executeQuery(sqlStr) 1. java的sql框架支持多种数据库 ...
- 输入apt-get update时出现Could not open lock file /var/lib/apt/lists/lock - open
我看了其它的资料发现不够清楚 我只报这些错误 1.1.ps-aux 查出apt-get进程的PID,通常是一个四位数字. 不好找apt-get进程 输入此代码就好找了 ps -aux|grep apt ...
- 浅谈css常用伪类用法
着重写一下after和before的用法: css样式搞定:标签元素+伪类after a.'class名':after{//我的样式名称是这个,可以写成你自己的样式名称 content: '已打包'; ...