引言
在现代生产环境中,nginx 作为反向代理服务器被广泛应用于服务的暴露与负载均衡。尤其是在面对公网访问时,通常会在 nginx 前端部署 cdn 或云厂商负载均衡器,以提升访问性能与安全性。如何准确获取并传递客户端的真实 ip,成为开发与运维的重要课题。
本文将详细剖析 nginx 获取客户端真实 ip 的原理、配置方法以及常用变量的使用场景,帮助您在不同协议与架构下正确处理客户端 ip。
反向代理与客户端 ip 获取的基本问题
默认情况下,nginx 并不会自动修改或添加请求头中的 x-forwarded-for
,这意味着:
- 如果前端的负载均衡器或 cdn 不传递
x-forwarded-for
,nginx 获取到的客户端 ip 实际上是负载均衡器的 ip。 - 如果前端已经传递了
x-forwarded-for
,nginx 会原样保留并转发该请求头。
因此,为确保后端服务能正确识别客户端真实 ip,通常需要根据实际情况对请求头进行配置和调整。
常用变量及其含义
理解 nginx 的内置变量对于正确配置至关重要,以下为关键变量解析:
$remote_addr
- 表示与 nginx 服务器建立连接的上一层代理或客户端的 ip 地址。
- 在 tcp 四层负载均衡场景下(开启获取客户端真实 ip 功能),
$remote_addr
通常是客户端的真实 ip。 - 在 http 七层负载均衡场景下,
$remote_addr
通常是负载均衡器或 cdn 的 ip,因为客户端真实 ip 通过x-forwarded-for
传递。
$http_x_forwarded_for
- 获取请求头中
x-forwarded-for
的原始值,通常是前端负载均衡器或 cdn 添加的客户端 ip 列表。 - 该值可以包含一个或多个 ip 地址,多个 ip 用逗号分隔,从左到右依次表示客户端真实 ip 及经过的代理 ip。
$proxy_add_x_forwarded_for
- nginx 自带的复合变量,用于追加当前连接的客户端 ip(
$remote_addr
)到已有的x-forwarded-for
列表中。 - 若请求中没有原始的
x-forwarded-for
,该变量值即为$remote_addr
。 - 例如,如果前端已经传递了
x-forwarded-for: 1.1.1.1
,且$remote_addr
是2.2.2.2
,设置后为:x-forwarded-for: 1.1.1.1, 2.2.2.2
。
典型配置方法及应用场景
在 nginx 配置中传递客户端真实 ip
proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
此配置可以在保持原有 x-forwarded-for
值的基础上,追加当前连接 ip,适用于多级代理链场景,方便后端服务追踪来源链路。
直接覆盖 x-forwarded-for 头
proxy_set_header x-forwarded-for $remote_addr;
此配置会覆盖前面传递的所有 x-forwarded-for
信息,直接将当前连接的 ip 作为唯一值。
适用场景:
- 您确信当前连接的
$remote_addr
是客户端的真实 ip(如 tcp 四层负载均衡开启真实 ip穿透时)。 - 或者想避免链路传递过长或含有无用代理 ip 时重置 ip 信息。
保持负载均衡器传递的真实 ip
当前端负载均衡器已经正确注入客户端真实 ip 到 x-forwarded-for
,一般无需在 nginx 反代层修改该头部,直接转发即可:
proxy_set_header x-forwarded-for $http_x_forwarded_for;
或者默认不设置,nginx 会自动将接收到的请求头透传。
不同协议和监听层级对 ip 的影响
tcp 四层监听(四层负载均衡):
- 负载均衡器通过网络层直接转发流量,若开启“获取客户端真实 ip”,则
$remote_addr
即真实客户端 ip,x-forwarded-for
通常不存在。
- 负载均衡器通过网络层直接转发流量,若开启“获取客户端真实 ip”,则
http 七层监听(七层负载均衡):
- 负载均衡器通过 http 协议代理请求,将客户端真实 ip 放进
x-forwarded-for
头部,$remote_addr
是负载均衡器实例 ip。
- 负载均衡器通过 http 协议代理请求,将客户端真实 ip 放进
综上,确定您的架构和协议环境,是选择合适真实 ip 获取策略的前提。
nginx 访问日志中打印真实 ip
为了在日志中更准确地记录客户端的真实 ip,配置访问日志时可使用:
log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '"$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main;
其中,$http_x_forwarded_for
可显示真实的客户端 ip 链路,方便排查和分析。
安全防护建议
由于 x-forwarded-for
头容易被客户端伪造,建议:
- 只信任来自可信负载均衡/代理服务器的 ip 和
x-forwarded-for
。 - 使用
real_ip
模块(ngx_http_realip_module
)替换$remote_addr
为真实客户端 ip,配置如下:
set_real_ip_from 192.168.0.0/16; # 代理服务器 ip 段 real_ip_header x-forwarded-for; real_ip_recursive on;
此配置确保后端应用能够获得正确的 $remote_addr
,并防止伪造。
总结
- 理解负载均衡器的协议层级和“获取客户端真实 ip”功能对于正确配置 nginx 与后端应用至关重要。
$proxy_add_x_forwarded_for
是追加客户端 ip 的最佳实践,适合多级代理环境。- 通过
real_ip
模块配置,可将真实客户端 ip 映射到$remote_addr
,方便应用处理。 - 日志中打印
$http_x_forwarded_for
有助于追踪多跳代理链路。
合理配置与使用这些变量,能帮助您在复杂的负载均衡与代理环境中准确获取客户端真实 ip,确保业务的稳定运行和安全防护。
以上就是nginx获取客户端真实ip的原理及配置方法的详细内容,更多关于nginx获取客户端真实ip的资料请关注代码网其它相关文章!
发表评论