Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: improve real-ip plugin docs #11963

Merged
merged 7 commits into from
Feb 13, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 135 additions & 56 deletions docs/en/latest/plugins/real-ip.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ keywords:
- API Gateway
- Plugin
- Real IP
description: This document contains information about the Apache APISIX real-ip Plugin.
description: The real-ip plugin allows APISIX to set the client's real IP by the IP address passed in the HTTP header or HTTP query string.
---

<!--
Expand All @@ -27,97 +27,176 @@ description: This document contains information about the Apache APISIX real-ip
#
-->

<head>
<link rel="canonical" href="https://docs.api7.ai/hub/real-ip" />
</head>

## Description

The `real-ip` Plugin is used to dynamically change the client's IP address and port as seen by APISIX.
The `real-ip` plugin allows APISIX to set the client's real IP by the 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.

This is more flexible but functions similarly to Nginx's [ngx_http_realip_module](https://nginx.org/en/docs/http/ngx_http_realip_module.html).
The plugin is functionally similar to NGINX's [ngx_http_realip_module](https://nginx.org/en/docs/http/ngx_http_realip_module.html) but offers more flexibility.

:::info IMPORTANT
## Attributes

This Plugin requires APISIX to run on [APISIX-Runtime](../FAQ.md#how-do-i-build-the-apisix-runtime-environment).
| Name | Type | Required | Valid values | Description |
|-----------|---------|----------|----------------|---------------|
| source | string | Yes | Any Nginx variable like `arg_realip` or `http_x_forwarded_for`. |ically Dynam sets the client's IP address and an optional port, or the client's hostname, from APISIX's view.|
| trusted_addresses | array[string] | No | List of IPs or CIDR ranges. | Dynamically sets the `set_real_ip_from` field. |
| recursive | boolean | No | True to enable, false to disable (default is false) | If the recursive search is disabled, the original client address that matches one of the trusted addresses is replaced by the last address sent in the configured `source`. If the recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the configured `source`. |

:::
## Examples

## Attributes
The examples below demonstrate how you can configure `real-ip` in different scenarios.

| Name | Type | Required | Valid values | Description |
|-------------------|---------------|----------|-----------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| source | string | True | Any Nginx variable like `arg_realip` or `http_x_forwarded_for`. | Dynamically sets the client's IP address and an optional port, or the client's host name, from APISIX's view. |
| trusted_addresses | array[string] | False | List of IPs or CIDR ranges. | Dynamically sets the `set_real_ip_from` field. |
| recursive | boolean | False | True to enable, false to disable, default is false | If recursive search is disabled, the original client address that matches one of the trusted addresses is replaced by the last address sent in the configured `source`. If recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the configured `source`. |
### Obtain Real Client Address From URI Parameter

:::note
The following example demonstrates how to update the client IP address with a URI parameter.

If the address specified in `source` is missing or invalid, the Plugin would not change the client address.
Create a route as follows:

:::
```shell
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_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
}
}
}'
```

## Enable Plugin
❶ Configure `source` to obtain value from the URL parameter `realip` using the [built-in variables](/apisix/reference/built-in-variables).

The example below enables the `real-ip` Plugin on the specified Route:
❷ Use the `response-rewrite` plugin to set response headers to verify if the client IP and port were actually updated.

:::note
You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command:
Send a request to the route with real IP and port in the URL parameter:

```bash
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
```shell
curl -i "http://127.0.0.1:9080/get?realip=1.2.3.4:9080"
```

:::
You should see the response includes the following header:

```text
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`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) header.

Create a route as follows:

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/index.html",
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_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"
}
"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": {
"127.0.0.1:1980": 1
}
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
}'
```

## Example usage
❶ Configure `source` to obtain value from the request header `X-Forwarded-For` using the [built-in variables](/apisix/reference/built-in-variables).

❷ Use the `response-rewrite` plugin to set a response header to verify if the client IP was actually updated.

After you have enabled the Plugin as mentioned above, you can test it as shown below:
Send a request to the route:

```shell
curl 'http://127.0.0.1:9080/index.html?realip=1.2.3.4:9080' -I
curl -i "http://127.0.0.1:9080/get"
```

```shell
...
remote-addr: 1.2.3.4
remote-port: 9080
You should see a response including the following header:

```text
remote-addr: 10.26.3.19
```

## Delete Plugin
The IP address should correspond to the IP address of the request-originating client.

### Obtain Real Client Address Behind Multiple Proxies

To remove the `real-ip` Plugin, you can delete the corresponding JSON configuration from the Plugin configuration. APISIX will automatically reload and you do not have to restart for this to take effect.
The following example shows how to get the real client IP when APISIX is behind multiple proxies, which causes [`X-Forwarded-For`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) header to include a list of proxy IP addresses.

Create a route as follows:

```shell
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/index.html",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_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.0/24"]
},
"response-rewrite": {
"headers": {
"remote_addr": "$remote_addr"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
```

❶ Configure `source` to obtain value from the request header `X-Forwarded-For` using the [built-in variables](/apisix/reference/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:

```shell
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:

```text
remote-addr: 127.0.0.2
```