Kubernetes 上的 Traefik 在传入连接上错误的客户端 IP

Jus*_*tin 8 networking docker kubernetes traefik traefik-ingress

我在 Kubernetes 上运行 Traefik,并使用以下配置创建了一个 Ingress:

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: whitelist-ingress
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.frontend.rule.type: PathPrefix
    traefik.ingress.kubernetes.io/whitelist-source-range: "10.10.10.10/32, 10.10.2.10/23"
    ingress.kubernetes.io/whitelist-x-forwarded-for: "true"
    traefik.ingress.kubernetes.io/preserve-host: "true"
spec:
  rules:
  - host:
    http:
      paths:
      - path: /endpoint
        backend:
          serviceName: endpoint-service
          servicePort: endpoint-port
---
Run Code Online (Sandbox Code Playgroud)

当我在上述端点上执行 POST 时,Traefik 记录传入 IP 为 172.16.0.1,因此未触发我的白名单。做一个 ifconfig 我看到 IP 属于 Docker

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.26.0.1  netmask 255.255.0.0  broadcast 172.26.255.255
Run Code Online (Sandbox Code Playgroud)

如何保留原始 IP 而不是 docker IP?

编辑

Traefik 作为 LoadBalancer 公开,端口是 443 通过 SSL

这是它的yml配置

---
kind: Service
apiVersion: v1
metadata:
  name: traefik
  annotations: {}
    # service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
spec:
  selector:
    k8s-app: traefik-ingress
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    name: http
  - protocol: TCP
    port: 443
    targetPort: 443
    name: https
  type: LoadBalancer
  externalTrafficPolicy: Local
  externalIPs:
  - <machine-ip>
---

kind: Deployment
apiVersion: apps/v1
metadata:
  name: traefik-ingress-controller
  namespace: default
  labels:
    k8s-app: traefik-ingress
spec:
  replicas: 2
  selector:
    matchLabels:
      k8s-app: traefik-ingress
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress
        name: traefik-ingress
    spec:
      hostNetwork: true
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 35
      volumes:
        - name: proxy-certs
          secret:
            secretName: proxy-certs
        - name: traefik-configmap
          configMap:
            name: traefik-configmap
      containers:
      - image: traefik:1.7.6
        name: traefik-ingress
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: 200m
            memory: 900Mi
          requests:
            cpu: 25m
            memory: 512Mi
        livenessProbe:
          failureThreshold: 2
          httpGet:
            path: /ping
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 5
        readinessProbe:
          failureThreshold: 2
          httpGet:
            path: /ping
            port: 80
            scheme: HTTP
          periodSeconds: 5
        volumeMounts:
          - mountPath: "/ssl"
            name: "proxy-certs"
          - mountPath: "/config"
            name: "traefik-configmap"
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        - name: dashboard
          containerPort: 8080
        args:
        - --logLevel=DEBUG
        - --configfile=/config/traefik.toml
---
Run Code Online (Sandbox Code Playgroud)

如您所见,这里是 kubectl get svc 的输出

traefik                       LoadBalancer   10.100.116.42    <machine-ip>     80:30222/TCP,443:31578/TCP   <days-up>
Run Code Online (Sandbox Code Playgroud)

请注意,Traefik 运行在单节点 kubernetes 集群中(主节点/工作节点在同一节点上)。

小智 2

在 LoadBalancer service type doc ssl support on aws中,您可以阅读以下声明:

\n\n
\n

HTTP 和 HTTPS 将选择第 7 层代理:ELB 将终止与用户的连接,解析标头并使用用户的 IP 地址注入 X-Forwarded-For 标头(Pod 只会看到转发请求时,连接另一端的 ELB 的 IP 地址。

\n
\n\n

因此,如果您将以下注释添加到 traeffik 服务中:

\n\n
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: https\n
Run Code Online (Sandbox Code Playgroud)\n\n

它应该与ingress.kubernetes.io/whitelist-x-forwarded-for: "true"入口配置中存在的注释配合使用,并且转发的标头由 aws 负载均衡器添加。

\n\n

免责声明:我尚未测试该解决方案。

\n\n

问候。

\n