IP Whitelisting with AuthorizationPolicy in EKS

The topic of IP whitelisting has been covered many times here, but the examples never quite work for me. Maybe because a lot of the examples assume Google Cloud/GKE? I’ve also noticed that most of the threads discussing IP whitelisting have a post telling everybody that Istio 1.5 deprecates Mixer.

I need the most basic IP whitelisting, only those on our local network. So would a single AuthorizationPolicy in the istio-system namespace be capable of this? Or must one also use an EnvoyFilter to do this?

Finally, all the docs which I’ve read indicate that the Istio Ingress must have externalTrafficPolicy set to Local. This setting makes my demo service flat-out stop working. Is it possible to get the IP whitelisting working without that setting? I suspect it may be because I have actually been able to see the IP I want to allow in the logs. The IP I whitelist comes through in a comma-separated list, so it seems like this would be sufficient to allow for the whitelisting. Especially if I were to write a little Lua in my EnvoyFilter.

But again, I can’t even tell if I’m supposed to use EnvoyFilter with AuthorizationPolicy…

Any pointers would be appreciated!

Finally, got something working, though not by using AuthorizationPolicy. Figured I would share this Yaml which finally made it work:

apiVersion: v1
kind: Service
metadata:
  name: httpbin
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
spec:
  type: NodePort
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: httpbin

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        name: httpbin
        ports:
        - containerPort: 80
          name: http

---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: rsl-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "*"
  gateways:
  - rsl-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: httpbin
      weight: 100

---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: rsl-envoyfilter
  namespace: istio-system
spec:
  workloadLabels:
    app: istio-ingressgateway
  filters:
    - listenerMatch:
        portNumber: 80
        listenerType: GATEWAY
      filterName: envoy.lua
      filterType: HTTP
      filterConfig:
        inlineCode: |
          function envoy_on_request(request_handle)
            local xff_header = request_handle:headers():get("X-Forwarded-For")
            local first_ip = string.gmatch(xff_header, "(%d+.%d+.%d+.%d+)")();
            first_ip = string.gsub(first_ip, ",", "")
            request_handle:headers():add("X-Custom-User-IP", first_ip);
          end

---
apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
  name: rsl-whitelistip
spec:
  compiledAdapter: listchecker
  params:
    overrides:
      - <redacted>
      - <redacted>
    blacklist: false
    entryType: IP_ADDRESSES
---
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
  name: rsl-sourceip
spec:
  compiledTemplate: listentry
  params:
    value: request.headers["x-custom-user-ip"] | "0.0.0.0"
---
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: checkip
spec:
  match: source.labels["istio"] == "ingressgateway"
  actions:
  - handler: rsl-whitelistip
    instances: [ rsl-sourceip ]
2 Likes

oh yeah ! thanks for you, this method works !!!

This is now supported in the AuthorizationPolicy in the new remoteIpBlocks field, check the updated task Istio / Authorization on Ingress Gateway for how to configure the trusted IPs in the X-Forwarded-For header.

EKS’ LB type is TCP Proxy, its Source of Client IP is Proxy Protocol.

Istio / Ingress Gateway

I have a same issue, even use remoteIpBlocks can’t filter allowed IP. My site returned RBAC access denied.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ingress-policy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
       remoteIpBlocks: ["ALLOWED PUBLIC IP"]

From Istio’s ingress gateway log I got

...
2021-12-21T03:36:41.819072Z     debug   envoy rbac      checking request: requestedServerName: , sourceIP: 10.123.45.111:25965, directRemoteIP: 10.123.45.111:25965, remoteIP: 10.123.45.111:25965,localAddress: 10.123.46.222:8443, ssl: uriSanPeerCertificate: , dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', '10.123.45.111:30974'
':path', '/healthz/ready'
':method', 'GET'
':scheme', 'https'
'user-agent', 'ELB-HealthChecker/2.0'
'accept-encoding', 'gzip, compressed'
'x-forwarded-for', '10.123.45.111'
'x-forwarded-proto', 'https'
'x-envoy-internal', 'true'
'x-request-id', '123412231a-cb12-9732-859e-0213jladfsj9'
'x-envoy-decorator-operation', 'demo-service.default.svc.cluster.local:80/*'
, dynamicMetadata:
2021-12-21T03:36:41.819091Z     debug   envoy rbac      enforced allowed, matched policy none

What’s wrong with this case?

gateway could not see the original src in your case

How to make gateway see the original src then? I’m using AWS running Istio now.

I installed Istio with NodePort ingress gateway type

istioctl install \
--set profile=demo \
--set values.gateways.istio-ingressgateway.type=NodePort

Should I change the type to LoadBalancer?