項目中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 | 用于記錄訪問時間和時區(qū) | 08/Oct/2020:02:37:25 -0400 |
$request | 用于記錄請求的url、請求方法,協(xié)議的版本 | GET / HTTP/1.1 |
$status | 響應狀態(tài)碼 | 200 |
$body_bytes_sent | 給客戶端發(fā)送的文件主體內容字節(jié) | 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和所有經(jīng)過的代理服務器的IP | 10.1.9.98 |
日積月累下,日志文件會越來越大,日志文件太大嚴重影響服務器效率,所以需要定時對日志文件進行切割。
由于這里是演示,所以切割方式是按分鐘來切割,正常生產(chǎn)上使用一般是按天來進行分割:
#!/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 主進程發(fā)送 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,表示直連的那臺代理)。當服務器無法過remote addr(遠程ip,表示直連的那臺代理)。當服務器無法過http_x_forwarded_for獲得上級代理或者客戶端的ip時(可能沒有經(jīng)過代理),應該使用$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中,如果請求沒有經(jīng)過nginx代理,可以使用如下方法獲取客戶端的真實IP:
# 類似nginx中的$remote_addr request.getRemoteHost();
如果請求經(jīng)過了nginx代理,可以從請求頭中獲?。ㄇ疤崾潜仨氄_配置nginx才能獲取到):
request.getHeader("x-real-ip");
如果是用的其他Apache,Squid等反向代理軟件,同樣是從請求頭中獲取真實IP,只是屬性名不一樣而已。
到此這篇關于項目中Nginx多級代理是如何獲取客戶端的真實IP地址的文章就介紹到這了,更多相關Nginx多級代理獲取客戶端真實IP內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解Nginx + Tomcat 反向代理 負載均衡 集群 部署指南
Nginx是一種服務器軟件,也是一種高性能的http和反向代理服務器,本篇文章主要介紹了Nginx + Tomcat 反向代理 負載均衡 集群 部署指南,有興趣的可以了解一下。2016-12-12Nginx實現(xiàn)https網(wǎng)站配置代碼實例
這篇文章主要介紹了Nginx實現(xiàn)https網(wǎng)站配置代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-11-11Keepalived實現(xiàn)Nginx負載均衡高可用的示例代碼
這篇文章主要介紹了Keepalived實現(xiàn)Nginx負載均衡高可用的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04