在web開(kāi)發(fā)過(guò)程中诲泌,我們經(jīng)常需要獲取用戶客戶端的真實(shí)IP灭返。比如我們想知道客戶的地理位置分布;比如服務(wù)端需要將會(huì)話和IP地址綁定奄侠,以提高安全性等瞬内。但是一般在分布式系統(tǒng)中迷雪,為了提高系統(tǒng)的可靠性和性能,都會(huì)采用代理來(lái)分發(fā)用戶的請(qǐng)求虫蝶,導(dǎo)致獲取用戶真實(shí)IP變得有些麻煩章咧。
獲取調(diào)用方IP的方法
直接調(diào)用HttpServletRequest中的request.getRemoteAddr()方法,獲取的IP地址能真,是當(dāng)前服務(wù)的上游服務(wù)的IP地址赁严,在沒(méi)有代理的情況下是準(zhǔn)確的扰柠,不過(guò)一般都會(huì)有一個(gè)或者多個(gè)代理,這種方式一般不適用疼约。一般可能用如下幾個(gè)字段
X-FORWARDED-FOR
X-FORWARDED-FOR這個(gè)http頭是個(gè)調(diào)試參數(shù)卤档,在代理服務(wù)器上做相關(guān)的配置,能夠?qū)崿F(xiàn)程剥,在經(jīng)過(guò)每一個(gè)代理的時(shí)候劝枣,會(huì)往后追加上代理的IP地址;這樣通過(guò)這個(gè)字段就可以知道织鲸,這個(gè)請(qǐng)求被代理了多少次舔腾,每次代理是由那個(gè)IP處理的;所以取列表第一個(gè)IP就是用戶的真實(shí)IP地址了搂擦。
nginx支持X-FORWARDED-FOR的配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Proxy-Client-IP
用apache http做代理時(shí)一般會(huì)加上Proxy-Client-IP請(qǐng)求頭
WL-Proxy-Client-IP
weblogic插件加上的頭
HTTP_CLIENT_IP
有些代理服務(wù)器會(huì)加上此請(qǐng)求頭稳诚。
X-Real-IP
在nginx中可以把上游調(diào)用的真實(shí)IP加到HTTP請(qǐng)求頭中,這個(gè)IP從remote_addr變量中獲取是從TCP鏈接中獲取的真實(shí)IP瀑踢。
proxy_set_header X-Real-IP $remote_addr;
某些特殊情況
正常我們會(huì)按照上面的順序按照優(yōu)先級(jí)獲取真實(shí)的IP地址扳还。網(wǎng)上一般都會(huì)把X-FORWARDED-FOR這個(gè)參數(shù)作為第一優(yōu)先級(jí)來(lái)處理。但是這個(gè)參數(shù)實(shí)際上是不安全的橱夭。
X-FORWARDED-FOR這個(gè)參數(shù)的值是個(gè)列表氨距,每次經(jīng)過(guò)代理都是往后追加,而不是覆蓋的徘钥。所以不能確保IP是可信的衔蹲。客戶端可以先偽造一個(gè)IP放到頭部呈础,真實(shí)IP就會(huì)在偽造IP之后了。比如:
客戶端偽造
X-FORWARDED-FOR: 1.1.1.1
經(jīng)過(guò)兩次代理(192.168.1.2,192.168.1.3)之后:
X-FORWARDED-FOR: 1.1.1.1,108.10.10.123,192.168.1.2,192.168.1.3
這樣獲取到的IP地址是1.1.1.1橱健,而不是真正的108.10.10.123而钞。其實(shí)真實(shí)IP已經(jīng)在列表中了,怎么避免獲取偽造的IP拘荡?
nginx有個(gè)realip模塊臼节,可以通過(guò)set_real_ip_from命令制定代理服務(wù)器的IP,因?yàn)榇矸?wù)器的IP地址都是已知的,所以可以通過(guò)從右至左依次獲取第一個(gè)不在代理IP列表中的合法IP就是用戶真實(shí)IP地址了珊皿。
set_real_ip_from 192.168.1.2;
set_real_ip_from 192.168.1.3;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
安裝realip模塊需要重新編譯nginx网缝,比較麻煩,也可以直接通過(guò)最上層代理(第一層代理)服務(wù)器獲取用戶真實(shí)IP蟋定,寫(xiě)入http頭部粉臊,后端服務(wù)優(yōu)先獲取此參數(shù)即可。比如:第一層代理是nginx,將remote_addr參數(shù)寫(xiě)入X-Real-IP驶兜,后端優(yōu)先獲取此參數(shù)扼仲,其他代理不要覆蓋此參數(shù)即可远寸;由于參數(shù)是覆蓋寫(xiě)入的,就算客戶端偽造一個(gè)X-Real-IP參數(shù)頭屠凶,也會(huì)被代理服務(wù)器復(fù)寫(xiě)為真實(shí)的IP.
參考
http://www.reibang.com/p/1e0124de8e02
http://nginx.org/en/docs/http/ngx_http_realip_module.html
轉(zhuǎn)自: https://heqiao2010.github.io