ip-restriction
The ip-restriction plugin supports restricting access to upstream resources by IP addresses, through either configuring a whitelist or blacklist of IP addresses. Restricting IP to resources helps prevent unauthorized access and harden API security.
Examples
The examples below demonstrate how you can configure the ip-restriction plugin for different scenarios.
Restrict Access by Whitelisting
The following example demonstrates how you can whitelist a list of IP addresses that should have access to the upstream resource and customize the error message for access denial.
- Admin API
- ADC
- Ingress Controller
Create a route with the ip-restriction plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "ip-restriction-route",
"uri": "/anything",
"plugins": {
"ip-restriction": {
"whitelist": [
"192.168.0.1/24"
],
"message": "Access denied"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: ip-restriction-service
routes:
- name: ip-restriction-route
uris:
- /anything
plugins:
ip-restriction:
whitelist:
- "192.168.0.1/24"
message: "Access denied"
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Preview the changes and confirm that they only affect resources for this guide:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=ip-restriction
Synchronize the configuration to the gateway:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=ip-restriction
When testing locally with kubectl port-forward, APISIX sees 127.0.0.1 as the client IP regardless of your machine's actual IP address. Make sure your whitelist or blacklist includes 127.0.0.1 when testing in this setup.
A NodePort or LoadBalancer Service does not preserve the client IP by default. To preserve it, set the gateway Service's externalTrafficPolicy to Local and ensure that the external load balancer forwards the source IP. This setting routes only to node-local gateway pods, so traffic can be uneven and a node without a local endpoint drops the request. If a trusted proxy replaces the source IP, configure the real-ip plugin to obtain it from the proxy-provided value instead.
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ip-restriction-plugin-config
spec:
plugins:
- name: ip-restriction
config:
whitelist:
- "192.168.0.1/24"
message: "Access denied"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ip-restriction-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ip-restriction-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f ip-restriction-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ip-restriction-route
spec:
ingressClassName: apisix
http:
- name: ip-restriction-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: ip-restriction
enable: true
config:
whitelist:
- "192.168.0.1/24"
message: "Access denied"
Apply the configuration to your cluster:
kubectl apply -f ip-restriction-ic.yaml
❶ Replace with the IP addresses you would like to whitelist.
❷ Customize the error message for when the access is denied.
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
If your IP is allowed, you should receive an HTTP/1.1 200 OK response. If not, you should receive an HTTP/1.1 403 Forbidden response with the following error message:
{"message":"Access denied"}
Restrict Access Using Modified IP
The following example demonstrates how you can modify the IP used for IP restriction, using the real-ip plugin. This is particularly useful if APISIX is behind a reverse proxy and the real client IP is not available to APISIX.
- Admin API
- ADC
- Ingress Controller
Create a route as follows:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "ip-restriction-route",
"uri": "/anything",
"plugins": {
"ip-restriction": {
"whitelist": [
"192.168.1.241"
]
},
"real-ip": {
"source": "arg_realip"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
❶ Obtain client IP address from the URL parameter realip using the built-in variables.
services:
- name: ip-restriction-service
routes:
- name: ip-restriction-route
uris:
- /anything
plugins:
ip-restriction:
whitelist:
- "192.168.1.241"
real-ip:
source: arg_realip
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
❶ Obtain client IP address from the URL parameter realip using the built-in variables.
Preview the changes and confirm that they only affect resources for this guide:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=ip-restriction
Synchronize the configuration to the gateway:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=ip-restriction
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ip-restriction-realip-plugin-config
spec:
plugins:
- name: ip-restriction
config:
whitelist:
- "192.168.1.241"
- name: real-ip
config:
source: arg_realip
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ip-restriction-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ip-restriction-realip-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ip-restriction-route
spec:
ingressClassName: apisix
http:
- name: ip-restriction-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: ip-restriction
enable: true
config:
whitelist:
- "192.168.1.241"
- name: real-ip
enable: true
config:
source: arg_realip
❶ Obtain client IP address from the URL parameter realip using the built-in variables.
Apply the configuration to your cluster:
kubectl apply -f ip-restriction-ic.yaml
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything?realip=192.168.1.241"
You should receive an HTTP/1.1 200 OK response.
Send another request with a different IP address:
curl -i "http://127.0.0.1:9080/anything?realip=192.168.10.24"
You should receive an HTTP/1.1 403 Forbidden response.