上回我们讲到,因为nginx反向代理x_forward_for的设置,导致grafana请求头的ip字节过长,无法获取zabbix的数据。
先看官方对proxy_set_header的解释:
Allows redefining or appending fields to the request header passed to the proxied server. (允许重新定义或者追加传递到proxy server的header )
An unchanged “Host” request header field can be passed like this:
proxy_set_header Host $http_host;复制
However, if this field is not present in a client request header then nothing will be passed. In such a case it is better to use the $host variable - its value equals the server name in the “Host” request header field or the primary server name if this field is not present:
proxy_set_header Host $host;复制
$proxy_add_x_forwarded_for
the “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.($proxy_add_x_forwarded_for是客户端X-Forwarded-For的值, 如果客户端header中没有设置, 则$proxy_add_x_forwarded_for 等于$remote_addr)
We use proxy_set_header directives to pass relevant information to the WAP servers, and also so we can capture it in the logs:
The X-Real-IP header contains the source (client's) IP address as captured in the $remote_addr variable.
The X-Forwarded-For conveys that header from the client request, with the client’s IP address appended to it (or just that address if the client request doesn’t have the header).(X-Real-IP包含客户端原始的IP,可以被$remote_addr捕获,X-Forwarded-For 代表客户端header中标记的IP, 它可以被$proxy_add_x_forward_for捕获, 如果header没有X-Forwarded-For 则它和$remoter_addr是相同的)
我们直接看实验,看完你就明白了:
我准备了3台nginx和一台windows(作为客户端访问)
windows:192.168.2.1
nginx1:192.168.2.2
user root;
worker_processes auto;
events {
worker_connections 1024;
}
http {
log_format main 'host:$host | http_host:$http_host |'
'proxy_host:$proxy_host | remote_addr:$remote_addr |'
'realip:$http_x_real_ip | $status |'
'xforward:$http_x_forwarded_for';
access_log tmp/access.log main;
server {
listen 801;
location ^~ {
proxy_pass http://192.168.2.128/;
#proxy_set_header Host $http_host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
复制
nginx2:192.168.2.128
user root;
worker_processes auto;
events {
worker_connections 1024;
}
http {
log_format main 'host:$host | http_host:$http_host |'
'proxy_host:$proxy_host | remote_addr:$remote_addr |'
'realip:$http_x_real_ip | $status |'
'xforward:$http_x_forwarded_for';
access_log tmp/access.log main;
server {
listen 80;
location ^~ {
proxy_pass http://192.168.2.4/;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
复制
nginx3:192.168.2.4
user root;
worker_processes auto;
events {
worker_connections 1024;
}
http {
log_format main 'host:$host | http_host:$http_host |'
'proxy_host:$proxy_host | remote_addr:$remote_addr |'
'realip:$http_x_real_ip | $status |'
'xforward:$http_x_forwarded_for';
access_log tmp/access.log main;
server {
listen 80;
location ^~ {
root "/var/www/html";
index index.html;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
复制
$host #HTTP请求行的主机名复制
$remote_addr #客户端地址
$status #HTTP响应代码复制
$http_host #请求地址,即浏览器中你输入的地址(IP或域名)
$proxy_add_x_forwarded_for#变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开。
访问流程:windows——>nginx1——>nginx2——>nginx3
先全部注释掉proxy_set_header的配置,访问日志如下:
nginx1(192.168.2.2)
host:192.168.2.2 | http_host:192.168.2.2:801 | proxy_host:192.168.2.128 | remote_addr:192.168.2.1 | realip:- | 304 | xforward:-
复制
nginx2(192.168.2.128)
host:192.168.2.128 | http_host:192.168.2.128 | proxy_host:192.168.2.4 | remote_addr:192.168.2.2 | realip:- | 304 | xforward:-
复制
nginx3(192.168.2.4)
host:192.168.2.4 | http_host:192.168.2.4 | proxy_host:- | remote_addr:192.168.2.128 | realip:- | 304 | xforward:-
复制
从日志可以看到,除了作为流量入口nginx1(2.2)的日志有分析价值外,其他的都没什么用。
开启配置后再看:
nginx1(192.168.2.2)
host:192.168.2.2 | http_host:192.168.2.2:801 | proxy_host:192.168.2.128 | remote_addr:192.168.2.1 | realip:- | 304 | xforward:-
复制
nginx2(192.168.2.128)
host:192.168.2.2 | http_host:192.168.2.2:801 | proxy_host:192.168.2.4 | remote_addr:192.168.2.2 | realip:192.168.2.1 | 304 | xforward:192.168.2.1
复制
nginx3(192.168.2.4)
host:192.168.2.2 | http_host:192.168.2.2 | proxy_host:- | remote_addr:192.168.2.128 | realip:192.168.2.2 | 304 | xforward:192.168.2.1, 192.168.2.2
复制
对比之后,效果很明显。我想你应该清楚了,简单地说,proxy_set_header可以修改发往后端服务器的请求头,让后端了解前端的真实信息,当存在多层代理的时候,合理的配置可以让信息更漂亮。比如,这边的nginx3的realip其实是有问题的,我想聪明的你应该已经找到解决办法了。
部分内容摘自网络,如有侵权,请联系作者删除。