博客 / Linux/ Nginx ngx_http_realip_module 模块详解:安装、配置与获取真实客户端IP

Nginx ngx_http_realip_module 模块详解:安装、配置与获取真实客户端IP

ngx_http_realip_module 模块概述

ngx_http_realip_module 是 Nginx 的一个核心模块,其主要作用在于:当 Nginx 服务器位于反向代理(如 CDN、负载均衡器)之后时,能够从代理服务器设置的 HTTP 头部信息中提取出原始客户端的真实 IP 地址。

如果没有启用此模块,Nginx 的访问日志(access_log)中记录的 IP 地址以及 PHP 等后端语言通过 $_SERVER['REMOTE_ADDR'] 获取到的 IP,都将是最后一个直接连接 Nginx 的代理服务器的 IP,而非终端用户的真实 IP。这会对访问统计、安全审计和地域限制等功能造成影响。

模块安装与启用

大多数预编译的 Nginx 包已包含此模块。你可以通过以下命令验证:

nginx -V 2>&1 | grep -o http_realip_module

如果输出 http_realip_module,则表示模块已存在。若需自行编译,在 ./configure 阶段加入 --with-http_realip_module 参数即可。

基础配置与应用场景

场景一:单层反向代理

假设网络架构如下:用户(IP: 123.123.123.123) → 反向代理服务器(IP: 10.10.10.10) → 后端 Nginx 服务器。

若不配置 realip 模块,后端 Nginx 日志中记录的 IP 将是 10.10.10.10。为获取真实用户 IP,需在后端 Nginx 的 httpserverlocation 上下文中添加:

set_real_ip_from 10.10.10.10;
real_ip_header X-Forwarded-For;
  • set_real_ip_from:定义可信的代理服务器 IP 地址或 CIDR 网段。表示来自此地址的连接是代理,其传递的 IP 头信息可信。
  • real_ip_header:指定从哪个 HTTP 请求头中提取真实 IP。常用的是 X-Forwarded-ForX-Real-IP

配置生效后,Nginx 会将 X-Forwarded-For 头中的第一个 IP(即 123.123.123.123)视为真实客户端 IP,并覆盖 $remote_addr 变量的值。

场景二:多层代理与 real_ip_recursive

在更复杂的架构中,例如:用户 → 代理1(192.168.1.10) → 代理2(10.10.10.10) → 后端 Nginx。

此时,到达后端 Nginx 的 X-Forwarded-For 头内容可能为:123.123.123.123, 192.168.1.10, 10.10.10.10

如果仅使用基础配置:

set_real_ip_from 10.10.10.10;
real_ip_header X-Forwarded-For;
# real_ip_recursive 默认为 off

Nginx 会取 X-Forwarded-For 头中最后一个 IP(即 10.10.10.10)作为真实 IP,这显然不正确。

为了解决这个问题,需要启用 real_ip_recursive 指令,并列出所有可信代理:

set_real_ip_from 10.10.10.10;
set_real_ip_from 192.168.1.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
  • real_ip_recursive off (默认):Nginx 将 real_ip_header 指定头部中的最后一个 IP 作为真实 IP。
  • real_ip_recursive on:Nginx 从 real_ip_header 指定头部的右侧开始向左遍历,跳过所有出现在 set_real_ip_from 中的可信 IP,选取第一个不可信 IP 作为真实客户端 IP。

在上例中,Nginx 会从右向左检查:10.10.10.10(可信,跳过)→ 192.168.1.10(可信,跳过)→ 123.123.123.123(不可信,选定为真实 IP)。

配置示例与验证

一个完整的配置示例可能如下(位于 nginx.conf 的 http 或 server 块中):

# 定义所有上游代理服务器的可信 IP 段
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
# 指定真实 IP 所在的 HTTP 头部
real_ip_header X-Forwarded-For;
# 启用递归查找,以应对多层代理
real_ip_recursive on;
# 可选:设置一个备用头部,如果 X-Forwarded-For 不存在则使用此头部
# real_ip_header X-Real-IP;

配置完成后,重载 Nginx:

nginx -s reload

验证配置是否生效的最佳方式是检查访问日志。确保日志格式变量 $remote_addr 已显示为真实客户端 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;

注意事项与常见问题

  • 安全警告:务必仅将可信的反向代理服务器 IP 添加到 set_real_ip_from。如果此列表配置不当,恶意用户可能伪造 X-Forwarded-For 头来冒充任意 IP。
  • 头部选择:与上游代理协商好使用的头部。常见的代理(如 Nginx、Apache、HAProxy、云服务商)一般默认使用 X-Forwarded-For。某些场景下也可能使用 X-Real-IP
  • 变量覆盖:realip 模块会修改 $remote_addr 变量的值。所有依赖此变量的功能(如限流、访问控制)都将基于新的、真实的客户端 IP 工作。
  • 与 proxy_protocol 的区别:realip 模块处理的是 HTTP 头部。若代理使用 PROXY protocol(常见于 TCP/UDP 代理),则需要启用 Nginx 的 listen ... proxy_protocol;set_real_ip_from 配合 real_ip_header proxy_protocol; 来获取真实 IP。

通过正确配置 ngx_http_realip_module,可以确保在复杂的代理网络之后,你的应用日志和安全策略始终基于真实的终端用户 IP,为运维和分析提供准确的数据基础。

  1. avatar
    fjpcode

    文中有一处笔误,在两层代理的场景下, X-Forwarded-For格式应该为 123.123.123.123, 192.168.1.10

    1. 感谢勘误

发表评论

您的邮箱不会公开。必填项已用 * 标注。