php獲取客戶端ip


下面是轉載:

 

REMOTE_ADDR只能獲取訪問者本地連接中設置的IP,如中南民族大學校園網中自己設置的10.X.XXX.XXX系列IP,而這個函數獲取的是局域網網關出口的IP地址,

如果訪問者使用代理服務器,將不獲取代理服務器的IP,而是獲取訪問者網關的真實IP。如果將這個函數應用到限IP訪問的網頁中,別人即使通過限IP訪問段中的代理服務器,也不能訪問該頁面。

// 定義一個函數getIP()

function getIP()

{

global $ip;

if (getenv("HTTP_CLIENT_IP"))

$ip = getenv("HTTP_CLIENT_IP");

else if(getenv("HTTP_X_FORWARDED_FOR"))

$ip = getenv("HTTP_X_FORWARDED_FOR");

else if(getenv("REMOTE_ADDR"))

$ip = getenv("REMOTE_ADDR");

else $ip = "Unknow";

return $ip;

}

// 使用方法:

echo getIP();

getenv("REMOTE_ADDR")用來取得客戶端的 IP 地址,但如果客戶端是使用代理服務器來訪問,那取到的就是代理服務器的 IP 地址,而不是真正的客戶端 IP 地址。要想透過代理服務器取得客戶端的真實 IP 地址,就要使用 getenv("HTTP_X_FORWARDED_FOR") 來讀取。

但是如果客戶端沒有通過代理服務器來訪問,那么用getenv("HTTP_X_FORWARDED_FOR") 取到的值將是空的。

else if(getenv("HTTP_X_FORWARDED_FOR"))

$ip = getenv("HTTP_X_FORWARDED_FOR");

表示如果getenv("HTTP_X_FORWARDED_FOR") 取到的值存在不為空(即客戶端使用代理服務器的情況下),則變量$ip等於getenv("HTTP_X_FORWARDED_FOR") 取到的真實IP值。

如果上面的else if(getenv("HTTP_X_FORWARDED_FOR"))取得的值為空(即沒有使用代理服務器),則不會執行下面的$ip = getenv("HTTP_X_FORWARDED_FOR");這一行語句。

這種情況下已經確認客戶端沒有使用代理服務器,從而通過

else if(getenv("REMOTE_ADDR"))

$ip = getenv("REMOTE_ADDR");

這兩行語句獲得客戶端的IP地址也是真實的IP地址。​

-------------------------------------------------------------------------------------------

下面也是轉載:

做網站時經常會用到remote_addr和x_forwarded_for這兩個頭信息來獲取客戶端的IP,然而當有反向代理或者CDN的情況下,這兩個值就不夠准確了,需要調整一些配置。

什么是remote_addr

remote_addr代表客戶端的IP,但它的值不是由客戶端提供的,而是服務端根據客戶端的ip指定的,當你的瀏覽器訪問某個網站時,假設中間沒有任何代理,那么網站的web服務器(Nginx,Apache等)就會把remote_addr設為你的機器IP,如果你用了某個代理,那么你的瀏覽器會先訪問這個代理,然后再由這個代理轉發到網站,這樣web服務器就會把remote_addr設為這台代理機器的IP。

什么是x_forwarded_for

正如上面所述,當你使用了代理時,web服務器就不知道你的真實IP了,為了避免這個情況,代理服務器通常會增加一個叫做x_forwarded_for的頭信息,把連接它的客戶端IP(即你的上網機器IP)加到這個頭信息里,這樣就能保證網站的web服務器能獲取到真實IP

使用HAProxy做反向代理

通常網站為了支撐更大的訪問量,會增加很多web服務器,並在這些服務器前面增加一個反向代理(如HAProxy),它可以把負載均勻的分布到這些機器上。你的瀏覽器訪問的首先是這台反向代理,它再把你的請求轉發到后面的web服務器,這就使得web服務器會把remote_addr設為這台反向代理的IP,為了能讓你的程序獲取到真實的客戶端IP,你需要給HAProxy增加以下配置

option forwardfor

它的作用就像上面說的,增加一個x_forwarded_for的頭信息,把你上網機器的ip添加進去

使用Nginx的realip模塊

當Nginx處在HAProxy后面時,就會把remote_addr設為HAProxy的IP,這個值其實是毫無意義的,你可以通過nginx的realip模塊,讓它使用x_forwarded_for里的值。使用這個模塊需要重新編譯Nginx,增加--with-http_realip_module參數

set_real_ip_from 10.1.10.0/24;

real_ip_header X-Forwarded-For;

上面的配置就是把從10.1.10這一網段過來的請求全部使用X-Forwarded-For里的頭信息作為remote_addr

將Nginx架在HAProxy前面做HTTPS代理

網站為了安全考慮通常會使用https連接來傳輸敏感信息,https使用了ssl加密,HAProxy沒法直接解析,所以要在HAProxy前面先架台Nginx解密,再轉發到HAProxy做負載均衡。這樣在Web服務器前面就存在了兩個代理,為了能讓它獲取到真實的客戶端IP,需要做以下配置。

首先要在Nginx的代理規則里設定

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

這樣會讓Nginx的https代理增加x_forwarded_for頭信息,保存客戶的真實IP。

其次修改HAProxy的配置

option forwardfor except 10.1.10.0/24

這個配置和之前設定的差不多,只是多了個內網的IP段,表示如果HAProxy收到的請求是由內網傳過來的話(https代理機器),就不會設定x_forwarded_for的值,保證后面的web服務器拿到的就是前面https代理傳過來的。

為什么PHP里的HTTP_X_FORWARDED_FOR和Nginx的不一樣

當你的網站使用了CDN后,用戶會先訪問CDN,如果CDN沒有緩存,則回源站(即你的反向代理)取數據。CDN在回源站時,會先添加x_forwarded_for頭信息,保存用戶的真實IP,而你的反向代理也會設定這個值,不過它不會覆蓋,而是把CDN服務器的IP(即當前remote_addr)添加到x_forwarded_for的后面,這樣x_forwarded_for里就會存在兩個值。Nginx會使用這些值里的第一個,即客戶的真實IP,而PHP則會使用第二個,即CDN的地址。為了能讓PHP也使用第一個值,你需要添加以下fastcgi的配置。

fastcgi_param HTTP_X_FORWARDED_FOR $http_x_forwarded_for;

它會把nginx使用的值(即第一個IP)傳給PHP,這樣PHP拿到的x_forwarded_for里其實就只有一個值了,也就不會用第二個CDN的IP了。

忽略x_forwarded_for

其實,當你使用了Nginx的realip模塊后,就已經保證了remote_addr里設定的就是客戶端的真實IP,再看下這個配置

set_real_ip_from 10.1.10.0/24;

real_ip_header X-Forwarded-For;

它就是把x_forwarded_for設為remote_addr,而nginx里的x_forwarded_for取的就是其中第一個IP。

使用這些設置就能保證你的remote_addr里設定的一直都是客戶端的真實IP,而x_forwarded_for則可以忽略了:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM