当前位置: 首页 > news >正文

HTTP协议头中X-Forwarded-For是能做什么?

X-Forwarded-For和相关几个头部的理解

  • $remote_addr

    是nginx与客户端进行TCP连接过程中,获得的客户端真实地址. Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求

  • X-Real-IP

    是一个自定义头。X-Real-Ip 通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端。需要注意的是,X-Real-Ip 目前并不属于任何标准,代理和 Web 应用之间可以约定用任何自定义头来传递这个信息

  • X-Forwarded-For

    X-Forwarded-For 是一个扩展头。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中.

X-Forwarded-For请求头格式非常简单,就这样:

X-Forwarded-For:client, proxy1, proxy2

可以看到,XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP。

如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

Proxy3 直连服务器,它会给 XFF 追加 IP2,表示它是在帮 Proxy2 转发请求。列表中并没有 IP3,IP3 可以在服务端通过 remote_address 来自 TCP 连接,表示与服务端建立 TCP 连接的设备 IP,在这个例子里就是 IP3。

详细分析一下,这样的结果是经过这样的流程而形成的:

  1. 用户IP0—> 代理Proxy1(IP1),Proxy1记录用户IP0,并将请求转发个Proxy2时,带上一个Http Header X-Forwarded-For: IP0

  2. Proxy2收到请求后读取到请求有 X-Forwarded-For: IP0,然后proxy2 继续把链接上来的proxy1 ip追加到 X-Forwarded-For 上面,构造出X-Forwarded-For: IP0, IP1,继续转发请求给Proxy 3

  3. 同理,Proxy3 按照第二部构造出 X-Forwarded-For: IP0, IP1, IP2,转发给真正的服务器,比如NGINX,nginx收到了http请求,里面就是 X-Forwarded-For: IP0, IP1, IP2 这样的结果。所以Proxy 3 的IP3,不会出现在这里。

  4. nginx 获取proxy3的IP 能通过remote_address就是真正建立TCP链接的IP,这个不能伪造,是直接产生链接的IP。$remote_address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求。

