2

Hello anyone who reads this,

I'm looking for a way to restrict access to a publically exposed service (type LoadBalancer) at 234.234.234.234:1234 to a specific trusted IP at 123.123.123.123.

The way to do this seems to be via nginx.ingress.kubernetes.io/whitelist-source-range: 123.123.123.123/32 as described in articles such as this: https://medium.com/@maninder.bindra/using-nginx-ingress-controller-to-restrict-access-by-ip-ip-whitelisting-for-a-service-deployed-to-bd5c86dc66d6

However, this runs into a problem because the default externalTrafficPolicy being set to "Cluster" obfuscates the sender IP to some local bs even for the bloody Ingress controller.

The solution to this appears to be to set controller.service.externalTrafficPolicy to Local, but I'm not sure about the ramifications of that since it changes the entire way of addressing pods and I've read some posts about performance issues with this approach. There is also the problem that the resource in question already exists and I'd have to recreate it fully, apparently. Every post I've read on this seems to assume your resource doesn't exist yet.

I wonder if there is a way to lift the source IP obfuscation without a change as large-looking as that.

2 Answers2

2

To implement IP whitelisting in a public Kubernetes service with the Nginx Ingress controller, you need to configure the externalTrafficPolicy to Local to preserve the client's IP address. By default, the externalTrafficPolicy is set to Cluster, which means that traffic from the client is routed to any node in the cluster, and this can obfuscate the original client IP address.

To retain the client's IP address, set the externalTrafficPolicy to Local for your LoadBalancer service:

example

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 1234
    targetPort: 5678
  type: LoadBalancer
  externalTrafficPolicy: Local

This setting ensures that external traffic is routed directly to the nodes where the pods are running, preserving the client's IP address.

enter image description here

You can update an existing service by applying this configuration, or you can patch the service using

kubectl patch service myapp-service -p '{"spec":{"externalTrafficPolicy":"Local"}}'

Next, configure the Ingress resource for IP whitelisting using the nginx.ingress.kubernetes.io/whitelist-source-range annotation:

example

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: "123.123.123.123/32"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 1234

enter image description here

This configuration restricts access to the Ingress to the specified IP address 123.123.123.123 and will use IP whitelisting in Nginx Ingress for a public service, setting externalTrafficPolicy to Local and preserve the client IP.

Another way to restrict access to a publicly exposed service in AKS is you can use the nginx.ingress.kubernetes.io/whitelist-source-range annotation to whitelist a specific trusted IP. However, the default externalTrafficPolicy being set to "Cluster" can obfuscate the sender IP, even for the Ingress controller. To lift the source IP obfuscation without changing the externalTrafficPolicy, you can use the nginx.ingress.kubernetes.io/real-ip-header annotation to specify the header that contains the real IP address of the client. Set the value to X-Forwarded-For to use the X-Forwarded-For header.

example-

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: "123.123.123.123/32"
    nginx.ingress.kubernetes.io/real-ip-header: "X-Forwarded-For"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              name: http

This example uses the nginx.ingress.kubernetes.io/real-ip-header annotation to specify the X-Forwarded-For header as the header that contains the real IP address of the client. This allows you to lift the source IP obfuscation without changing the externalTrafficPolicy.

Using either externalTrafficPolicy: Local or the real-ip-header annotation with X-Forwarded-For approach to achieve IP whitelisting with Nginx Ingress in AKS are valid, and the choice between them depends on the specific requirements and network architecture.

References:

Arko
  • 151
  • 2
0

"Setting the externalTrafficPolicy to Local comes with potential downsides such as Load Distribution: Traffic is only sent to nodes with relevant pods or in case of pod failures, the service won't reroute traffic to other nodes unless a relevant pod is available on those nodes." - Arko

This explanation resolved my doubts about using externalTrafficPolicy: Local in my specific use case.