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.

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

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: