跳到主要内容

real-ip

real-ip 插件允许 APISIX 通过 HTTP 请求头或 HTTP 查询字符串中传递的 IP 地址来设置客户端的真实 IP。当 APISIX 位于反向代理之后时,这特别有用,因为否则代理可能会充当请求发起客户端。

该插件的功能类似于 NGINX 的 ngx_http_realip_module,但提供了更大的灵活性。

信任转发的客户端信息

以下两项信任设置分别作用于不同范围:

  • 全局配置 apisix.trusted_addresses 用于标识直接连接到网关的可信反向代理。网关可以保留这些代理提供的 ForwardedX-Forwarded-* 请求头;OpenID Connect 重定向 URI 的自动构建等功能,也只会对来自这些地址的请求使用转发的协议、主机和端口。此设置本身不会重写网关识别的客户端 IP。
  • 插件字段 trusted_addresses 用于限制哪些直接对等端可以在路由上提供 source 所指定的值。对等端受信任时,插件会使用该来源重写网关识别的客户端 IP。

只应配置你所管理的代理地址。信任任意地址会允许客户端伪造其表面上的 IP 地址、协议、主机或端口。当对等端未通过适用的信任检查时,网关会保留直接连接地址,并替换或清除不受信任的转发来源请求头。

示例

下面的示例展示了如何在不同场景下配置 real-ip

从 URI 参数获取真实客户端地址

以下示例展示了如何使用 URI 参数更新客户端 IP 地址。

创建一个路由如下:

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
}
}
}'

❶ 配置 source 以使用 内置变量 从 URL 参数 realip 获取值。

❷ 使用 response-rewrite 插件设置响应头,以验证客户端 IP 和端口是否实际已更新。

在 URL 参数中带上真实 IP 和端口发送请求到该路由:

curl -i "http://127.0.0.1:9080/get?realip=1.2.3.4:9080"

你应该看到响应包含以下请求头:

remote_addr: 1.2.3.4
remote_port: 9080

从请求头获取真实客户端地址

以下示例展示了当 APISIX 位于反向代理(如负载均衡器)之后时,如果代理在 X-Forwarded-For 请求头中暴露了真实客户端 IP,如何设置真实客户端 IP。

创建一个路由如下:

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
}
}
}'

❶ 配置 source 以使用 内置变量 从请求头 X-Forwarded-For 获取值。

❷ 使用 response-rewrite 插件设置响应头,以验证客户端 IP 是否实际已更新。

发送请求到该路由:

curl -i "http://127.0.0.1:9080/get" \
-H "X-Forwarded-For: 10.26.3.19"

你应该看到包含以下请求头的响应:

remote_addr: 10.26.3.19

IP 地址应对应于请求发起客户端的 IP 地址。

从多层代理后获取真实客户端地址

以下示例展示了当 APISIX 位于多层代理之后时,如何获取真实客户端 IP,这会导致 X-Forwarded-For 请求头包含代理 IP 地址列表。

创建一个路由如下:

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
}
}
}'

❶ 配置 source 以使用 内置变量 从请求头 X-Forwarded-For 获取值。

❷ 将 recursive 设置为 true,以便将与受信任地址之一匹配的原始客户端地址替换为配置的 source 中发送的最后一个非受信任地址。

❸ 使用 response-rewrite 插件设置响应头,以验证客户端 IP 是否实际已更新。

发送请求到该路由:

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"

你应该看到包含以下请求头的响应:

remote_addr: 127.0.0.2