real-ip
The real-ip plugin allows APISIX to set the client's real IP by IP address passed in the HTTP header or HTTP query string. This is particularly useful when APISIX is behind a reverse proxy, since the proxy could act as the request originating client otherwise.
The plugin is functionally similar to NGINX's ngx_http_realip_module but offers more flexibilities.
Examples
The examples below demonstrate how you can configure real-ip in different scenarios.
Obtain Real Client Address From URI Parameter
The following example demonstrates how to update client IP address with an URI parameter.
Create a route as follows:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "real-ip-route",
"uri": "/get",
"plugins": {
"real-ip": {
"source": "arg_realip",
"trusted_addresses": ["127.0.0.0/24"]
},
"response-rewrite": {
"headers": {
"remote_addr": "$remote_addr",
"remote_port": "$remote_port"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- name: real-ip-route
uris:
- /get
plugins:
real-ip:
source: arg_realip
trusted_addresses:
- 127.0.0.0/24
response-rewrite:
headers:
remote_addr: $remote_addr
remote_port: $remote_port
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- 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: real-ip-plugin-config
spec:
plugins:
- name: real-ip
config:
source: arg_realip
trusted_addresses:
- 127.0.0.0/24
- name: response-rewrite
config:
headers:
remote_addr: $remote_addr
remote_port: $remote_port
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: real-ip-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: real-ip-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: real-ip-route
spec:
ingressClassName: apisix
http:
- name: real-ip-route
match:
paths:
- /get
upstreams:
- name: httpbin-external-domain
plugins:
- name: real-ip
config:
source: arg_realip
trusted_addresses:
- 127.0.0.0/24
- name: response-rewrite
config:
headers:
remote_addr: $remote_addr
remote_port: $remote_port
Apply the configuration:
kubectl apply -f real-ip-ic.yaml
❶ Configure source to obtain value from the URL parameter realip using the built-in variables.
❷ Use the response-rewrite plugin to set response headers to verify if the client IP and port were actually updated.
Send a request to the route with real IP and port in the URL parameter:
curl -i "http://127.0.0.1:9080/get?realip=1.2.3.4:9080"
You should see the response includes the following headers:
remote_addr: 1.2.3.4
remote_port: 9080
Obtain Real Client Address From Header
The following example shows how to set the real client IP when APISIX is behind a reverse proxy, such as a load balancer, when the proxy exposes the real client IP in the X-Forwarded-For header.
Create a route as follows:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "real-ip-route",
"uri": "/get",
"plugins": {
"real-ip": {
"source": "http_x_forwarded_for",
"trusted_addresses": ["127.0.0.0/24"]
},
"response-rewrite": {
"headers": {
"remote_addr": "$remote_addr"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- name: real-ip-route
uris:
- /get
plugins:
real-ip:
source: http_x_forwarded_for
trusted_addresses:
- 127.0.0.0/24
response-rewrite:
headers:
remote_addr: $remote_addr
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- 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: real-ip-plugin-config
spec:
plugins:
- name: real-ip
config:
source: http_x_forwarded_for
trusted_addresses:
- 127.0.0.0/24
- name: response-rewrite
config:
headers:
remote_addr: $remote_addr
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: real-ip-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: real-ip-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: real-ip-route
spec:
ingressClassName: apisix
http:
- name: real-ip-route
match:
paths:
- /get
upstreams:
- name: httpbin-external-domain
plugins:
- name: real-ip
config:
source: http_x_forwarded_for
trusted_addresses:
- 127.0.0.0/24
- name: response-rewrite
config:
headers:
remote_addr: $remote_addr
Apply the configuration:
kubectl apply -f real-ip-ic.yaml
❶ Configure source to obtain value from the request header X-Forwarded-For using the built-in variables.
❷ Use the response-rewrite plugin to set a response header to verify if the client IP was actually updated.
Send a request to the route:
curl -i "http://127.0.0.1:9080/get" \
-H "X-Forwarded-For: 10.26.3.19"
You should see a response including the following header:
remote_addr: 10.26.3.19
The IP address should correspond to the IP address of the request originating client.
Obtain Real Client Address Behind Multiple Proxies
The following example shows how to get the real client IP when APISIX is behind multiple proxies, which causes X-Forwarded-For header to include a list of proxy IP addresses.
Create a route as follows:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "real-ip-route",
"uri": "/get",
"plugins": {
"real-ip": {
"source": "http_x_forwarded_for",
"recursive": true,
"trusted_addresses": ["192.128.0.0/16", "127.0.0.1/32"]
},
"response-rewrite": {
"headers": {
"remote_addr": "$remote_addr"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- name: real-ip-route
uris:
- /get
plugins:
real-ip:
source: http_x_forwarded_for
recursive: true
trusted_addresses:
- 192.128.0.0/16
- 127.0.0.1/32
response-rewrite:
headers:
remote_addr: $remote_addr
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- 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: real-ip-plugin-config
spec:
plugins:
- name: real-ip
config:
source: http_x_forwarded_for
recursive: true
trusted_addresses:
- 192.128.0.0/16
- 127.0.0.1/32
- name: response-rewrite
config:
headers:
remote_addr: $remote_addr
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: real-ip-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: real-ip-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: real-ip-route
spec:
ingressClassName: apisix
http:
- name: real-ip-route
match:
paths:
- /get
upstreams:
- name: httpbin-external-domain
plugins:
- name: real-ip
config:
source: http_x_forwarded_for
recursive: true
trusted_addresses:
- 192.128.0.0/16
- 127.0.0.1/32
- name: response-rewrite
config:
headers:
remote_addr: $remote_addr
Apply the configuration:
kubectl apply -f real-ip-ic.yaml
❶ Configure source to obtain value from the request header X-Forwarded-For using the built-in variables.
❷ Set recursive to true so that the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the configured source.
❸ Use the response-rewrite plugin to set a response header to verify if the client IP was actually updated.
Send a request to the route:
curl -i "http://127.0.0.1:9080/get" \
-H "X-Forwarded-For: 127.0.0.2, 192.128.1.1, 127.0.0.1"
You should see a response including the following header:
remote_addr: 127.0.0.2