概述

我们在做nginx方向代理的时候,为了记录整个代理过程,我们往往会在配置文件中加上如下配置:

location ^~ /app/download/ {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
proxy_pass http://10.1.10.203:8080;
}

proxy_set_header就是记录整个代理过程的配置。其中X-Forwarded-For(XFF)位于HTTP请求头,已经成为事实上的标准。
XFF的请求格式很简单,如下:

X-Forwarded-For: client, proxy1, proxy2

由上面可以看到XFF的的内容由[IP+英文逗号+空格]组成(如果有多个代理的话),最开始的client是客户端的IP,proxy1和proxy2分别是一级代理和二级代理的IP。
假设代理如下:

如上,proxy1、proxy2和proxy3都用NG做反代,并且在它们的配置上都加上如下配置:

proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

那么在Real Server(NG的WEB容器)上打印的日志(日志里带$http_x_forwarded_for)就会带有IP0,IP1,IP2的HTTP头,可以看到没有IP3,因为IP3是直连服务器,它会给XFF追加IP2的地址,表示它是帮proxy2做转发的,Real Server要获取IP3的地址,需通过remote Address字段获得。
同理,在proxy3上日志里只会有IP0和IP1,proxy2上日志里只有IP0,proxy1上没有IP。

测试

测试拓扑如下:

在proxy1上的配置如下:

    server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html; # Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf; location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.169.130/;
}
}

在proxy2上的配置如下:

    server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html; # Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf; location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.169.131/;
}
}

在proxy3的配置如下:

    server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html; # Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf; location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://xxx.xxx.xxx.xxx:8888/;
}
}

proxy1,proxy2,proxy3上的日志格式如下:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

Real Server日志格式如下:

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent $upstream_cache_status "$http_referer" '
'"$http_user_agent" "==$http_x_forwarded_for" "--$http_x_real_ipi"';

我在本机浏览器输入:http://192.168.169.128/,然后分别在proxy1-3还有Real Server上抓取nginx日志,proxy1-3日志最后一个字段是$http_x_forwarded_for,Real Server倒数二个字段是$http_x_forwarded_for如下:
proxy1日志:

192.168.169.1 - - [04/Jun/2019:10:57:06 +0800] "GET / HTTP/1.1" 200 20 "-"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/74.0.3729.169 Safari/537.36" "-"

proxy2日志:

192.168.169.128 - - [04/Jun/2019:10:57:06 +0800] "GET / HTTP/1.0" 200 10 "-"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/74.0.3729.169 Safari/537.36" "192.168.169.1"

proxy3日志:

192.168.169.130 - - [29/Mar/2019:23:29:36 +0800] "GET / HTTP/1.0" 200 10 "-"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/74.0.3729.169 Safari/537.36" "192.168.169.1, 192.168.169.128"

Real Server日志:

183.66.224.50 - - [04/Jun/2019:10:57:03 +0800] "GET / HTTP/1.0" 200 10 - "-"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/74.0.3729.169 Safari/537.36" "==192.168.169.1, 192.168.169.128, 192.168.169.130" "---"

从上面的日志可以知道:
(1)、设置X-Forwarded-For是一个可叠加的过程;
(2)、后端服务器XFF获取不到直连服务器IP。比如Real-Server的日志中XFF字段没有proxy3的IP地址,依次类推;
(3)、代理中要配置proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