x-forwarded-for 实践研究:

  1. uwsgi_pass的情况下,nginx 没有设置proxy_pass x-forwarded-for: $proxy_add_x_forwarded_for;

    • 如果请求头传了XFF,在flask里面能正常读取请求头里面的XFF,就是当是一个普通的头读出;如果header不传这个XFF的话,就读不到
  2. proxy_pass 情况下

    • 没有传 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的话,跟上面的uwsgi_pass 一样,都是在没有设置header XFF情况下,读不到。

    • 如果传了 proxy_set_header X-Forwarded-For remote_address),因为这句proxy_set_header 会让nginx追加一个$remote_address到XFF。

    • header 传xff的话, 程序里面可以读到Xff 头: X-Forwarded-For: 188.103.19.120, 10.0.2.2 (第一个是我自己编的,第二个是proxy_add_x_forwarded_for 这句而追加$remote_addr到XFF。

总结:

  1. 只要nginx前端(例如lvs, varnish)转发请求给nginx的时候,带了x-forwarded-for ,那么程序就一定能读到这个字段,如果nginx还设置了proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, 那么程序能读到XFF是:ip0, ip1 (客户端Ip,lvs或者varnishIP)。 如果nginx没有设置,那么nginx还是会原样把http头传给程序,也就是说程序也能读到XFF,而且XFF就是ip0 客户端IP。

  2. proxy_pass 设置这个头 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 是站在一个作为代理的角度把。能继续传输多级代理的头。

  3. nginx的日志格式写了$http_x_forwared_for 说明前端(lvs)确实传了这个头过来。所以是程序是读取到的

  4. uwsgi_pass 不能设置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 这个头,是因为这个头是对http代理来说,用来传递IP的,uwsgi 不可能充当一个代理。

  5. nginx->程序,这里其实有两个链接过程,其他IP与nginx的TCP连接, nginx与程序的TCP连接。所以$remote_addr都是对各自来说的。程序的remote_addr: remote_addr 127.0.0.1 (跟它链接的是nginx 内网127.0.0.1)nginx的remote_addr : X-Real-Ip: 10.0.2.2 (跟它链接的是我的电脑,IP 10.0.2.2)

  6. 对程序来说,读取的request.remote_addr 也永远是直接跟他链接的ip, 也就是反向代理nginx

  7. The access_route attribute uses the X-Forwarded-For header, falling back to the REMOTE_ADDRWSGI variable; 也就是说access_route默认读取XFF头,如果没有,降级读取WSGI的REMOTE_ADDR变量,这个 WSGI的REMOTE_ADDR变量 就是 $remote_addr

  8. request.envron 是WSGI的变量,都是wsgi server转过来的,普通的头都是加了HTTP_前缀的 ,包括proxy_set_header Host proxy_add_x_forwarded_for;
    添加的头都会出现在处理,因为他们就是普通的http头

  9. LVS->nginx的情况下, 请求的时候主动加XFF,程序读取的时候没显示。因为LVS设置XFF的时候,直接把直连的IP赋值给LVS,忽略掉所有本来有的XFF,要从LVS这里开始。 所以程序读到的XFF是 :XFF headers 218.107.55.254, 10.120.214.252
    前面的是我的IP, 后面的是LVS的IP

X-Forwarded-For和相关几个头部的理解

  • $remote_addr

    是nginx与客户端进行TCP连接过程中,获得的客户端真实地址. Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求

  • X-Real-IP

    是一个自定义头。X-Real-Ip 通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端。需要注意的是,X-Real-Ip 目前并不属于任何标准,代理和 Web 应用之间可以约定用任何自定义头来传递这个信息

  • X-Forwarded-For

    X-Forwarded-For 是一个扩展头。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中.

X-Forwarded-For请求头格式非常简单,就这样:

X-Forwarded-For:client, proxy1, proxy2

可以看到,XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP。

如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

Proxy3 直连服务器,它会给 XFF 追加 IP2,表示它是在帮 Proxy2 转发请求。列表中并没有 IP3,IP3 可以在服务端通过 remote_address 来自 TCP 连接,表示与服务端建立 TCP 连接的设备 IP,在这个例子里就是 IP3。

详细分析一下,这样的结果是经过这样的流程而形成的:

  1. 用户IP0—> 代理Proxy1(IP1),Proxy1记录用户IP0,并将请求转发个Proxy2时,带上一个Http Header X-Forwarded-For: IP0

  2. Proxy2收到请求后读取到请求有 X-Forwarded-For: IP0,然后proxy2 继续把链接上来的proxy1 ip追加到 X-Forwarded-For 上面,构造出X-Forwarded-For: IP0, IP1,继续转发请求给Proxy 3

  3. 同理,Proxy3 按照第二部构造出 X-Forwarded-For: IP0, IP1, IP2,转发给真正的服务器,比如NGINX,nginx收到了http请求,里面就是 X-Forwarded-For: IP0, IP1, IP2 这样的结果。所以Proxy 3 的IP3,不会出现在这里。

  4. nginx 获取proxy3的IP 能通过remote_address就是真正建立TCP链接的IP,这个不能伪造,是直接产生链接的IP。$remote_address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求。

x-forwarded-for 实践研究:

  1. uwsgi_pass的情况下,nginx 没有设置proxy_pass x-forwarded-for: $proxy_add_x_forwarded_for;

    • 如果请求头传了XFF,在flask里面能正常读取请求头里面的XFF,就是当是一个普通的头读出;如果header不传这个XFF的话,就读不到
  2. proxy_pass 情况下

    • 没有传 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的话,跟上面的uwsgi_pass 一样,都是在没有设置header XFF情况下,读不到。

    • 如果传了 proxy_set_header X-Forwarded-For remote_address),因为这句proxy_set_header 会让nginx追加一个$remote_address到XFF。

    • header 传xff的话, 程序里面可以读到Xff 头: X-Forwarded-For: 188.103.19.120, 10.0.2.2 (第一个是我自己编的,第二个是proxy_add_x_forwarded_for 这句而追加$remote_addr到XFF。

总结:

  1. 只要nginx前端(例如lvs, varnish)转发请求给nginx的时候,带了x-forwarded-for ,那么程序就一定能读到这个字段,如果nginx还设置了proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, 那么程序能读到XFF是:ip0, ip1 (客户端Ip,lvs或者varnishIP)。 如果nginx没有设置,那么nginx还是会原样把http头传给程序,也就是说程序也能读到XFF,而且XFF就是ip0 客户端IP。

  2. proxy_pass 设置这个头 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 是站在一个作为代理的角度把。能继续传输多级代理的头。

  3. nginx的日志格式写了$http_x_forwared_for 说明前端(lvs)确实传了这个头过来。所以是程序是读取到的

  4. uwsgi_pass 不能设置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 这个头,是因为这个头是对http代理来说,用来传递IP的,uwsgi 不可能充当一个代理。

  5. nginx->程序,这里其实有两个链接过程,其他IP与nginx的TCP连接, nginx与程序的TCP连接。所以$remote_addr都是对各自来说的。程序的remote_addr: remote_addr 127.0.0.1 (跟它链接的是nginx 内网127.0.0.1)nginx的remote_addr : X-Real-Ip: 10.0.2.2 (跟它链接的是我的电脑,IP 10.0.2.2)

  6. 对程序来说,读取的request.remote_addr 也永远是直接跟他链接的ip, 也就是反向代理nginx

  7. The access_route attribute uses the X-Forwarded-For header, falling back to the REMOTE_ADDRWSGI variable; 也就是说access_route默认读取XFF头,如果没有,降级读取WSGI的REMOTE_ADDR变量,这个 WSGI的REMOTE_ADDR变量 就是 $remote_addr

  8. request.envron 是WSGI的变量,都是wsgi server转过来的,普通的头都是加了HTTP_前缀的 ,包括proxy_set_header Host proxy_add_x_forwarded_for;
    添加的头都会出现在处理,因为他们就是普通的http头

  9. LVS->nginx的情况下, 请求的时候主动加XFF,程序读取的时候没显示。因为LVS设置XFF的时候,直接把直连的IP赋值给LVS,忽略掉所有本来有的XFF,要从LVS这里开始。 所以程序读到的XFF是 :XFF headers 218.107.55.254, 10.120.214.252
    前面的是我的IP, 后面的是LVS的IP

相关文章:

HTTP协议头中X-Forwarded-For是能做什么?

X-Forwarded-For和相关几个头部的理解 $remote_addr 是nginx与客户端进行TCP连接过程中,获得的客户端真实地址. Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后…...

Linux高并发服务器开发(八)Socket和TCP

文章目录 1 IPV4套接字结构体2 TCP客户端函数 3 TCP服务器流程函数代码粘包 4 三次握手5 四次挥手6 滑动窗口 1 IPV4套接字结构体 2 TCP客户端 特点:出错重传 每次发送数据对方都会回ACK,可靠 tcp是打电话的模型,建立连接 使用连接 关闭连接…...

力扣第220题“存在重复元素 III”

在本篇文章中,我们将详细解读力扣第220题“存在重复元素 III”。通过学习本篇文章,读者将掌握如何使用桶排序和滑动窗口来解决这一问题,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。 问题描述…...

Qt实战项目——贪吃蛇

一、项目介绍 本项目是一个使用Qt框架开发的经典贪吃蛇游戏,旨在通过简单易懂的游戏机制和精美的用户界面,为玩家提供娱乐和编程学习的机会。 游戏展示 二、主要功能 2.1 游戏界面 游戏主要是由三个界面构成,分别是游戏大厅、难度选择和游戏…...

Windows 10,11 Server 2022 Install Docker-Desktop

docker 前言 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 docker-compose Compose 是用于定义和运行…...

C++中的RAII(资源获取即初始化)原则

C中的RAII(Resource Acquisition Is Initialization,资源获取即初始化)原则是一种管理资源、避免资源泄漏的惯用法。RAII是C之父Bjarne Stroustrup提出的设计理念,其核心思想是将资源的获取(如动态内存分配、文件句柄、…...

【机器学习】Whisper:开源语音转文本(speech-to-text)大模型实战

目录 一、引言 二、Whisper 模型原理 2.1 模型架构 2.2 语音处理 2.3 文本处理 三、Whisper 模型实战 3.1 环境安装 3.2 模型下载 3.3 模型推理 3.4 完整代码 3.5 模型部署 四、总结 一、引言 上一篇对​​​​​​​ChatTTS文本转语音模型原理和实战进行了讲解&a…...

ubuntu22.04 编译安装openssl C++ library

#--------------------------------------------------------------------------- # openssl C library # https://www.openssl.org/source/index.html #--------------------------------------------------------------------------- cd /opt/download # 下载openssl-3.0.13…...

百度Agent初体验(制作步骤+感想)

现在AI Agent很火,最近注册了一个百度Agent体验了一下,并做了个小实验,拿它和零一万物(Yi Large)和文心一言(ERNIE-4.0-8K-latest)阅读了相同的一篇网页资讯,输出资讯摘要&#xff0…...

7-491 3名同学5门课程成绩,输出最好成绩及所在的行和列(二维数组作为函数的参数)

编程:数组存储3名同学5门课程成绩 输出最好成绩及所在的行和列 要求:将输入、查找和打印的功能编写成函数 并将二维数组通过指针参数传递的方式由主函数传递到子函数中 输入格式: 每行输入一个同学的5门课的成绩,每个成绩之间空一格,见输入…...

OpenCloudOS开源的操作系统

OpenCloudOS 是一款开源的操作系统,致力于提供高性能、稳定和安全的操作系统环境,以满足现代计算和应用程序的需求。它结合了现代操作系统设计的最新技术和实践,为开发者和企业提供了一个强大的平台。本文将详细介绍 OpenCloudOS 的背景、特性…...

排序题目:多数元素 II

文章目录 题目标题和出处难度题目描述要求示例数据范围进阶 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 解法三思路和算法代码复杂度分析 题目 标题和出处 标题:多数元素 II 出处:229. 多数元素 II 难度 3 级 题目描述 …...

<电力行业> - 《第1课:电力行业的五大四小》

1 什么是电力行业的五大四小? 我们常说的电力行业的五大四小,指的是电力行业有实力的公司,分为:较强梯队的五大集团、较弱梯队的四小豪门。 五个实力雄厚的集团,分别是: 中国华能集团公司中国大唐集团公…...

数据库定义语言(DDL)

数据库定义语言(DDL) 一、数据库操作 1、 查询所有的数据库 SHOW DATABASES;效果截图: 2、使用指定的数据库 use 2403 2403javaee;效果截图: 3、创建数据库 CREATE DATABASE 2404javaee;效果截图: 4、删除数据…...

mybatis实现多表查询

mybatis高级查询【掌握】 1、准备工作 【1】包结构 创建java项目,导入jar包和log4j日志配置文件以及连接数据库的配置文件; 【2】导入SQL脚本 运行资料中的sql脚本:mybatis.sql 【3】创建实体来包,导入资料中的pojo 【4】User…...

数据结构:队列详解 c++信息学奥赛基础知识讲解

目录 一、队列概念 二、队列容器 三、队列操作 四、代码实操 五、队列遍历 六、案例实操 题目描述: 输入格式: 输出格式: 输入样例: 输出样例: 详细代码: 一、队列概念 队列是一种特殊的线性…...

硬件开发笔记(二十三):贴片电阻的类别、封装介绍,AD21导入贴片电阻原理图封装库3D模型

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140110514 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

Kafka基本原理详解

(一)概念理解 Apache Kafka是一种开源的分布式流处理平台,专为高性能、高吞吐量的实时数据处理而设计。它最初由LinkedIn公司开发,旨在解决其网站活动中产生的大量实时数据处理和传输问题,后来于2011年开源&#xff0…...

【Unity】RPG2D龙城纷争(七)关卡编辑器之剧情编辑

更新日期:2024年7月1日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、剧情编辑1.对话数据集2.对话触发方式3.选择对话角色4.设置对话到关卡5.通关条件简介 严格来说,剧情编辑不在关卡编辑器界面中完成,只不过它仍然属于关卡编辑的范畴。 在我们的设想中…...

uniapp启动页面鉴权页面闪烁问题

在使用uni-app开发app 打包完成后如果没有token,那么就在onLaunch生命周期里面判断用户是否登录并跳转至登录页。 但是在app中页面会先进入首页然后再跳转至登录页,十分影响体验。 处理方法: 使用plus.navigator.closeSplashscreen() 官网…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

DiscuzX3.5发帖json api

参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...

一些实用的chrome扩展0x01

简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...

C++--string的模拟实现

一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...