专栏首页小勇DW3nginx之配置proxy_set_header问题梳理

nginx之配置proxy_set_header问题梳理

客户端请求web服务,客户端:
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修改为如下:

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"';

proxy_set_header Host $host;

这里的Host变量的值对应的就是日志中的 $http_host 的值

当客户端用户访问 http://192.168.223.136:8080/proxy_path/index.html 时

查看代理服务器和后端服务器的地址,可以发现 $http_host 对应的值为: 192.168.223.136:8080

192.168.223.1 - - [18/Jul/2017:10:21:25 +0800] "GET /favicon.ico HTTP/1.1" 192.168.223.136:8080 404 24 "http://192.168.223.136:8080/proxy_path/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "-"

由于我将后端服务器关闭了,所以出现502网管错误:

然后开启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代理服务器,也就是客户端请求的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

但是区别在于:

$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开。

举个例子,有一个web应用,在它之前通过了两个nginx转发,www.linuxidc.com 即用户访问该web通过两台nginx。

在第一台nginx中,使用

proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

现在的$proxy_add_x_forwarded_for变量的"X-Forwarded-For"部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。

到了第二台nginx,使用

proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;

现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了

“用户的真实ip,第一台nginx的ip”。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MySql数据库实现分布式的主从结构

    最近学习了关于使用MySql数据的实现主动结构的原理,在以前的并发访问低的场景一下,一般一台性能高的服务器作为一个MySql数据,就可以满足业务的增删改查场景,...

    小勇DW3
  • Kafka如何保证百万级写入速度已经保证不丢失不重复消费

    “这篇文章来聊一下Kafka的一些架构设计原理,这也是互联网公司面试时非常高频的技术考点。

    小勇DW3
  • JVM调优日志解析分析

    -XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)

    小勇DW3
  • nginx限制上传大小和超时时间设置说明/php限制上传大小

    现象说明: 在服务器上部署了一套后台环境,使用的是nginx反向代理tomcat架构,在后台里上传一个70M的视频文件,上传到一半就失效了! 原因是nginx配...

    洗尽了浮华
  • Nginx配置文件的理解

    小俊丶Eternally
  • Nginx配置文件的理解

    小俊丶Eternally
  • 无懈可击的web设计-读书笔记1

    <html> <head> <title>Page Title</title>

    lilugirl
  • Spring AOP的三种实现方式

    参考:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.ht...

    week
  • nginx被动检测

    随着应用越来越多,tomcat容器也越来越重,随之而来的是tomcat宕机越来越频繁。最终选择jar包部署测试反向代理的效果。虽然jar包部署之后项目肯定会稳...

    程序员_备忘录
  • 【AI芯展开推理战】赛灵思最新深度神经网络推理器xDNN参数曝光

    目前来看,FPGA可能没有像一些人预期的那样在深度学习的训练空间中占据一席之地,但AI推理的低功耗、高频率需求非常适合可重复编程硬件的性能曲线。

    新智元

扫码关注云+社区

领取腾讯云代金券