1. 程式人生 > >nginx做負載CDN加速獲取端真實ip

nginx做負載CDN加速獲取端真實ip

在不用cdn的情況下,nginx做負載獲取真實ip時,nginx配置如下:

proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
 

然後後端伺服器獲取ip程式碼:

String address = request.getHeader("X-Forwarded-For");
if (address != null && address.length() > 0
		&& !"unknown".equalsIgnoreCase(address)) {
	return address;
}
address = request.getHeader("Proxy-Client-IP");
if (address != null && address.length() > 0
		&& !"unknown".equalsIgnoreCase(address)) {
	return address;
}
address = request.getHeader("WL-Proxy-Client-IP");
if (address != null && address.length() > 0
		&& !"unknown".equalsIgnoreCase(address)) {
	return address;
}
return request.getRemoteAddr();

這樣就能獲取到真實的IP,伺服器測試一下:

不加cdn,獲取得IP:123.116.126.51(我當前客戶端機器的真實IP)

然後加上加了cdn後,後去到的IP:123.116.126.51, 202.108.251.166hosts指向cdn的ip)

即:client 真實IP,代理IP,google之,

X-Forwarded-For:簡稱XFF頭,它代表客戶端,也就是HTTP的請求端真實的IP,只有在通過了HTTP 代理或者負載均衡伺服器時才會新增該項 。

標準格式如下:
X-Forwarded-For: client1, proxy1, proxy2
從標準格式可以看出,
X-Forwarded-For頭資訊可以有多個,中間用逗號分隔,第一項為真實的客戶端ip,剩下的就是曾經經過的代理或負載均衡的ip地址,經過幾個就會出現幾個。

當Nginx設定X-Forwarded-For等於$proxy_add_x_forwarded_for後會有兩種情況發生

1、如果從CDN過來的請求沒有設定X-Forwarded-For頭(通常這種事情不會發生),而到了我們這裡Nginx設定將其設定為$proxy_add_x_forwarded_for的話,X-Forwarded-For的資訊應該為CDN的IP,因為相對於Nginx負載均衡來說客戶端即為CDN,這樣的話,後端的web程式時死活也獲得不了真實使用者的IP的。

2、CDN設定了X-Forwarded-For,我們這裡又設定了一次,且值為$proxy_add_x_forwarded_for的話,那麼X-Forwarded-For的內容變成 ”客戶端IP

,CDN的ip“如果是這種情況的話,那後端的程式通過X-Forwarded-For獲得客戶端IP,則取逗號分隔的第一項即可

這個比較頭疼,如果只想獲取客戶端真實ip,那麼只能修改我們後端程式碼,如果有多個,那麼取第一個。這不是我想要的,

那麼怎麼樣才能不修改就能真實IP呢?

Nginx中還有一個$http_x_forwarded_for變數,這個變數中儲存的內容就是請求中的X-Forwarded-For資訊。如果後端獲得X-Forwarded-For資訊的程式相容性不好的話(沒有考慮到X-Forwarded-For含有多個IP的情況),最好就不要將X-Forwarded-For設定為 $proxy_add_x_forwarded_for。應該設定為$http_x_forwarded_for或者乾脆不設定!

上面這段話的意思是我們不加$proxy_add_x_forwarded_for, 但是這樣不在cdn的情況下去會取不到真實IP,有沒有一個兩全齊美的方法呢?

經過幾種配置之後,發現做如下配置:

proxy_set_header X-Forwarded-For  $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;	

這樣配置第一次獲取 $http_x_forwarded_for,如果不存在,那麼獲取$proxy_add_x_forwarded_for。

這樣不管是否在cdn環境,都可以獲得一個客戶端IP。

(注:多層代理未測試)