Nginx前端設置反向代理,后端Apache如何獲取訪客的真實IP,結合PHP


nginx反向代理后,在應用中取得的ip都是反向代理服務器的ip,取得的域名也是反向代理配置的url的域名,解決該問題,需要在nginx反向代理配置中添加一些配置信息,目的將客戶端的真實ip和域名傳遞到應用程序中。

①:php獲取REMOTE_ADDR就是這樣一個情況(內網地址)。

②:獲取的是攻擊者偽造的ip地址。攻擊者可以隨便偽造一個頭部信息,隨便填寫一個ip放到頭部發過來,php獲取到HTTP_CLIENT_IP就是這樣一個情況。偽造的ip,導致我們數據庫存儲是假的ip,無從真實去判斷攻擊者的來源。比如批量注冊帳號的注冊ip,登錄的ip等。

配置如下:

location ~* \.(jpg|png|gif)$ { proxy_set_header X-Forwarded-For $remote_addr; #proxy_pass http://....
} location ~ \.php$ { proxy_set_header X-Forwarded-For $remote_addr; #proxy_pass http://....
}

PHP代碼:

function getIP() { $ip = "unknown"; if (getenv("HTTP_X_FORWARDED_FOR")) { //這個提到最前面,作為優先級,nginx代理會獲取到用戶真實ip,發在這個環境變量上,必須要nginx配置這個環境變量HTTP_X_FORWARDED_FOR
            $ip = getenv("HTTP_X_FORWARDED_FOR"); } else if (getenv("REMOTE_ADDR")) { //在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"); } return $ip; }

總結

在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地址。

 

 

php獲取用戶IP地址的三個屬性的區別

 

下面分析獲得IP的幾種情況。

 

一、沒有使用代理服務器的情況:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 沒數值或不顯示
HTTP_X_FORWARDED_FOR = 沒數值或不顯示

 

二、使用透明代理服務器的情況: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。
這類代理服務器還是將您的信息轉發給您的訪問對象,無法達到隱藏真實身份的目的。

 


三、使用普通匿名代理服務器的情況: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,但是向訪問對象透露了您是使用代理服務器訪問他們的。

 


四、使用欺騙性代理服務器的情況: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欺騙它。

 


五、使用高匿名代理服務器的情況: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。
完全用代理服務器的信息替代了您的所有信息,就象您就是完全使用那台代理服務器直接訪問對象。

 

返回一個ip

public static function getIP() {
        if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
            $cip = $_SERVER["HTTP_CLIENT_IP"];
        } else if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } else if (!empty($_SERVER["REMOTE_ADDR"])) {
            $cip = $_SERVER["REMOTE_ADDR"];
        } else {
            $cip = '';
        }
        preg_match("/[\d\.]{7,15}/", $cip, $cips);
        $cip = isset($cips[0]) ? $cips[0] : 'unknown';
        unset($cips);

        return $cip;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM