ip相關

作網站時常常會用到remote_addrx_forwarded_for這兩個頭信息來獲取客戶端的IP,然而當有反向代理或者CDN的狀況下,這兩個值就不夠準確了,須要調整一些配置。php

什麼是remote_addr

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

什麼是x_forwarded_for

正如上面所述,當你使用了代理時,web服務器就不知道你的真實IP了,爲了不這個狀況,代理服務器一般會增長一個叫作x_forwarded_for的頭信息,把鏈接它的客戶端IP(即你的上網機器IP)加到這個頭信息裏,這樣就能保證網站的web服務器能獲取到真實IPweb

使用HAProxy作反向代理

一般網站爲了支撐更大的訪問量,會增長不少web服務器,並在這些服務器前面增長一個反向代理(如HAProxy),它能夠把負載均勻的分佈到這些機器上。你的瀏覽器訪問的首先是這臺反向代理,它再把你的請求轉發到後面的web服務器,這就使得web服務器會把remote_addr設爲這臺反向代理的IP,爲了能讓你的程序獲取到真實的客戶端IP,你須要給HAProxy增長如下配置segmentfault

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則能夠忽略了:)

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

php中HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR的使用 
1.REMOTE_ADDR:瀏覽當前頁面的用戶計算機的ip地址 
2.HTTP_X_FORWARDED_FOR: 瀏覽當前頁面的用戶計算機的網關 
3.HTTP_CLIENT_IP:客戶端的ip 

在PHP 中使用 $_SERVER["REMOTE_ADDR"] 來取得客戶端的 IP 地址,但若是客戶端是使用代理服務器來訪問,那取到的就是代理服務器的 IP 地址,而不是真正的客戶端 IP 地址。要想透過代理服務器取得客戶端的真實 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 來讀取。 

不過要注意的事,並非每一個代理服務器都能用 $_SERVER["HTTP_X_FORWARDED_FOR"] 來讀取客戶端的真實 IP,有些用此方法讀取到的仍然是代理服務器的 IP。 

還有一點須要注意的是:若是客戶端沒有經過代理服務器來訪問,那麼用$_SERVER["HTTP_X_FORWARDED_FOR"] 取到的值將是空的。 

if ($_SERVER['HTTP_X_FORWARDED_FOR'] && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/',$_SERVER['HTTP_X_FORWARDED_FOR'])) {  
      $onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];  
} elseif  ($_SERVER['HTTP_CLIENT_IP']  && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/',$_SERVER['HTTP_CLIENT_IP'])) {  
      $onlineip = $_SERVER['HTTP_CLIENT_IP']; 




獲取用戶IP地址的三個屬性的區別 (HTTP_X_FORWARDED_FOR,HTTP_VIA,REMOTE_ADDR) 
1、沒有使用代理服務 器的狀況: 

REMOTE_ADDR = 您的 IP 
HTTP_VIA = 沒數值或不顯示 
HTTP_X_FORWARDED_FOR = 沒數值或不顯示 

2、使用透明代理服務器的情 況:Transparent Proxies 

REMOTE_ADDR = 最後一個代理服務器 IP 
HTTP_VIA = 代理服務器 IP 
HTTP_X_FORWARDED_FOR = 您的真實 IP ,通過多個代理服務器時,這個值相似以下:203.98.182.163, 203.98.182.163, 203.129.72.215。 

這類代理服務器仍是將您的信息轉發給您的訪問對象,沒法達到隱藏真實身份的目的。 

3、使用普通匿名代理服務器的狀況:Anonymous Proxies 

REMOTE_ADDR = 最後一個代理服務器 IP 
HTTP_VIA = 代理服務器 IP 
HTTP_X_FORWARDED_FOR = 代理服務器 IP ,通過多個代理服務器時,這個值相似以下:203.98.182.163, 203.98.182.163, 203.129.72.215。 

隱藏了您的真實IP,可是向訪問對象透露了您是使用代理服務器訪問他們的。 

4、使用欺騙性代理服務器的狀況:Distorting Proxies 

REMOTE_ADDR = 代理服務器 IP 
HTTP_VIA = 代理服務器 IP 
HTTP_X_FORWARDED_FOR = 隨機的 IP ,通過多個代理服務器時,這個值相似以下:203.98.182.163, 203.98.182.163, 203.129.72.215。 

告訴了訪問對象您使用了代理服務器,但編造了一個虛假的隨機IP代替您的真實IP欺騙它。 

5、使用高匿名代理服務器的狀況:High Anonymity Proxies (Elite proxies) 

REMOTE_ADDR = 代理服務器 IP 
HTTP_VIA = 沒數值或不顯示 
HTTP_X_FORWARDED_FOR = 沒數值或不顯示 ,通過多個代理服務器時,這個值相似以下:203.98.182.163, 203.98.182.163, 203.129.72.215。 

徹底用代理服務器的信息替代了您的全部信息,就象您就是徹底使用那臺代理服務器直接訪問對象。 

更多:http://segmentfault.com/q/1010000000095850

相關文章
相關標籤/搜索