Restrict Access by Gateway/Service using source ip

I need restrict based on source ip.
I trying use AuthorizationPolicy for this

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: deny-all
 namespace: eng
spec:
 selector:
   matchLabels:
     app: ords-frontend
 action: DENY
 rules:
 - from:
   - source:
       notIpBlocks: ["187.103.152.251/32"]

I think this problem occurs because I don’t recivie the source ip from the client and is required by notIpBlocks and i don’t understand reason.

user --> LB(80) --> istio-gateway(31380) --> Virtual Service --> Pod

The LB Listen on port 80 and the istio-gateway listen port 31380 using nodeport.

I can see traffic between lb and istio-gateway show the real client ip.

14:00:50.142249 IP 192.168.224.137.31380 > 187.103.152.251.33544: Flags [P.], seq 1:168, ack 540, win 309, options [nop,nop,TS val 934972807 ecr 2749116122], length 167
14:00:50.142840 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [.], ack 168, win 510, options [nop,nop,TS val 2749116127 ecr 934972807], length 0
14:00:50.389345 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [P.], seq 540:1080, ack 168, win 511, options [nop,nop,TS val 2749116372 ecr 934972807], length 540
14:00:50.391023 IP 192.168.224.137.31380 > 187.103.152.251.33544: Flags [P.], seq 168:335, ack 1080, win 317, options [nop,nop,TS val 934973056 ecr 2749116372], length 167
14:00:50.391595 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [.], ack 335, win 510, options [nop,nop,TS val 2749116376 ecr 934973056], length 0
14:00:50.576550 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [P.], seq 1080:1620, ack 335, win 511, options [nop,nop,TS val 2749116560 ecr 934973056], length 540
14:00:50.577706 IP 192.168.224.137.31380 > 187.103.152.251.33544: Flags [P.], seq 335:502, ack 1620, win 325, options [nop,nop,TS val 934973243 ecr 2749116560], length 167
14:00:50.578293 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [.], ack 502, win 510, options [nop,nop,TS val 2749116563 ecr 934973243], length 0

the tcpdump was executed in k8s server where istio-gateway is running

I defined the parameter externalTrafficPolicy to Local

kubectl patch svc istio-ingressgateway -n istio-system -p ‘{“spec”:{“externalTrafficPolicy”:“Local”}}’

Below is my configuration by gateway and virtual services

---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gw-eng-ords-frontend
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "engenharia.xxxx.local" 
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-gw-eng-ords-frontend
spec:
  hosts:
  - "*"
  gateways:
  - gw-eng-ords-frontend
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: ords-frontend
        port:
          number: 80
    timeout: 900s
