X-Forwarded-For: client1, proxy1, proxy2, proxy3
其中的值通过一个 逗号+空格 把多个IP地址区分开, 最左边(client1)是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。 在上面这个例子中,这个请求成功通过了三台代理服务器:proxy1, proxy2 及 proxy3。请求由client1发出,到达了proxy3(proxy3可能是请求的终点)。请求刚从client1中发出时,XFF是空的,请求被发往proxy1;通过proxy1的时候,client1被添加到XFF中,之后请求被发往proxy2;通过proxy2的时候,proxy1被添加到XFF中,之后请求被发往proxy3;通过proxy3时,proxy2被添加到XFF中,之后请求的的去向不明,如果proxy3不是请求终点,请求会被继续转发。
如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到这样信息:X-Forwarded-For: IP0, IP1, IP2
鉴于伪造这一字段非常容易,应该谨慎使用X-Forwarded-For字段。正常情况下XFF中最后一个IP地址是最后一个代理服务器的IP地址, 这通常是一个比较可靠的信息来源。
//不同环境下获取真实的IP function get_ip(){ //判断服务器是否允许$_SERVER if(isset($_SERVER)){ if(isset($_SERVER[HTTP_X_FORWARDED_FOR])){ $realip = $_SERVER[HTTP_X_FORWARDED_FOR]; }elseif(isset($_SERVER[HTTP_CLIENT_IP])) { $realip = $_SERVER[HTTP_CLIENT_IP]; }else{ $realip = $_SERVER[REMOTE_ADDR]; } }else{ //不允许就使用getenv获取 if(getenv("HTTP_X_FORWARDED_FOR")){ $realip = getenv( "HTTP_X_FORWARDED_FOR"); }elseif(getenv("HTTP_CLIENT_IP")) { $realip = getenv("HTTP_CLIENT_IP"); }else{ $realip = getenv("REMOTE_ADDR"); } } return $realip; }
getenv是函数名,从环境中取字符串,获取环境变量的值,getenv()用来取得参数envvar环境变量的内容。参数envvar为环境变量的名称,如果该变量存在则会返回指向该内容的指针。环境变量的格式为envvar=value。getenv函数的返回值存储在一个全局二维数组里,当你再次使用getenv函数时不用担心会覆盖上次的调用结果。