HTTP请求头中的X-Forwarded-For介绍的更多相关文章

  1. HTTP 请求头中的 X-Forwarded-For(转)

    原文:https://imququ.com/post/x-forwarded-for-header-in-http.html 我一直认为,对于从事 Web 前端开发的同学来说,HTTP 协议以及其他常 ...

  2. Http 请求头中的 Proxy-Connection

    平时用 Chrome 开发者工具抓包时,经常会见到 Proxy-Connection 这个请求头.之前一直没去了解什么情况下会产生它,也没去了解它有什么含义.最近看完<HTTP 权威指南> ...

  3. js 中ajax请求时设置 http请求头中的x-requestd-with= ajax

    今天发现 AngularJS 框架的$http服务提供的$http.get() /$http.post()的ajax请求中没有带 x-requested-with字段. 这样的话,后端的php 就无法 ...

  4. HTTP 请求头中的 Remote_Addr,X-Forwarded-For,X-Real-IP

    REMOTE_ADDR 表示发出请求的远程主机的 IP 地址,remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间 ...

  5. shiro + jwt 实现 请求头中的 rememberMe 时间限制功能

    前言: 上一篇提出, 通过修改 rememberMe 的编码来实现 rememberMe的功能的设想, 事后我去尝试实现了一番, 发现太麻烦, 还是不要那么做吧. 程序还是要越简单越好. 那功能总是要 ...

  6. shiro 获取请求头中的 rememberMe

    前言: 上一篇提到了, 将 sessionId 放到请求头中去, 那rememberMe是否也可以放到请求头中去呢. 其实不管是sessionId还是rememberMe, shiro都会默认往coo ...

  7. shiro 获取请求头中的 sessionId

    前言: 在前后端项目中, 前端有可能会要求, 后台返回一个 sessionId 给他, 然后他在请求后台接口时, 把这个sessionId 带给后台, 后台拿到这个sessionId , 就能识别, ...

  8. Ajax 请求头中常见content-type

    四种常见的 POST 提交数据方式 HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范.规范把 HTTP 请求分为三个部分:状态行.请求头.消息主体.协议规定 POST ...

  9. WebAPi获取请求头中对应键值

    /// <summary> /// 依据键获取请求头中值数据 /// </summary> /// <param name="request"> ...

  10. 使用zuul实现验证自定义请求头中的token

    路由:她会把外部所有对请求转发到具体的微服务实例上,是实现外部访问同一接口的基础 过滤: 就是权限的检查, 判断当前的请求是否有权限区访问那些服务集群 搭建后台网关: 导入eureka - clien ...

随机推荐

  1. TP的where方法的使用

    1.Thinkphp中where()条件的使用 总是有人觉得,thinkphp的where()就是写我要进行增加.查询.修改.删除数据的条件,很简单的,其实我想告诉你,where()是写条件语句的,但 ...

  2. C++线性表的链式存储结构

    C++实现线性表的链式存储结构: 为了解决顺序存储不足:用线性表另外一种结构-链式存储.在顺序存储结构(数组描述)中,元素的地址是由数学公式决定的,而在链式储存结构中,元素的地址是随机分布的,每个元素 ...

  3. Android Google Play app signing 最终完美解决方式

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/105561341 本文出自[赵彦军的博客] 在 GooglePlay 创建 App ...

  4. 微信小程序与H5数据传递

    这的场景是 小程序webview 加载 H5应用 需求点: 1. 小程序的登录code 需要与H5应用的sessionId建立绑定关系 2.H5内发起微信小程序支付,支付参数传递到小程序,支付结果传递 ...

  5. SwiftUI - 一步一步教你使用UIViewRepresentable封装网络加载视图(UIActivityIndicatorView)

    概述 网络加载视图,在一个联网的APP上可以讲得上是必须要的组件,在SwiftUI中它并没有提供如 UIKit 中的UIActivityIndicatorView直接提供给我们调用,但是我们可以通过 ...

  6. uni-app同步缓存值 设置 读取 删除

    A页面 <view class="go-to-tab" @tap="gotologin"> 去login页面 </view> msg : ...

  7. mysql优化之分区

    mysql分区类型 日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会 ...

  8. DPK

    一.概念 dpk文件是Delphi的包文件,有dpk文件的组件安装比较方便.一般来说,支持不同版本Delphi的组件会有不同的dpk文件,一般以7结尾的dpk文件是支持Delphi 7的.如果没有支持 ...

  9. Python爬虫某招聘网站的岗位信息

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:阿尔法游戏 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  10. L16 LeNet

    **本小节用到的数据下载 1.涉及语句 import d2lzh1981 as d2l 数据1 : d2lzh1981 链接:https://pan.baidu.com/s/1LyaZ84Q4M75G ...