win10客戶端請求web服務,win10的ip:192.168.223.1
nginx作為反向代理服務器:192.168.223.136
nginx作為后端web服務器:192.168.223.137
前提條件:配置nginx轉發到后端服務器
server {
listen 8080;
server_name 192.168.223.136;
location / {
root "/www/html";
index index.html;
#auth_basic "required auth";
#auth_basic_user_file "/usr/local/nginx/users/.htpasswd";
error_page 404 /404.html;
}
location /images/ {
root "/www";
rewrite ^/images/bbs/(.*\.jpeg)$ /images/$1 break;
rewrite ^/images/www/(.*)$ http://192.168.223.136/$1 redirect;
}
location /basic_status {
stub_status;
}
location ^~/proxy_path/ {
root "/www/html";
index index.html;
proxy_pass http://192.168.223.137/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
location ^~/proxy_path/ {
root "/www/html";
index index.html;
proxy_pass http://192.168.223.137/;
將左側匹配到的/proxy_path/開頭的url全部轉發到后端服務器192.168.223.137
現在一一測試各個proxy_set_header設置的變量的內容
1、proxy_set_header Host $host;
將136代理服務器,137后端服務器的log_format修改為如下:

然后開啟137后端nginx,查看日志:
192.168.223.136 "192.168.223.1" - - [17/Jul/2017:17:06:44 +0800] "GET /index.html HTTP/1.0" "192.168.223.136" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" "192.168.223.1"
即驗證了proxy_set_header Host $host; $host就是nginx代理服務器,也就是win10客戶端請求的host
2、proxy_set_header Host $proxy_host;
將設置修改為上述proxy_host然后重啟ngxin代理服務器136
[root@wadeson nginx]# sbin/nginx -s reload
重新請求代理頁面:http://192.168.223.136:8080/proxy_path/index.html,然后日志如下:
首先查看136代理服務器的日志:
192.168.223.1 - - [18/Jul/2017:10:30:12 +0800] "GET /proxy_path/index.html HTTP/1.1" 192.168.223.136:8080 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "-"
因為win10是136的客戶端,請求的host為192.168.223.136:8080,而nginx代理服務器作為137后端服務器的客戶端,將請求的報文首部重新封裝,將proxy_host封裝為請求的host
那么137上面日志請求的host就是其自身,proxy_host就是代理服務器請求的host也就是后端服務器137
192.168.223.136 "192.168.223.1" - - [18/Jul/2017:10:30:12 +0800] "GET /index.html HTTP/1.0" "192.168.223.137" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "192.168.223.1"
3、proxy_set_header Host $host:$proxy_port;
了解了上面的知識,那么此處對應的host就知道代表的啥了,$host代表轉發服務器,$proxy_port代表136轉發服務器請求后端服務器的端口,也就是80
於是觀察136、137的日志進行驗證:
192.168.223.1 - - [18/Jul/2017:10:38:38 +0800] "GET /proxy_path/index.html HTTP/1.1" 192.168.223.136:8080 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "-"
192.168.223.136 "192.168.223.1" - - [18/Jul/2017:10:38:38 +0800] "GET /index.html HTTP/1.0" "192.168.223.136:80" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "192.168.223.1"
4、proxy_set_header X-Real-IP $remote_addr;
將$remote_addr的值放進變量X-Real-IP中,此變量名可變,$remote_addr的值為客戶端的ip
nginx轉發136服務器日志格式為:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $http_host '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
nginx后端137服務器的日志格式:
log_format main '$remote_addr "$http_x_real_ip" - $remote_user [$time_local] "$request" "$http_host" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
兩者區別在於"$http_x_real_ip",添加了這個變量的值
重新請求需要訪問的地址http://192.168.223.136:8080/proxy_path/index.html
136的日志:
192.168.223.1 - - [18/Jul/2017:10:45:07 +0800] "GET /proxy_path/index.html HTTP/1.1" 192.168.223.136:8080 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "-"
137的日志:
192.168.223.136 "192.168.223.1" - - [18/Jul/2017:10:45:07 +0800] "GET /index.html HTTP/1.0" "192.168.223.136:80" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "192.168.223.1"
紅色標記的就是"$http_x_real_ip"的值,即可以看見用戶真實的ip,也就是客戶端的真實ip
5、proxy_set_header X-Forwarded-For $remote_addr;
理解了上面的含義那么這個封裝報文的意思也就請求了
首先還是比對136和137的日志格式:
136代理服務器的日志格式:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $http_host '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
137后端服務器的日志格式:
log_format main '$remote_addr "$http_x_real_ip" - $remote_user [$time_local] "$request" "$http_host" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
重新請求需要訪問的地址http://192.168.223.136:8080/proxy_path/index.html
136的日志顯示:
192.168.223.1 - - [18/Jul/2017:10:51:25 +0800] "GET /proxy_path/index.html HTTP/1.1" 192.168.223.136:8080 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "-",最后一個字段"$http_x_forwarded_for"對應的為空值
137的日志顯示:
192.168.223.136 "192.168.223.1" - - [18/Jul/2017:10:51:25 +0800] "GET /index.html HTTP/1.0" "192.168.223.136:80" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "192.168.223.1"
可以看出137后端服務器成功的顯示了真實客戶端的ip
6、proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
5、6兩者的區別:
在只有一個代理服務器的轉發的情況下,兩者的效果貌似差不多,都可以真實的顯示出客戶端原始ip
但是區別在於: