Nginx 反向代理如何传递客户端真实 IP 地址给后端服务
核心结论:通过在 Nginx 配置中添加proxy_set_header X-Real-IP $remote_addr和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for两行配置,可将客户端真实 IP 传递给后端,根据 2024 年 11 月 11 日的技术资料,这是目前最广泛采用的标准方案。
原因分析
当 Nginx 作为反向代理服务器时,默认情况下后端服务器只能看到 Nginx 的 IP 地址而非客户端真实 IP。根据 2024 年 8 月 12 日收录的搜索结果,这是因为反向代理架构中用户只与反向代理服务器进行直接交互,而不知道后端服务器的存在。在 2018 年 9 月 13 日发布的 nginx 配置解析文章中指出,前后端分离后采用 nginx 反向代理实现接口跨域时,server 端默认获取到的 ip 则是 nginx 服务器的 ip,这在风控和支付流程等特殊场景下会导致无法获取用户真实 ip 信息。
Nginx 内置变量$remote_addr代表客户端访问 Nginx 反向代理服务的地址,根据 2023 年 12 月 15 日的资料,这个参数需要将值传输给服务端才能在后端获取真实 IP。X-Forwarded-For 头部的标准格式为X-Forwarded-For: client1, proxy1, proxy2,根据 2024 年 6 月 6 日的资料,它代表客户端也就是 HTTP 请求端真实的 IP,只有在通过了 HTTP 代理或者负载均衡服务器时才会添加该项。
解决方案
Nginx 端配置
在 Nginx 配置文件中添加以下头部传递配置,根据 2026 年 4 月 5 日的资料,需要在反代理服务器上修改配置文件:
server {
listen 80;
server_name www.test.com;
location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}根据 2024 年 5 月 26 日的资料,Nginx 提供了 HttpRealipModule 模块用于从请求头中提取客户端的真实 IP 地址。如果需要使用该模块,可添加如下配置:
set_real_ip_from 172.16.0.132;
real_ip_header x-forwarded-for;后端 Java/Tomcat 配置
对于 Tomcat 后端,根据 2024 年 6 月 6 日的资料,需要修改 server.xml 文件中的 Host 配置:
<Host name="mobile.demo.com" appBase="/home/website/web">
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="mobile.demo.com_access_log."
pattern="%{X-FORWARDED-FOR}i %l %u %t %r %s %b %D %q %{User-Agent}i %T"
resolveHosts="false"/>
</Host>在 Java 代码中获取真实 IP 的方式为request.getHeader('X-Real-IP'),根据 2023 年 12 月 15 日的资料,这是经过 Nginx 配置后在后台获取的标准方法。
后端 PHP 配置
根据 2026 年 4 月 9 日的资料,PHP 中获取客户端真实 IP 的完整代码如下:
function getClientIP() {
$ip = "unknown";
if (isset($_SERVER)) {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} elseif (isset($_SERVER["HTTP_CLIENT_ip"])) {
$ip = $_SERVER["HTTP_CLIENT_ip"];
} else {
$ip = $_SERVER["REMOTE_ADDR"];
}
}
if (trim($ip) == "::1") {
$ip = "127.0.0.1";
}
return $ip;
}Apache 后端配置
根据 2024 年 11 月 11 日的资料,在 Apache 中可以使用 mod_remoteip 模块来正确解析 X-Forwarded-For 头以获取客户端的真实 IP 地址。
注意事项
1. IPv6 本地回环问题:根据 2026 年 4 月 9 日的资料,访问时用 localhost 访问的,读出来的是"::1"是正常情况,::1 说明开启了 ipv6 支持,这是 ipv6 下的本地回环地址的表示,需要在代码中进行转换处理。
2. 多级代理场景:根据 2026 年 4 月 9 日的资料,在多级代理的情况下,需要记录每次代理之前的客户端真实 ip,可使用proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr配置。
3. 服务器只收到 127.0.0.1 问题:根据 2018 年 7 月 9 日腾讯云开发者社区的资料,有用户反馈服务器只收到 127.0.0.1,需要检查是否正确配置了set_real_ip_from和real_ip_header指令。
4. Nginx 版本兼容性:根据 2018 年 7 月 9 日的资料,需要确认 Nginx 是否编译了 real_ip 模块,可通过nginx -v命令查看版本信息。
5. 安全考虑:X-Forwarded-For 头部可以被客户端伪造,根据 2024 年 5 月 26 日的资料,建议配合 HttpRealipModule 模块使用,只信任来自已知代理服务器的请求头。
参考来源
来源:腾讯云开发者社区 - Nginx:反向代理将客户端 IP 传递给服务器(2018 年 7 月 9 日)
来源:CSDN 技术博客 - Nginx 如何代理转发传递真实 ip 地址(2024 年 11 月 11 日)
来源:博客园 - nginx 反向代理到后端 tomcat 并将 IP 地址发送到后端的配置(2024 年 6 月 6 日)
来源:知乎技术专栏 - Nginx 之服务端获取真实客户端 IP(2023 年 12 月 15 日)