---```

I need restrict the access to url engenharia.xxxx.local for source ip.

Am I do some configuration wrong ?

Hi @rlljorge

Not sure on this. In your AuthorizationPolicy you mention

matchLabels:
     app: ords-frontend

may be you should mention

matchLabels:                  
   app: istio-ingressgateway

i mentioned this when i am doing Authorization on Ingress Gateway task https://istio.io/docs/tasks/security/authorization/authz-ingress/#ip-based-allow-list-and-deny-list
and also ceck the hosts field ( A VirtualService must be bound to the gateway and must have one or more hosts that match the hosts specified in a server. The match could be an exact match or a suffix match with the server’s hosts.) https://istio.io/docs/reference/config/networking/gateway/#Server
give a try.

Hi, @Shubham

I applied on istio-ingressgateway because I have other gateways and I need restrict different source ip for each.

kubectl get gateways.networking.istio.io --all-namespaces
NAMESPACE   NAME                    AGE
aten        gw-aten-jasperserver    13h
aten        gw-aten-ords-frontend   13h
default     gw-gitlab               14d
default     gw-jasperserver         14d
eng         gw-eng-jasperserver     13h
eng         gw-eng-ords-frontend    13h

I applied on istio-ingress gateway for testing.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: deny-all
 namespace: istio-system
spec:
 selector:
   matchLabels:
     app: istio-ingressgateway
 action: DENY
 rules:
 - from:
   - source:
       notIpBlocks: ["187.103.152.251/32"]

This blocked the access for all gateway/virtual servers including the addresss ip in notIpBlocks.

RBAC: access denied

unfortunately it didn’t work.

If a change notIpBlocks from 187.103.152.251/32 to 10.32.0.0/12 I can access.
I thing this shows that the real source ip address isn’t detect on istio-gateway

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: deny-all
 namespace: istio-system
spec:
 selector:
   matchLabels:
     app: istio-ingressgateway
 action: DENY
 rules:
 - from:
   - source:
       notIpBlocks: ["10.32.0.0/12"]

I defined the externalTrafficPolicy:Local in istio-ingressgateway.

Someone have any ideia ?

Hi
you can try with namespace in which your gateway is like default. AFAIK namespace: istio-system
apply the policy to all gateway (which reference to istio-ingressgateway) in the mesh.

may be this will help you

@Shubham I tried this away in previous test

...
metadata:
 name: deny-all
 namespace: istio-system
spec:
 selector:
   matchLabels:
     app: istio-ingressgateway
 action: DENY 
...

I did not succeed …

@YangminZhu @incfly can you help on this.(pls)

Hi ! I am keep looking for a solution for this

Can I do this using istio ?

Thanks

The source IP in authorization policy is the IP of the direct peer in front of it, Is “10.32.0.0” the IP of your LB? How does your LB forwards the request to istio? Unless your LB puts the real source IP somewhere in the request, istio won’t be able to see it.

If you LB uses the forward header to pass the end user IP, it may be supported later when the downstream IP suppot is added to the authorization policy, see https://github.com/istio/istio/issues/22341 for more info.

@YangminZhu Thanks for answering

My load balancer is a haproxy in transparent mode, I can see the real client ip in tcpdump.
This tcpdump was executed on kubernetes work node where the istio-ingressgateway pod is execute.

14:00:50.142249 IP 192.168.224.137.31380 > 187.103.152.251.33544: Flags [P.], seq 1:168, ack 540, win 309, options [nop,nop,TS val 934972807 ecr 2749116122], length 167
14:00:50.142840 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [.], ack 168, win 510, options [nop,nop,TS val 2749116127 ecr 934972807], length 0
14:00:50.389345 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [P.], seq 540:1080, ack 168, win 511, options [nop,nop,TS val 2749116372 ecr 934972807], length 540
14:00:50.391023 IP 192.168.224.137.31380 > 187.103.152.251.33544: Flags [P.], seq 168:335, ack 1080, win 317, options [nop,nop,TS val 934973056 ecr 2749116372], length 167
14:00:50.391595 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [.], ack 335, win 510, options [nop,nop,TS val 2749116376 ecr 934973056], length 0
14:00:50.576550 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [P.], seq 1080:1620, ack 335, win 511, options [nop,nop,TS val 2749116560 ecr 934973056], length 540
14:00:50.577706 IP 192.168.224.137.31380 > 187.103.152.251.33544: Flags [P.], seq 335:502, ack 1620, win 325, options [nop,nop,TS val 934973243 ecr 2749116560], length 167
14:00:50.578293 IP 187.103.152.251.33544 > 192.168.224.137.31380: Flags [.], ack 502, win 510, options [nop,nop,TS val 2749116563 ecr 934973243], length 0

The ip addres 187.103.152.251 is a real client.
The ip addres 192.168.224.137 is the local network for kubernetes node.

My loadbalancer listen the 187.103.145.30:80 and send in trasparent mode to 192.168.224.137:31380.

The 31380 is the istio-ingressgateway service is configure to NodePort type.

istio-ingressgateway NodePort 10.99.165.158 15020:30397/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31585/TCP,15030:30864/TCP,15031:31896/TCP,15032:31991/TCP,15443:32560/TCP

I cannot find the problem, the real ip arrived to kubernetes node but for some reason cannot be read by istio.

Solved !

Solved ! The CNI didn’t send the source ip.

Thank you @YangminZhu and @Shubham

Hello, how did you solve it? I have the same problem