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

OldBoy~發表於2017-05-17

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。
完全用代理伺服器的資訊替代了您的所有資訊,就象您就是完全使用那臺代理伺服器直接訪問物件。

 

相關文章