X-Forwarded-Host 在 nginx 中不起作用

X-Forwarded-Host 在 nginx 中不起作用

更新 2。我想添加并转发所有流量到localhost/admin/而不是localhost/

  • 应用程序监听这些路径:
    • localhost/(然后应用程序获取 302 localhost/login),
    • localhost/overview
    • localhost/books/details, ETC。
  • 我希望管理员用户使用这些 URL:
    • localhost/admin/(通过应用程序获取 302 localhost/admin/login
    • localhost/admin/overview
    • localhost/admin/books/details
  • 使用我的反向代理(见下文):
    • localhost/admin/(我localhost/login通过应用程序获得 302)

我也可以用来ingrees-nginx-controller代替安装文件。

在docker nginx.conf中(或类似于k8s)

server {
    listen 80 default_server;
    listen [::]:80 default_server;
        ...
        location /admin {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host/admin;
        proxy_pass http://<conteiner2>.docker-network;
    }
    ... 
}

更新1 对于 kubernetes,我正在尝试设置ingress-nginx 为此,我安装了ingress-nginx-controller并使用以下 YAML 设置ingress-nginx

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      more_set_headers "Host $host";
      more_set_headers "X-Real-IP $remote_addr";
      more_set_headers "X-Forwarded-For $proxy_add_x_forwarded_for";
      more_set_headers "X-Forwarded-Proto $scheme";
      more_set_headers "X-Forwarded-Host $host/admin";
  name: test-ingress
  namespace: <namespace>
spec:
  rules:
    - http:
        paths:
        - path: /admin
          backend:
            serviceName: <app1>-admin
            servicePort: 8002

答案1

因此,这里有几件事要发生;最重要的是:

proxy_set_header X-Forwarded-Host $host/admin;
proxy_pass http://<conteiner2>.docker-network;

是不正确的,因为x-forwarded-HOST不应该包含乌里,正如您所看到的/admin:它应该只是$host;您真正想要的是更新proxy_pass以包含,$request_uri正如您可以观察到的那样,在使用 nginx Ingress 控制器时生成的 nginx.conf 会这样做。等待位置的 URI/admin以及位置中匹配的任何其他内容将按预期向上游传递:

proxy_set_header X-Forwarded-Host $host;
proxy_pass http://<conteiner2>.docker-network$request_uri;
# or you're free to hard-code /admin if you prefer:
proxy_pass http://<conteiner2>.docker-network/admin;

其次,如果您遇到想要将一些configuration-snippet:应用于一个 URI 但不想同时应用于它们的情况,则将两个路由分成两个单独的 Ingress 资源,以便可以独立管理它们:

kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      # this one just applies to /api
  name: test-ingress-api
spec:
  rules:
    - http:
        paths:
        - path: /api
          backend:
            serviceName: <app2>-api
            servicePort: 8000
---
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      # this one just applies for /admin
  name: test-ingress-admin
spec:
  rules:
    - http:
        paths:
        - path: /admin
          backend:
            serviceName: <app1>-admin
            servicePort: 8002

关于如何调试 nginx 代理,有什么想法吗?

有两种很好的方法:首先,获取生成的 nginx.conf 并通读它以查看您期望发生的情况以及实际发生的情况:

kubectl cp ${the_nginx_controller_pod}:/etc/nginx/nginx.conf ingress-nginx.conf

另一种方法是转动nginx 日志级别debug如果您尝试在生产环境中进行调试,这可能会有问题,因为它会生成大量的文本,但它几乎肯定会对您要调试的内容提供实际答案):

# the ConfigMap may be named differently in your setup:
$ kubectl edit configmap nginx-ingress-controller

# and add:
data:
   error-log-level: debug

# then wait a few seconds for nginx to notice the configmap change
# and if it doesn't, kill the controller pods to force the reload

相关内容