How to Use IP Restriction Plugin

This plugin can be very handed when you need to restrict access to your api services. Its settings are quite easy to understand. There are only two variables to control how users want to restrict access.

Users can use either config.allow or config.deny to allow or deny access from a single ip or ip range in CIDR notation. These two variables are arrays meaning you can add multiple ip or ip ranges to them.

Let me use some examples to demonstrate how this works.

Usage example

In the first part, I will use Admin API to set up IP Restriction plugin

Prerequisite : A Kong instance running with Admin API

You can find official documentation here.

Let’s begin:

Create a service

1
2
3
4
5
curl -X POST \
--url http://localhost:8001/services \
--header "Content-Type: application/json" \
--header "Accept: application/json, */*" \
--data '{"name":"ip-restrict-service","url":"https://httpbin.org/anything"}'

Create Route

1
2
3
4
5
curl -X POST \
--url http://localhost:8001/services/ip-restrict-service/routes \
--header "Content-Type: application/json" \
--header "Accept: application/json, */*" \
--data '{"name":"ip-restrict-route","paths":["/ip"]}'

When we visit our route, we should get HTTP/1.1 200 OK and result as below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "HTTPie/2.4.0",
"X-Forwarded-Host": "localhost",
"X-Forwarded-Path": "/ip",
"X-Forwarded-Prefix": "/ip"
},
"json": null,
"method": "GET",
"origin": "192.168.160.1",
"url": "https://localhost/anything"
}

Notice that we were accessing our service at ip 192.168.160.1

Enable plugin to deny access

You can also enable this plugin on a service or route.

1
2
3
4
5
curl -X POST \
--url http://localhost:8001/plugins \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data name=ip-restriction \
--data config.deny=192.168.160.1

If we visit the route again, we will get HTTP/1.1 403 Forbidden

1
2
3
{
"message": "Your IP address is not allowed"
}

cURL from another IP

Create an Nginx container

1
docker run --network=kong-ce-net --name=nginx-test -d nginx:alpine

Get in to nginx container

1
docker exec -it nginx-test sh

Test curl

1
curl http://kong-ce:8000/ip -i

We should get HTTP/1.1 200 OK again and this time we got

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.74.0",
"X-Amzn-Trace-Id": "Root=1-605b4bf7-7edfd453701dc2a84ffceaf0",
"X-Forwarded-Host": "kong-ce",
"X-Forwarded-Path": "/ip",
"X-Forwarded-Prefix": "/ip"
},
"json": null,
"method": "GET",
"origin": "192.168.160.3",
"url": "https://kong-ce/anything"
}

As we can see our IP address is 192.168.160.3, that’s why we can access this route again.

Enable plugin to ONLY allow access

Let’s delete the previous plugin first and then apply below.

1
2
3
4
5
curl -X POST \
--url http://localhost:8001/routes/ip-restrict-route/plugins \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data name=ip-restriction \
--data config.allow=192.168.160.3

Now the plugin only allows access from the nginx-test container.

Other deployments methods

DBless deployment

Please save below content to kong.yaml and load it to your dbless deployment configuration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
_format_version: "2.1"
_transform: true

services:
- name: ip-restrict-service
url: https://httpbin.org/anything
routes:
- name: ip-restrict-route
paths:
- /ip

plugins:
- name: ip-restriction
config:
allow:
- 192.168.186.1
route: ip-restrict-route

After successfully deploying your Kong instance, you should only be able to access /ip route from nginx-test container.

Kubernetes Ingress Controller

Please change <CLIENT_CERT_CN_NAME> of your consumer object and put your CA root crtificate in x509 format.

Below example will deploy :

  • Echo deployment
  • Echo Service
  • IP restriction plugin
  • Ingress rule to use IP Restriction plugin

Please save below to ip.yaml and use kubectl apply -f ip.yaml to apply it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-deployment
spec:
replicas: 1
selector:
matchLabels:
app: echo-pod
template:
metadata:
labels:
app: echo-pod
spec:
containers:
- name: echoheaders
image: k8s.gcr.io/echoserver:1.10
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: echo-service
spec:
selector:
app: echo-pod
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: proxy-to-echo
annotations:
konghq.com/plugins: ip-allow-ip
konghq.com/strip-path: "true"
spec:
ingressClassName: kong
rules:
- http:
paths:
- backend:
service:
name: echo-service
port:
number: 80
path: /ip
pathType: Prefix
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: ip-allow-ip
config:
allow:
- 192.168.186.1
plugin: ip-restriction

Extended information

There is one settings users need to know about is how to get the correct client_ip when you are running Kong behind a proxy or load balancer. For more information about getting client ip behind proxy, please refer to this serverfault answer.

When Kong is behind the proxy or LB, it sees the traffic from IP_address of the proxy or LB instead of the correct client ip. To solve this issue, there are 3 kong variables you need to use.

After enabling these 3 variables, Kong will get the correct client ip again.