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