nginx多級代理下如何獲取客戶端真實IP
多級代理中獲取客戶端真實IP
日誌的格式
nginx中常用日誌格式配置如下:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
其中的main為日誌格式的別名,在使用的時候直接使用別名即可。
例子:
10.0.3.137 - - [09/Oct/2020:09:41:02 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko" "10.1.9.98"
變數 | 含義 | 例子 |
---|---|---|
$remote_addr | 客戶端的ip地址(直連的IP,代理伺服器,顯示代理服務ip) | 10.0.3.137 |
$remote_user | 用於記錄遠端客戶端的使用者名稱稱 | - |
$time_local | 用於記錄訪問時間和時區 | 08/Oct/2020:02:37:25 -0400 |
$request | 用於記錄請求的url、請求方法,協議的版本 | GET / HTTP/1.1 |
$status | 響應狀態碼 | 200 |
$body_bytes_sent | 給客戶端傳送的檔案主體內容位元組 | 0 |
$http_referer | 可以記錄使用者是從哪個連結訪問過來的 | - |
$http_user_agent | 使用者所使用的代理(一般為瀏覽器) | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko |
$http_x_forwarded_for | 可以記錄客戶端IP和所有經過的代理伺服器的IP | 10.1.9.98 |
日積月累下,日誌檔案會越來越大,日誌檔案太大嚴重影響伺服器效率,所以需要定時對日誌檔案進行切割。
由於這裡是演示,所以切割方式是按分鐘來切割,正常生產上使用一般是按天來進行分割:
#!/bin/bash
#日誌檔案存放目錄
LOGS_PATH=/usr/local/nginx/logs
#備份檔名稱
YESTERDAY=$(date -d "yesterday" +%Y%m%d%H%M)
#重新命名日誌檔案
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log
mv ${LOGS_PATH}/error.log ${LOGS_PATH}/error_${YESTERDAY}.log
## 向 Nginx 主程式傳送 USR1 訊號。USR1 訊號是重新開啟日誌檔案
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)
然後新增定時任務:
# crontab -e
*/1 * * * * /bin/bash /usr/local/nginx/logs/nginx_log.sh
獲取客戶端真實IP
伺服器資源分配情況如下:
- 10.1.9.98:充當客戶端
- 10.0.3.137:一級代理
- 10.0.4.105:二級代理
- 10.0.4.129:三級代理
- 10.0.4.120:伺服器端,為了方便,這裡使用一個nginx充當伺服器端,正常情況下一般是一個web伺服器,如tomcat。
各個服務初始配置如下:
10.0.3.137的配置:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $http_x_forwarded_for - $http_x_real_ip';
access_log logs/access.log main;
server {
listen 80;
location / {
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.0.4.105;
}
}
}
10.0.4.105的配置,其他配置與10.0.3.137的一致:
...
location / {
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.0.4.129;
}
...
10.0.4.129的配置,其他配置與10.0.3.137的一致:
...
location / {
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.0.4.120;
}
...
10.0.4.120的配置,其他配置與10.0.3.137的一致
...
location / {
root html;
index index.html;
}
...
下面的記錄為access.log
中列印的結果:
操作 | 10.0.3.137 | 10.0.4.105 | 10.0.4.129 | 10.0.4.120 |
---|---|---|---|---|
10.1.9.98訪問curl http://10.0.3.137 | 10.1.9.98 - - - - | 10.0.3.137 - - - - | 10.0.4.105 - - - - | 10.0.4.129 - - - - |
10.0.3.137開啟X-Forwarded-For | 10.1.9.98 - - - - | 10.0.3.137 - 10.1.9.98 - - | 10.0.4.105 - 10.1.9.98 - - | 10.0.4.129 - 10.1.9.98 - - |
10.0.4.105開啟X-Forwarded-For | 10.1.9.98 - - - - | 10.0.3.137 - 10.1.9.98 - - | 10.0.4.105 - 10.1.9.98, 10.0.3.137 - - | 10.0.4.129 - 10.1.9.98, 10.0.3.137 - - |
10.0.4.129開啟X-Forwarded-For | 10.1.9.98 - - - - | 10.0.3.137 - 10.1.9.98 - - | 10.0.4.105 - 10.1.9.98, 10.0.3.137 - - | 10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - - |
10.1.9.98偽造頭部訪問curl http://10.0.3.137 -H ‘X-Forwarded-For: 1.1.1.1’ | 10.1.9.98 - 1.1.1.1 - - | 10.0.3.137 - 1.1.1.1, 10.1.9.98 - - | 10.0.4.105 - 1.1.1.1, 10.1.9.98, 10.0.3.137 - - | 10.0.4.129 - 1.1.1.1, 10.1.9.98, 10.0.3.137, 10.0.4.105 - - |
10.0.3.137開啟X-Real-IP | 10.1.9.98 - - - - | 10.0.3.137 - 10.1.9.98 - 10.1.9.98 | 10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.1.9.98 | 10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.1.9.98 |
10.0.4.105開啟X-Real-IP | 10.1.9.98 - - - - | 10.0.3.137 - 10.1.9.98 - 10.1.9.98 | 10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.0.3.137 | 10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.0.3.137 |
10.0.4.129開啟X-Real-IP | 10.1.9.98 - - - - | 10.0.3.137 - 10.1.9.98 - 10.1.9.98 | 10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.0.3.137 | 10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.0.4.105 |
10.1.9.98偽造頭部訪問 curl http://10.0.3.137 -H ‘X-Real-IP: 8.8.8.8’ | 10.1.9.98 - - - 8.8.8.8 | 10.0.3.137 - 10.1.9.98 - 10.1.9.98 | 10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.0.3.137 | 10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.0.4.105 |
總結:
- X-Forwarded-For是一個追加的過程,後面的代理會把前面代理的IP追加到X-Forwarded-For尾部,用逗號進行分隔。
- 應用伺服器(10.0.4.120)無法從X-Forwarded-For中獲取到與它直連的代理伺服器的IP(10.0.4.129),此時我們可以使用 r e m o t e a d d r ( 遠 程 i p , 表 示 直 連 的 那 臺 代 理 ) 。 當 服 務 器 無 法 過 remote_addr(遠端ip,表示直連的那臺代理)。當伺服器無法過 remoteaddr(遠程ip,表示直連的那臺代理)。當服務器無法過http_x_forwarded_for獲得上級代理或者客戶端的ip時(可能沒有經過代理),應該使用$remote_addr。
- 在代理過程中至少有一個代理設定了X-Forwarded-For,否則後面的代理或者應用伺服器無法獲得相關資訊。
X-Forwarded-For
中雖然包含了真實的客戶端IP,一般是第一個IP,但是如果客戶端偽造了請求頭,那麼真實的客戶端IP就不是第一個了。- HTTP中header裡面的
X-Real-IP
只是一個變數,後面的設定會覆蓋前面的設定,所以只需要在第一個代理伺服器上設定proxy_set_header X-Real-IP $remote_addr
即可,然後在應用端直接引用$http_x_real_ip就行。
在java中,如果請求沒有經過nginx代理,可以使用如下方法獲取客戶端的真實IP:
# 類似nginx中的$remote_addr
request.getRemoteHost();
如果請求經過了nginx代理,可以從請求頭中獲取(前提是必須正確配置nginx才能獲取到):
request.getHeader("x-real-ip");
如果是用的其他Apache,Squid等反向代理軟體,同樣是從請求頭中獲取真實IP,只是屬性名不一樣而已。
相關文章
- Nginx 反向代理後如何獲取真實客戶端 IPNginx客戶端
- 阿里雲CDN + nginx多級代理獲取客戶端IP阿里Nginx客戶端
- nginx反向代理獲取客戶端的真實IP和域名Nginx客戶端
- 獲取客戶端真實IP客戶端
- .net 獲取客戶端真實ip客戶端
- Java面試題-如何獲取客戶端真實IPJava面試題客戶端
- 伺服器獲取真實客戶端 IP伺服器客戶端
- nginx設定反向代理怎麼獲取客戶端的真實IP和域名以供日誌分析Nginx客戶端
- Nginx代理後服務端使用remote_addr獲取真實IPNginx服務端REM
- 在容器服務中獲取客戶端真實源 IP客戶端
- ABP vNext 審計日誌獲取真實客戶端IP客戶端
- 【Nginx】如何獲取客戶端真實IP、域名、協議、埠?看這一篇就夠了!Nginx客戶端協議
- c# 獲取客戶端IPC#客戶端
- 服務端如何獲取客戶端請求IP地址服務端客戶端
- spring boot 獲取客戶端ip資訊Spring Boot客戶端
- Django透過request獲取客戶端IPDjango客戶端
- 一次獲取客戶端 IP 記錄客戶端
- java web 通過request獲取客戶端IPJavaWeb客戶端
- 經過代理如何獲取真實IP 及 laravel 中配置可信代理的原理Laravel
- 在OwinSelfHost專案中獲取客戶端IP地址客戶端
- 在SelfHost專案中獲取客戶端IP地址客戶端
- X-Forwarded-For中多個IP哪個是真實客戶端IP? - adam-pForward客戶端
- Spring 客戶端 IP 地址獲取及儲存細節Spring客戶端
- tomcat採集阿里雲slb真實客戶端ip🫚Tomcat阿里客戶端
- 獲取客戶端Mac地址客戶端Mac
- nginx 代理轉發 傳遞真實 ip 地址Nginx
- Nacos - 客戶端例項列表獲取客戶端
- 乾貨:不同場景容器內獲取客戶端源IP的方法客戶端
- PHP 獲取使用者真實的ipPHP
- laravel symfony request獲取真實ip的坑Laravel
- nginx獲取真實ip,proxy_set_head怎麼設定頭部資訊Nginx
- 【Go】獲取使用者真實的ip地址Go
- 【Go】獲取使用者真實的 ip 地址Go
- 如何使用python爬蟲直接返回客戶端IP?Python爬蟲客戶端
- 如何繞過CDN獲取網站的真實IP?手把手教你!網站
- Istio 中實現客戶端源 IP 的保持客戶端
- 國外免費代理ip地址密碼如何獲取?密碼
- 使用 geoip2/geoip2,如何獲取真實使用者 IP 地址