【问题标题】:Nginx HTTPS->HTTP gets 403 "SSL required" error with SpringNginx HTTPS->HTTP 在 Spring 中出现 403“需要 SSL”错误
【发布时间】:2020-09-27 19:28:51
【问题描述】:

问题

在尝试通过我的 ELB 路由到 Kubernetes Nginx 入口控制器时,我从 Spring 获得了 403 SSL 要求。

设置

我的设置如下:

  1. 我的 Kubernetes 集群(由 kops 创建)有一个带有 ACM 的 ELB (AWS),它将所有请求路由到
  2. Nginx Ingress Controller 依次根据中规定的规则路由所有请求
  3. 将流量传递到的入口
  4. 中公开端口 80 并路由到端口 8080 的服务
  5. 使用标签“app=foobar”(在部署中描述)选择的 Pod
  6. Pod 正在运行 Spring Boot Web App v2.1.3

所以基本上: https://foo.bar.com(:443) -> ingress -> http://foo.bar.svc.cluster.local:80

这对所有东西都很有用。除了 SprintBoot。 出于某种原因,我不断收到来自 Spring 的 403 - SSL required

这里要记住一点:我的 Spring 应用程序与 SSL 没有任何关系。我不希望它以那种性质做任何事情。出于本示例的目的,这应该是常规 REST API 请求,SSL 终止发生在容器外部。

到目前为止我尝试了什么

  • 端口转发到服务本身并请求 - 它工作正常。
  • WebSecurityConfigurerAdapter 中禁用 CSRF
  • 输入入口注释 nginx.ingress.kubernetes.io/force-ssl-redirect=true - 当我尝试它时它会给出 TOO_MANY_REDIRECTS 错误(而不是 403)
  • 输入入口注释nginx.ingress.kubernetes.io/ssl-redirect=true - 没有任何作用
  • 输入入口注释 nginx.ingress.kubernetes.io/enable-cors: "true" - 没有任何作用
  • 还有nginx.ingress.kubernetes.io/ssl-passthrough: "true"
  • 还有nginx.ingress.kubernetes.io/secure-backends: "true"
  • 还有kubernetes.io/tls-acme: "true"
  • 我尝试了一大堆其他我现在不记得的东西

它在我的集群中是什么样子的

Nginx 入口控制器注解是这样的(我使用的是官方的 nginx 入口控制器 helm 图,除了这个东西几乎没有修改):

service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "aws_acm_certificate_arn"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"

入口如下所示:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foobar
  namespace: api
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: http
        path: /

服务如下所示:

apiVersion: v1
kind: Service
metadata:
  name: foobar
  namespace: api
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: foobar

我认为问题是什么

我的预感是它带有 X-Forwarded 标头,而 Spring 在幕后发挥了它的魔力,试图变得聪明,并决定我需要基于某些标头的 SSL,而无需我明确要求它。但我还没弄明白。


我到处寻找解决方案,但找不到任何可以减轻痛苦的方法...希望您能提供帮助!

编辑

我发现我当前的设置(没有 k8s 和 nginx)工作正常,ELB 通过 X-Forwarded-Port: 443X-Forwarded-Proto: https,它似乎工作,但在我的带有 nginx 的 k8s 集群上,我放入了一个监听器客户端吐出所有标题,我的标题似乎是X-Forwarded-Port: 80X-Forwarded-Proto: http

【问题讨论】:

  • 错误是显示给你的spring boot api(curl、ajax、postman等)的最终客户端还是显示为你的elb/nginx的登录?
  • @JRichardsz "SSL required" 443 在我使用的任何客户端中从 spring boot api 返回。我还得到了更多线索,请注意我刚刚发布的编辑
  • @DorMunis 您应该能够使用属性文件关闭 https 要求。我不确定你为什么在这种情况下强制使用 HTTPS,因为 HTTPS 会被 ELB 终止,而你的 Kubernetes 集群应该只关心端口和服务端点/IP。
  • @sonus21 黑盒方法,这不是我现在正在做的新事物,我想在实际代码中尽可能地改变。不过谢谢你的回复,我也会调查一下
  • 您是否有机会在您的 Spring Boot 应用程序(配置或代码)中启用 ssl? security.require-ssl=true

标签: spring spring-boot ssl nginx kubernetes


【解决方案1】:

感谢所有提供帮助的人,我实际上找到了答案。 在代码中,有一些验证表明所有请求都应该来自安全源,并且 Nginx Ingress Controller 更改了这些标头(X-Forwarded-Proto 和 X-Forwarded-Port),因为 SSL 在 ELB 中终止并作为HTTP

为了解决这个问题,我做了以下操作:

  1. 在配置映射中添加了use-proxy-protocol: true - 它传递了正确的标头,但出现了有关断开连接的错误(我现在不记得实际的错误,如果有,我稍后会编辑这个答案将是对它的任何请求)

  2. 为了修复这些错误,我在 nginx 入口控制器注释配置中添加了以下内容:

service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"

这确保所有流量都将使用代理协议,而且我还必须将 backend-protocolHTTP 更改为 TCP

这样做可确保所有路由 ELB 的请求保留其原始 X 标头,并传递给 Nginx 入口控制器,然后再传递给需要传递这些标头的应用程序。

【讨论】:

    猜你喜欢
    • 2018-09-22
    • 2013-07-19
    • 2018-01-09
    • 1970-01-01
    • 2020-10-31
    • 2015-04-24
    • 2015-11-13
    • 1970-01-01
    • 2021-04-02
    相关资源
    最近更新 更多