前言
之前我们分享了nginx反向代理的X-Real-IP
和X-Forwarded-For
的作用和实现原理,现在我们就根据之前的实验结果,继续分享nginx反向代理如何获取客户端的真实IP
Realip模块
该模块的作用是帮助我们在使用了代理的情况下获取客户真实ip。该模块默认不编译进nginx二进制文件中,需要在编译时指定 --with-http_realip_module 参数才会安装该模块(yum安装的nginx默认编译该模块)
参数说明
set_real_ip_from
指定可信地址,这里的可信地址是上一级代理,也就是直接访问上游服务的代理的ip;可以指定多行该指令;如果不使用该指令,就无法获取到起始客户端IPreal_ip_header
告知Nginx真实客户端IP从哪个请求头获取。默认是X-Real-IP。但我们一般设置为X-Forwarded-For。real_ip_recursive off
是否递归解析,off表示默认从最后一个地址开始解析。例如 X-Forwarded-For 是 1.1.1.1,2.2.2.2,3.3.3.3,那么off取的是3.3.3.3,我们一般设置为on。如果只有一层代理,on和off都无所谓。
以上参数,一般配置在后端服务中,中间代理层不做配置
实验解析
网络环境还是上篇文档中的相关配置,下面直接开始实验过程。
角色 | ip | 软件及版本 |
---|---|---|
客户端 | 192.168.124.101 | nginx1.22.1 |
反向代理A | 192.168.124.170 | nginx1.22.1 |
反向代理B | 192.168.124.171 | nginx1.22.1 |
反向代理C | 192.168.124.172 | nginx1.22.1 |
后端web服务器 | 192.168.124.173 | nginx1.22.1 |
客户端配置域名解析文件C:\Windows\System32\drivers\etc\hosts
192.168.124.170 www.ywnm.com
real_ip_recursive
开启
在反向代理节点A/B/C中开启proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
,A节点开启proxy_set_header X-Real-IP $remote_addr;
,
后端web服务器,配置Realip模块参数real_ip_recursive on;
,set_real_ip_from
添加3个代理地址为可信地址,具体配置如下
后端web服务
http{
...
log_format main '$remote_addr + "$http_host" + "$http_x_forwarded_for" + "$http_x_real_ip"';
access_log logs/access.log main;
server {
listen 80;
server_name 192.168.124.173;
set_real_ip_from 192.168.124.170;
set_real_ip_from 192.168.124.171;
set_real_ip_from 192.168.124.172;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
location / {
root html/;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html/;
}
}
}
访问www.ywnm.com
,后端web服务日志:
192.168.124.101 + "www.ywnm.com" + "192.168.124.101, 192.168.124.170, 192.168.124.171" + "-"
关闭
后端web服务器,设置real_ip_recursive off;
,访问www.ywnm.com
,后端web服务日志:
192.168.124.171 + "www.ywnm.com" + "192.168.124.101, 192.168.124.170, 192.168.124.171" + "-"
注意
这里的remote_addr值变成了192.168.124.171
。上一篇中的实验结果,该值都是192.168.124.172
,即后端web服务的上层代理节点C的ip。
set_real_ip_from
设置不同可信地址set_real_ip_from时,后端web服务日志中remote_addr
的变化
set_real_ip_from可信地址设置为192.168.124.170/171,去掉192.168.124.172,后端web服务日志
192.168.124.172 + "www.ywnm.com" + "192.168.124.101, 192.168.124.170, 192.168.124.171" + "-"
set_real_ip_from可信地址设置为192.168.124.170/172,去掉192.168.124.171,后端web服务日志
192.168.124.171 + "www.ywnm.com" + "192.168.124.101, 192.168.124.170, 192.168.124.171" + "-"
set_real_ip_from可信地址设置为192.168.124.171/172,去掉192.168.124.170,后端web服务日志
192.168.124.170 + "www.ywnm.com" + "192.168.124.101, 192.168.124.170, 192.168.124.171" + "-"
通过启用Realip模块
配置,与上篇《nginx反向代理之获取客户端IP(一)》实验结果对比,可知:
不使用realip模块, $remote_addr
是上一级代理的ip。使用了realip模块,$remote_addr是real_ip_header指令指定的起始客户端ip.当real_ip_recursive为off时,nginx会把real_ip_header指定的HTTP头中的最后一个IP当成真实IP 当real_ip_recursive为on时,nginx会把real_ip_header指定的HTTP头中的最后一个不是信任服务器的IP当成真实IP
IP地址伪装
从之前的实验结果, 我们一共得到得到了2种获取客户端真实IP的方式:
从首层代理(或者是互联网中的CDN)自定义header头
即设置proxy_set_header X-Real-IP $remote_addr;
,然后在应用端解析$http_x_real_ip
获取forwarded-for信息,设置realip
即每层代理都设置proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
,在后端web服务通知设置可信地址,并开启real_ip_recursive来获取真实客户端ip。
以上的2种方案都能获取到真实的客户端ip,但是当你的后端服务不是nginx作为web服务(不能设置可信地址,并且从右往左遍历ip串),或者是后端代码通过获取远程客户端ip,如以下代码:
public String getClientIp(HttpServletRequest request) {
String xff = request.getHeader("X-Forwarded-For");
if (xff == null) {
return request.getRemoteAddr();
} else {
return xff.contains(",") ? xff.split(",")[0] : xff;
}
}
这个时候,通过X-Forwarded-For
来获取heade头作为客户端真实ip就会出现问题。我们通过apipost伪装X-Forwarded-For并发送请求来模拟
此时后端web中获取到的日志信息:
192.168.124.101 + "www.ywnm.com" + "2.2.2.2, 192.168.124.101, 192.168.124.170, 192.168.124.171" + "-"
此时X-Forwarded-For为2.2.2.2, 192.168.124.101, 192.168.124.170, 192.168.124.171
,如果取字符串的最左侧ip,客户端为2.2.2.2
总结
小型架构(单一代理)
直接使用 X-Real-IP,简单高效,日志中获取到的 IP 就是客户端的真实 IP。或者使用remote_addr,因为remote_addr无法伪造多层代理架构(Nginx + CDN / WAF / 反向代理链)
建议使用 X-Forwarded-For,配合 real_ip_recursive 来递归解析最原始的 IP 地址。。并且首层代理配置proxy_set_header X-Forwarded-For $remote_addr;
代替proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
,这样X-Forwarded-For将无法伪造客户端ip。

优网科技秉承"专业团队、品质服务" 的经营理念,诚信务实的服务了近万家客户,成为众多世界500强、集团和上市公司的长期合作伙伴!
优网科技成立于2001年,擅长网站建设、网站与各类业务系统深度整合,致力于提供完善的企业互联网解决方案。优网科技提供PC端网站建设(品牌展示型、官方门户型、营销商务型、电子商务型、信息门户型、DIY体验、720全景展厅及3D虚拟仿真)、移动端应用(手机站、APP开发)、微信定制开发(微信官网、微信商城、企业微信)、微信小程序定制开发等一系列互联网应用服务。