獲取用戶的真實ip

常見的坑有兩個:php


 


1、獲取的是內網的ip地址。在nginx做爲反向代理層的架構中,轉發請求到php,java等應用容器上。結果php獲取的是nginx代理服務器的ip,表現爲一個內網的地址。php獲取REMOTE_ADDR就是這樣一個狀況(內網地址)。java


2、獲取的是攻擊者僞造的ip地址。攻擊者能夠隨便僞造一個頭部信息,隨便填寫一個ip放到頭部發過來,php獲取到HTTP_CLIENT_IP就是這樣一個狀況。僞造的ip,致使咱們數據庫存儲是假的ip,無從真實去判斷攻擊者的來源。好比批量註冊賬號的註冊ip,登陸的ip等。nginx


     爲避免僞造,不要使用discuz原來的獲取ip函數,裏面的判斷優先級會使得攻擊者容易僞造ip。數據庫


 


 


php代碼:瀏覽器


 


 


 


function getIP() {服務器


 


        if (getenv("HTTP_X_FORWARDED_FOR")) {架構


            //這個提到最前面,做爲優先級,nginx代理會獲取到用戶真實ip,發在這個環境變量上,必需要nginx配置這個環境變量HTTP_X_FORWARDED_FOR函數


            $ip = getenv("HTTP_X_FORWARDED_FOR");代理


        } else if (getenv("REMOTE_ADDR")) {ip


           //在nginx做爲反向代理的架構中,使用REMOTE_ADDR拿到的將會是反向代理的的ip,即拿到是nginx服務器的ip地址。每每表現是一個內網ip。


            $ip = getenv("REMOTE_ADDR");


        } else if ($_SERVER['REMOTE_ADDR']) {


            $ip = $_SERVER['REMOTE_ADDR'];


        } else if (getenv("HTTP_CLIENT_IP")) {


            //HTTP_CLIENT_IP攻擊者能夠僞造一個這樣的頭部信息,致使獲取的是攻擊者隨意設置的ip地址。


            $ip = getenv("HTTP_CLIENT_IP");


        } else {


            $ip = "unknown";


        }


        return $ip;


    }


 


 


 


說明


 


在反向代理架構中,不能經過REMOTE_ADDR來獲取用戶的真實ip!


 


之前的理解方式有誤(更新一下)


通常的方式是這樣:


nginx>>(fastcgi方式)>>php引擎


nginx把REMOTE_ADDR傳遞給了php。表明的是當前與nginx通訊的客戶端ip,通常狀況下(非反向代理),這個客戶就是用戶的瀏覽器,因此獲得的用戶的ip。



假設作了反向代理架構,是下面這樣子的:



用 戶>>>>>>>>>>>服務器 a>>>>>>>>>>>>>>>>>>nginx>>>>>>>>>>>>>> (fastcgi方式通訊)>>>>>>>>>>>>php引擎



   用戶訪問一個域名,其實是經過服務器a作了轉發,轉發到nginx去(反向代理架構常常會這樣部署)



  因而,當前與nginx通訊的客戶端,就是服務器a的地址, REMOTE_ADDR就是a服務器的地址了。



  如何判斷:nginx的上一層是否是還有一層。像上面的狀況就還有一層。因此獲得的將會是服務器a的地址。


 


 


 


總結:在nginx做爲反向代理的架構中,php的REMOTE_ADDR(其餘語言也是相似的名稱)拿到的將會是nginx代理的ip地址。拿不到用戶的真實ip,拿到是nginx反向代理服務器地址。


 


REMOTE_ADDR本意就是遠程的地址,nginx是代理層,轉發請求到php,php獲取到的遠程地址其實是nginx反向代理服務器ip,這是符合協議規則的。


 


可是,可讓nginx幫助咱們拿到用戶的真實ip,寫到一個環境變量中,而後轉發給咱們,只要按照某個約定的名稱便可,好比約定名稱爲HTTP_X_FORWARD_FOR(也能夠約定其餘名稱,關鍵看nginx中配置,能夠全公司考慮統一)。


 


 


nginx配置相似於這樣:


 


fastcgi_param  HTTP_X_FORWARD_FOR  $remote_addr;


 


 上一句的目的是,將HTTP_X_FORWARD_FOR的值設置爲$remote_addr的值。也就是將用戶真實的ip(或用戶使用代理的ip)放到HTTP_X_FORWARD_FOR中去。


 


 $remote_addr是nginx的內置變量,這個變量它獲得是用戶真實的ip地址(用戶使用了代理,則就是代理的ip地址)。


 


因而在php端經過getenv("HTTP_X_FORWARDED_FOR")就能夠獲取到nginx傳遞過來的值,是用戶真實的ip地址。

相關文章
相關標籤/搜索