概述

我们在做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. 关于连接内部服务器以及redis缓存基本操作

    1.linux命令行远程连接内部服务器 ssh -p 6637 mndevops@172.18.11.183 //建立连接命令 端口号和用户名+ip 输入密码 ./redis-cli 进入redis数 ...

  2. 从联想昭阳到MacBook Pro,致我的那些败家玩意——电脑

    对于程序员来说,你懂的,电脑就是我们的女朋友,在很多层面上,它都是,打游戏.敲代码,以及看影片. 我第一台电脑是联想的笔记本(昭阳系列),花了 4000 多块买的. 那时候,家里很是缺钱,4000 多 ...

  3. C - Battle City BFS+优先队列

    Many of us had played the game "Battle city" in our childhood, and some people (like me) e ...

  4. 百度关键词搜索工具 v1.1|url采集工具 v1.1

    功能介绍:关键词搜索工具 批量关键词自动搜索采集 自动去除垃圾二级泛解析域名 可设置是否保存域名或者url 持续更新中

  5. Redis安装部署(一主二从三哨兵)

    需求:根据当前客户的生产环境,模拟安装部署Redis的测试环境,方便后续的功能测试. 1.准备工作 2.安装编译Redis 3.Redis运行环境配置 4.Redis启动和关闭 1.准备工作 Redi ...

  6. [PHP] excel 的导入导出

    其实excel导入导出挺简单的,导出最简单! 其原理都是把数据读出来,导出是从数据库中读出数据,导入是从文件读出数据! 导出写入文件,导入写入数据库! 但是在导入表的时候,用的是PHPExcel, 不 ...

  7. [YII2] 去除自带js,加载自己的JS,然后ajax(json)传值接值!

    本想用YII2自带的JS,可是用着效果不好,想从新加载,找了好多终于实现啦!还有ajax(json)传值接值! 首先直接了当的就把YII2自带的js去掉! 把下面代码加入到/config/main.p ...

  8. C# 序列化之二进制

    序列化:又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方. 一般有三种方式:1.是使用BinaryF ...

  9. Linux-Discuz安装LAMP

    1.下载,解压Discuz cd /data/discuz wget http://download.comsenz.com/DiscuzX/3.2/Discuz_X3.2_SC_GBK.zip un ...

  10. MySQL中出现Unknow column 'xx' in field list的解决办法

    首先创建一个表,然后插入数据发现出错误 经过多次尝试发现title前面多了一个空格 我们把空格去掉,然后在插入数据,发现数据创建成功