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函數時不用擔心會覆蓋上次的調用結果。