Nginx 的 set_real_ip_from 指令用于处理经过反向代理服务器或负载均衡器转发的客户端真实 IP 地址。在很多情况下,客户端的请求会通过中间设备(如 CDN、反向代理、负载均衡器)到达 Nginx。这时,Nginx 只能看到中间设备的 IP 地址,而无法获取客户端的真实 IP。set_real_ip_from 指令可以帮助 Nginx 信任特定来源的代理服务器,从而提取并记录请求中的客户端真实 IP。
背景
反向代理或负载均衡器通常会将客户端的真实 IP 地址存放在 HTTP 请求头中,例如:
• X-Forwarded-For
• X-Real-IP
通过 set_real_ip_from 和 real_ip_header 指令,Nginx 可以识别这些头部信息,将客户端的真实 IP 地址用于日志记录、访问控制、请求限速等。
使用场景
• 反向代理:当 Nginx 位于多层反向代理之后时,可以配置它从代理的请求头中提取客户端的 IP。
• CDN:当使用 CDN(如 Cloudflare、阿里云 CDN、腾讯云 CDN)时,客户端 IP 可能会被 CDN 覆盖,Nginx 可以通过指定 CDN 的 IP 段来信任这些头部信息。
• 负载均衡:如果客户端请求通过负载均衡服务器转发,set_real_ip_from 可以让 Nginx 获取最原始的客户端 IP。
指令语法
set_real_ip_from ;
• <source>:可以是单个 IP 地址、CIDR 地址段、IP 范围或子网。表示 Nginx 信任这些来源,它们传递的 X-Forwarded-For 或 X-Real-IP 等头部中包含的客户端真实 IP 可以被接受。
此外,还需要配合使用 real_ip_header 来指定从哪个头部字段中提取真实 IP:
real_ip_header
;
• <header>:指定用于存放客户端真实 IP 的 HTTP 头部,如 X-Forwarded-For 或 X-Real-IP。
典型配置示例
- 配置反向代理
假设客户端的请求通过一个反向代理(IP 地址为 192.168.1.1)转发到 Nginx。代理会将客户端的真实 IP 地址放入 X-Forwarded-For 头部字段中。Nginx 配置如下:
http {
信任反向代理的 IP 地址
set_real_ip_from 192.168.1.1;
# 从 X-Forwarded-For 头部中提取真实 IP
real_ip_header X-Forwarded-For;
server {
listen 80;
location / {
# 日志中记录客户端真实 IP
access_log /var/log/nginx/access.log combined;
}
}
}
在这个配置中:
• set_real_ip_from 192.168.1.1; 表示信任 IP 为 192.168.1.1 的代理服务器,并从该代理传递的请求头中提取真实 IP。
• real_ip_header X-Forwarded-For; 表示从 X-Forwarded-For 头部提取客户端的真实 IP。
- 使用 CDN 提供商
如果你的网站使用了 CDN(如 Cloudflare 或阿里云 CDN),可以配置 Nginx 从 CDN 服务器传递的请求中提取客户端 IP。CDN 提供商通常会发布一系列 IP 地址段,你可以将这些地址段配置在 set_real_ip_from 中。
例如,使用 Cloudflare 的 CDN,Cloudflare 会在 CF-Connecting-IP 或 X-Forwarded-For 头部中传递客户端的 IP,Nginx 配置如下:
http {
信任 Cloudflare 的 IP 段
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
... (Cloudflare 的其他 IP 段)
# 从 CF-Connecting-IP 头部提取真实 IP
real_ip_header CF-Connecting-IP;
server {
listen 80;
location / {
# 使用客户端的真实 IP
access_log /var/log/nginx/access.log combined;
}
}
}
在这个配置中:
• set_real_ip_from 指定了信任的 Cloudflare IP 段(可以根据 Cloudflare 官方文档获取最新的 IP 段)。
• real_ip_header CF-Connecting-IP; 指定从 CF-Connecting-IP 头部提取真实 IP。
- 配置多个信任来源
Nginx 允许你设置多个 set_real_ip_from 指令,以信任来自不同 IP 地址段或多个代理服务器的请求。下面是一个包含多个代理服务器和子网的示例:
http {
信任多个代理服务器和子网
set_real_ip_from 192.168.1.1; # 单个代理服务器 IP
set_real_ip_from 192.168.2.0/24; # 一个子网
set_real_ip_from 203.0.113.0/24; # 另一个子网
# 从 X-Forwarded-For 头部提取真实 IP
real_ip_header X-Forwarded-For;
server {
listen 80;
location / {
access_log /var/log/nginx/access.log combined;
}
}
}
- 配置基于真实 IP 的访问控制
你还可以基于从 set_real_ip_from 信任的 IP 中提取到的客户端真实 IP 实现访问控制。例如,允许特定 IP 访问某个页面,其他 IP 则拒绝访问:
http {
set_real_ip_from 192.168.1.1; # 信任代理服务器
real_ip_header X-Forwarded-For;
server {
listen 80;
location /admin {
allow 203.0.113.5; # 允许特定 IP 访问
deny all; # 拒绝其他 IP
}
}
}
重要注意事项
1. 信任来源的安全性:set_real_ip_from 配置的 IP 段应是完全信任的代理服务器或 CDN。否则,恶意用户可以伪造 X-Forwarded-For 或其他 IP 头部,欺骗 Nginx 以使用错误的客户端 IP。
2. 代理链问题:如果请求经过了多个代理,X-Forwarded-For 头部会包含多个 IP 地址(第一个是客户端 IP,接下来的依次是代理的 IP)。你可以通过配置 real_ip_recursive 指令来处理这种情况:
real_ip_recursive on;
该配置允许 Nginx 递归地从 X-Forwarded-For 列表中提取最前面的客户端 IP。
总结
Nginx 的 set_real_ip_from 指令与 real_ip_header 配合使用,能够让 Nginx 信任特定的代理服务器或 CDN,从请求头中提取并使用客户端的真实 IP 地址。这在处理反向代理、负载均衡或 CDN 场景时非常有用,有助于正确记录客户端 IP,进行基于 IP 的访问控制或流量监控等操作。