在 Google 前端负载均衡器后面运行时如何正确从 Spring Boot 2.3 重定向到 HTTPS
Posted
技术标签:
【中文标题】在 Google 前端负载均衡器后面运行时如何正确从 Spring Boot 2.3 重定向到 HTTPS【英文标题】:How to properly Redirect from Spring Boot 2.3 to HTTPS when running behind a Google Front End Load Balancer 【发布时间】:2020-10-13 14:05:42 【问题描述】:我有一个 Spring Boot 应用程序在 GKE 上通过入口控制器使用 Google https 负载均衡器运行。我正在寻找的行为是让 Spring Boot 应用程序在收到 http 请求时重定向到 https。在 Spring Boot 2.2 及更早的版本中,我可以使用以下代码和配置来做到这一点。
我的应用程序 yaml 中的配置
server:
port: 8877
use-forward-headers: true # this should make it understand X-Forwarded-Proto header
在我的 Spring Security 配置中我做了
@Override
protected void configure(HttpSecurity http) throws Exception
/* When the app is running on GKE traffic will come in through the
* GCP http load balancer. Which will set the X-Forwarded-Proto
* header to http or https. When the app runs on a dev machine
* these headers are not set.
*
* see https://cloud.google.com/load-balancing/docs/https/
*
* The code forces ssl if the x forwarded proto header is present
* as that indicates the app is online and accessible to the
* wider internet.
*
*/
http.requiresChannel()
.requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
.requiresSecure();
// more stuff omitted
在 Spring Boot 2.3 server.use-forward-headers
已弃用我将配置更改为
server:
port: 7777
forward-headers-strategy: native
tomcat:
remoteip:
protocol-header: "X-Forwarded-Proto"
remote-ip-header: "X-Forwarded-For"
我没有对需要安全通道的代码进行任何更改。但是,当像 https://example.com 这样的请求通过 GCP 负载均衡器到达引导时,它不会被识别为安全连接,并且重定向 https://example.com 是从 Spring Boot 发送的。这会导致浏览器说检测到无限重定向循环。
问题在通过 Ingress 控制器配置的 GCP 负载均衡器后面的 GKE 上运行的 Spring Boot 2.3 上从 http 重定向到 https 的正确方法是什么?
【问题讨论】:
【参考方案1】:Spring Boot 依赖于 Tomcat 来评估传入的请求,以确定该请求是否应被视为“安全”。 Tomcat remote IP valve 正在查看两位信息以评估请求是否安全。
-
向tomcat发送请求的负载均衡器/代理的IP地址
x-forwarded-proto
http 标头的值
在tomcat配置中称为内部代理的负载均衡器的IP地址必须在受信任列表中,并且x-forwaded-proto
必须是https
,以便tomcat认为请求安全。否则,将发送重定向。
谷歌负载均衡器正在发送带有x-forwaded-proto: https
的请求,但源IP 是google range 35.191.0.0/16
和130.211.0.0/22
之一,因此tomcat 认为来自GCP 负载均衡器的https 请求不安全,发回重定向.从而导致浏览器抱怨的无限重定向循环。
Spring Boot 使用属性 server.tomcat.remoteip.internal-proxies
配置 tomcat 远程 IP 地址,该属性使用下面的正则表达式具有来自 RFC 1918 的私有 IP 地址的默认值。
10\\.\\d1,3\\.\\d1,3\\.\\d1,3|192\\.168\\.\\d1,3\\.\\d1,3|169\\.254\\.\\d1,3\\.\\d1,3|127\\.\\d1,3\\.\\d1,3\\.\\d1,3|172\\.1[6-9]1\\.\\d1,3\\.\\d1,3|172\\.2[0-9]1\\.\\d1,3\\.\\d1,3|172\\.3[0-1]1\\.\\d1,3\\.\\d1,3|0:0:0:0:0:0:0:1|::1
Tomcat 不知道如何比较 ip 地址范围,因此必须将 google 源 ips 转换为正则表达式才能工作。
server:
port: 7777
forward-headers-strategy: native
tomcat:
remoteip:
protocol-header: "X-Forwarded-Proto"
remote-ip-header: "X-Forwarded-For"
internal-proxies: ".*" # should Java regex to match ip address range of the load balancer servers. Not a best practice to trust all ip addresses.
【讨论】:
在我的情况下,使用ForwardedHeaderFilter
***.com/a/67377536/986942修复以上是关于在 Google 前端负载均衡器后面运行时如何正确从 Spring Boot 2.3 重定向到 HTTPS的主要内容,如果未能解决你的问题,请参考以下文章
如何拒绝对没有主机标头的 Google 外部 HTTPS 负载均衡器的请求?
如何使 HTTP 调用到达亚马逊 AWS 负载均衡器后面的所有实例?
在负载均衡器后面运行多个 daphne 实例:django-channels