Nginx real_ip_header 通过 GCE 入口?

Posted

技术标签:

【中文标题】Nginx real_ip_header 通过 GCE 入口?【英文标题】:Nginx real_ip_header through a GCE ingress? 【发布时间】:2018-07-17 18:07:18 【问题描述】:

我的目标是通过 GCE 入口通过 nginx 服务的 Kubernetes Engine 上部署的 Angular 应用的 IP 地址过滤访问。

但在我的 nginx 上,remote_addr 不正确。

$LB_IP 是这里定义的 ip:kubernetes.io/ingress.global-static-ip-name: app-angular

我在 nginx 上使用 set_real_ip_from 从 X-Forwarded-For 设置 ip

set_real_ip_from $LB_IP;
real_ip_header X-Forwarded-For;

原始 ip 出现在 X-Forwarded-For 标头中,正如谷歌文档中所预期的那样:https://cloud.google.com/compute/docs/load-balancing/http/#components

我可以看到 X-Forwarded-For 包含 $CLIENT_IP 但 remote_addr 不正确,顺便说一下我的 IP 过滤器不起作用。有什么想法吗?

我的 nginx 日志:

10.40.40.40 - - [07/Feb/2018:11:29:48 +0000] "GET /styles.bundle.css HTTP/1.1" 200 35908 "http://MY_URL/home" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/64.0.3282.140 Safari/537.36" "$CLIENT_IP, $LB_IP"

但我想要:

$CLIENT_IP - - [07/Feb/2018:11:29:48 +0000] "GET /styles.bundle.css HTTP/1.1" 200 35908 "http://MY_URL/home" "Mozilla/5.0 (Macintosh; Intel Mac) OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36" "$CLIENT_IP, $LB_IP"

我的 Ingress 配置:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: app-angular
spec:
  rules:
    - host: MY_URL
      http:
        paths:
        - backend:
            serviceName: app-backend
            servicePort: 80

我的后端配置:

apiVersion: v1
kind: Service
metadata:
  name: app-backend
spec:
  type: NodePort
  selector:
    app: app-angular
  ports:
  - port: 80
    targetPort: 80

我的部署配置:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app-angular
spec:
  replicas: 2
  revisionHistoryLimit: 2
  template:
    metadata:
      labels:
        app: app-angular
        tier: frontend
    spec:
      containers:
      - name: app-angular
        image: gcr.io/MY_PROJECT/app-angular:MY_TAG
        imagePullPolicy: Always
        ports:
          - containerPort: 80

我的 nginx 配置:

server 
  listen 80;

  root /usr/share/nginx/html;

  location / 

    set_real_ip_from $LB_IP;
    real_ip_header X-Forwarded-For;

    allow 130.211.0.0/22; #Google IP
    allow $CLIENT_IP; # FILTERED IP
    allow 10.0.0.0/8; #internal network
    deny all;

    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  


有什么想法吗?

【问题讨论】:

【参考方案1】:

它们是两种解决方案(感谢 gcbirzan 帮助我解决 GCP 松弛问题):

1) 使用来自 IP 地址范围的良好 IPS 更新我的 nginx 配置:

IP 地址范围可在此处找到:https://console.cloud.google.com/networking/networks/list。 您可以为一个区域或所有需要的区域添加 set_real_ip_from。 不要忘记 real_ip_recursive on;

server 
  listen 80;

  root /usr/share/nginx/html;

  location / 

    set_real_ip_from 10.128.0.0/20;
    ...
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    allow 130.211.0.0/22; #Google IP
    allow $CLIENT_IP; # FILTERED IP
    allow 10.0.0.0/8; #internal network
    deny all;

    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  


2) 更新我的后端配置:

externalTrafficPolicy:本地

apiVersion: v1
kind: Service
metadata:
  name: app-backend
spec:
  type: NodePort
  selector:
    app: app-angular
  ports:
  - port: 80
    targetPort: 80
  externalTrafficPolicy: Local

更新 nginx 配置:

现在 $remote_addr 中显示的 IP 将设置为您的客户端请求的负载均衡器 IP 和 google Infra IPS:130.211.0.0/22,35.191.0.0/16

别忘了real_ip_recursive on;

server 
  listen 80;

  root /usr/share/nginx/html;

  location / 

    set_real_ip_from $LB_IP;
    set_real_ip_from 130.211.0.0/22;
    set_real_ip_from 35.191.0.0/16;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    allow 130.211.0.0/22; #Google IP
    allow 35.191.0.0/16; #Google IP
    allow $CLIENT_IP; # FILTERED IP
    allow 10.0.0.0/8; #internal network
    deny all;

    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  


【讨论】:

【参考方案2】:

您提供的链接专门针对 GCP 负载平衡器。 至于 nginx 负载均衡器,您应该考虑将 ExternalTrafficPolicy annotation 添加到您的 NodePort 服务以保留客户端 IP。

我还发现了一个可追溯到 2017 年年中的类似问题,表明 certain versions of the nginx controller 存在问题,请确保您使用的图像没有此问题。

最后,您可能需要添加 use-proxy-protocol: "true" with the configuration ConfigMap,因为您使用的入口充当使用代理的 HTTP(S) 负载均衡器。

【讨论】:

感谢您的帮助,我找到了解决方案。 ExternalTrafficPolicy 是一个好方法。最后一点是不可能的:use-proxy-protocol: "true" ,因为我没有使用 nginx-ingress,所以我使用 gce ingress 和 nginx 作为我的 Angular 应用程序的 http 服务器。【参考方案3】:

我们在nginx ingress 前面使用HTTP GCLB ingress。为了让RealIP 工作,我添加了

kind: ConfigMap
apiVersion: v1
metadata:
  name: ingress-nginx
  labels:
    k8s-addon: ingress-nginx.addons.k8s.io
data:
  ##
  ## Google Infra Blocks needed
  ##  130.211.0.0/22,35.191.0.0/16
  ##
  ## Google Cloud Load Balancer
  ##  GCLB-IP/32
  proxy-real-ip-cidr: 130.211.0.0/22,35.191.0.0/16,[YOUR-GCLB-IP]/32

这允许nginx 信任来自 Google 基础架构的X-Forwarded-For

【讨论】:

感谢您的帮助,我找到了解决方案。但我没有使用 nginx-ingress,我使用 gce ingress 和 nginx 作为我的 Angular 应用程序的 http 服务器。 啊。谢谢你的澄清。我将nginx with GCE ingress 的提及混为一谈GCLB Ingress in front of nginx Ingress

以上是关于Nginx real_ip_header 通过 GCE 入口?的主要内容,如果未能解决你的问题,请参考以下文章

Nginx之跟踪与调试

nginx服务搭建

在CentOS上安装nginx

Dockerfile构建nginx镜像以及使用nginx -g "daemon off;"方式前台运行

nginx ,node 配置项目

Nginx linux下的安装