一.REMOTE_ADDR,X-Forwarded-For,HTTP_CLIENT_IP,X-Real-IP区别
- REMOTE_ADDR:客户端与服务器连接是的IP地址。如果客户端通过代理访问服务端,在REMOTE_ADDR表示与服务器最近的代理服务器的IP地址;
- HTTP_CLIENT_IP: 是代理服务器发送的HTTP头。
- X-Forwarded-For:是一个 HTTP 扩展头部。格式:
X-Forwarded-For: client, proxy1, proxy2
,由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP。
如:
如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到以下信息:X-Forwarded-For: IP0, IP1, IP2
注意列表中并没有 IP3,IP3 可以在服务端通过 REMOTE_ADD字段获得. - X-Real-IP:没有相关标准,取值与架构有关。一般也不怎用,更多的使用X-Formarded-For代替。如下
// 最后一跳如果是正向代理,可能会保留真实客户端IP
X-Real-IP: IP0
// 最后一跳如果是反向代理,比如Nginx,一般会是与之直接连接的代理服务器IP
X-Real-IP: IP3
1.1不同架构下几个变量的取值
1)没有使用代理服务器
REMOTE_ADDR = 真实客户端IP
HTTP_X_FORWARDED_FOR = 没数值或不显示
2)使用透明代理服务器
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 【您的真实 IP, 代理服务器IP1,代理服务器IP1】时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
ps:这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
3)使用普通匿名代理服务器
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 【代理服务器IP1,代理服务器IP2】时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
ps:隐藏了真实IP
4)使用欺骗性代理服务器
REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 【随机IP, 代理服务器IP1,代理服务器IP2】时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
ps:告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它
5)使用高匿名代理服务器
REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 没数值或不显示
ps:完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象
1.2.如何获取客户端的真实IP
总的思路主要还是通过X-Forwarded-For来获取客户端真实IP。不同web服务器,不同架构可能实现方式有些不一样。
有篇比较好的文章,觉得写的挺好,可以参考:https://huaweicloud.blog.csdn.net/article/details/107567634
假设访问链路:clent–>proxy1–>proxy2–>proxy3–>nginx–>app server
在上面这个例子中,这个请求成功通过了三台代理服务器:proxy1, proxy2 及 proxy3。请求由client1发出,到达了proxy3(proxy3可能是请求的终点)。请求刚从client1中发出时,XFF是空的,请求被发往proxy1;通过proxy1的时候,client 的IP被添加到XFF中,之后请求被发往proxy2;通过proxy2的时候,proxy1的IP被添加到XFF中,表示代理proxy1z转发的请求;之后请求被发往proxy3,通过proxy3时,proxy2的IP被添加到XFF中,之后请求的的去向不明,如果proxy3不是请求终点,请求会被继续转发。
特别注意:
HTTP_X_FORWARDED_FOR头伪造起来非常容易,所以在尝试使用X-Forwarded-For获取客户端真实IP地址时,要谨慎。不过。正常情况下XFF中最后一个IP地址是最后一个代理服务器的IP地址, 这通常是一个比较可靠的信息来源。
比如使用代码就可以很方便的伪造X-Forwarded-For
import sys, httplib, random
params = "value=xxx"
ipAddress = "10.200.0."+random(1,254)
headers = { "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Encoding":"gzip, deflate", "Accept-Language":"zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3", "Connection":"keep-alive", "X-Forwarded-For":ipAddress, "Content-Length":"31", "Content-Type":"application/x-www-form-urlencoded", "User-Agent":"Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0" }
con2 = httplib.HTTPConnection("192.168.0.100")
try:
con2.request("POST", "/xxx.php", params, headers)
r2 = con2.getresponse()
print r2.read()
except Exception, e:
print e
sys.exit(1)