使用ingress-nginx时后端返回302导致无限重定向问题
Ingress-Nginx 后端302重定向引发无限循环问题排查
问题现象
使用Ingress-Nginx时,访问https://service.example.com认证失败后,后端返回302重定向到https://login.example.com,但实际出现无限循环:请求反复回到service.example.com,持续触发认证失败。
Ingress配置
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: main-ing namespace: default annotations: nginx.ingress.kubernetes.io/ssl-passthrough: "true" spec: ingressClassName: nginx rules: - host: service.example.com http: paths: - pathType: Prefix path: / backend: service: name: prometheus-service port: number: 443 - host: login.example.com http: paths: - pathType: Prefix path: / backend: service: name: authentication-grant-service port: number: 443
后端未授权处理代码
func unauthorizedPage(logger *zap.Logger, w http.ResponseWriter, req *http.Request) { logger.Error("The user is not authorized to make this request - referring", zap.String("refer", req.Host+req.URL.Path)) for name, values := range req.Header { for _, value := range values { fmt.Println(name, value) } } http.Redirect(w, req, "https://login.example.com", http.StatusFound) }
日志信息
{"level":"error","ts":1658531352.658133,"caller":"proxy/proxy.go:30","msg":"The user is not authorized to make this request - referring","refer":"service.example.com/",".... {"level":"error","ts":1658531352.658133,"caller":"proxy/proxy.go:30","msg":"The user is not authorized to make this request - referring","refer":"login.example.com/","....
尝试的修复及问题
修改后端代码跳过来自login.example.com的请求重定向,但页面返回空白:
// unauthorizedPage is the default redirect page func unauthorizedPage(logger *zap.Logger, w http.ResponseWriter, req *http.Request) { refer := req.Host + req.URL.Path if refer != "service.example.com/" { logger.Info("Not failing request since redundant", zap.String("refer", refer)) return } logger.Error("The user is not authorized to make this request - referring", zap.String("refer", req.Host+req.URL.Path)) for name, values := range req.Header { for _, value := range values { fmt.Println(name, value) } } http.Redirect(w, req, "https://login.example.com", http.StatusFound) }
原因分析
核心问题是启用了nginx.ingress.kubernetes.io/ssl-passthrough: "true"注解:
- SSL Passthrough模式下,Ingress-Nginx不会终止SSL连接,直接将加密流量透传给后端服务,此时Ingress基于**SNI(Server Name Indication)**路由请求,而非解析HTTP请求的Host头。
- 后端返回302重定向后,若请求是Ingress内部转发而非客户端发起新请求,SNI仍为
service.example.com,导致Ingress错误将请求路由到prometheus-service,再次触发认证失败形成循环。 - 日志中出现
refer: login.example.com/,说明后端收到了指向登录域名的请求,但因路由错误被发到prometheus-service,进而被拦截。
解决方案
方案1:关闭SSL Passthrough(推荐)
去掉nginx.ingress.kubernetes.io/ssl-passthrough: "true"注解,改用Ingress-Nginx终止SSL连接,配置tls字段处理证书:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: main-ing namespace: default spec: ingressClassName: nginx tls: - hosts: - service.example.com - login.example.com secretName: your-tls-secret # 替换为你的TLS证书Secret rules: - host: service.example.com http: paths: - pathType: Prefix path: / backend: service: name: prometheus-service port: number: 443 - host: login.example.com http: paths: - pathType: Prefix path: / backend: service: name: authentication-grant-service port: number: 443
此模式下Ingress可解析HTTP Host头,正确将login.example.com请求路由到对应服务,重定向逻辑正常生效。
方案2:保留SSL Passthrough的调整
若必须使用SSL Passthrough,需确保:
- 后端302重定向直接返回给客户端,由客户端发起
login.example.com的新请求,无内部代理逻辑。 - 验证Ingress的SNI路由规则,确保
login.example.com的SNI能被正确识别并路由到authentication-grant-service,可通过Ingress-Nginx日志确认。
修复空白页面问题
之前的临时修复直接return未返回响应内容导致空白。正确做法是确保login.example.com请求被正确路由到authentication-grant-service,由登录服务返回对应页面内容。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

