在不用cdn的狀況下,nginx作負載獲取真實ip時,nginx配置以下: java
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,服務器測試一下: nginx
不加cdn,獲取得IP:123.116.126.51(我當前客戶端機器的真實IP) web
而後加上加了cdn後,後去到的IP:123.116.126.51, 202.108.251.166(hosts指向cdn的ip) shell
即: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後會有兩種狀況發生 測試
一、若是從CDN過來的請求沒有設置X-Forwarded-For頭(一般這種事情不會發生),而到了咱們這裏Nginx設置將其設置爲$proxy_add_x_forwarded_for的話,X-Forwarded-For的信息應該爲CDN的IP,由於相對於Nginx負載均衡來講客戶端即爲CDN,這樣的話,後端的web程序時死活也得到不了真實用戶的IP的。 google
二、CDN設置了X-Forwarded-For,咱們這裏又設置了一次,且值爲$proxy_add_x_forwarded_for的話,那麼X-Forwarded-For的內容變成 」客戶端IP,CDN的ip「若是是這種狀況的話,那後端的程序經過X-Forwarded-For得到客戶端IP,則取逗號分隔的第一項便可。 spa
這個比較頭疼,若是隻想獲取客戶端真實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。