nginx配置获取客户端的真实ip
场景描述:
访问路径: A机器 - > B机器的 ->C虚拟机 :
A机器为客户端用户,本地地址为 192.168.0.110
B机器为服务端反向代理服务器 本地地址为192.168.0.128 –>(192.168.56.1)
C机器为B主机安装的linux虚拟机,并安装了nginx ,本地ip为**(192.168.56.10)**
从侧面反映了反向代理的好处,直接从A是无法访问C的,但是在B中做了反向代理 ,就能访问了,保护了服务端的地址。而无法将C的ip暴露给客户端A
注意:在B和C直接由于使用了虚拟机,虚拟机的网关的ip为192.168.56.1 所以 在C端取到的上一层ip为192.168.56.1
目的: 在C机器取到 A的ip地址,并输出日志客户端的真实ip为192.168.0.110
B机器的nginx 配置:(首层代理)
location /bb/ {proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $remote_addr;proxy_pass http://192.168.56.10/cc/;}
在B中的nginx 中 给请求设置了 header 。 X-Real-IP 和 X-Forwarded-For
X-Real-IP 取得值是 r e m o t e a d d r ,而 remote_addr ,而 remoteaddr,而remote_addr为与主机B直连客户端A 的ip地址。
X-Forwarded-For 取得值是个用逗号分隔得多个值,主要包括客户端X-Forwarded-For的值 与 $remote_addr 的值,两部分用逗号分隔。
所以此时 X-Real-IP 为 192.168.0.110, X-Forwarded-For 为 ,192.168.0.110 此时客户端并未主动传 X-Forwarded-For 头。
proxy_set_header X-Real-IP $remote_addr;这句的作用是将客户端的IP地址赋值给X-Real-IP请求头,$remote_addr变量表示与nginx服务器直接连接的客户端或代理服务器的IP地址。这句一般用于第一层代理服务器,以便后续的代理服务器能够获取到客户端的IP地址。proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;这句的作用是将客户端请求头中的X-Forwarded-For和 r e m o t e a d d r 两部分用逗号分隔后赋值给 X − F o r w a r d e d − F o r 请求头, remote_addr两部分用逗号分隔后赋值给X-Forwarded-For请求头, remoteaddr两部分用逗号分隔后赋值给X−Forwarded−For请求头,proxy_add_x_forwarded_for变量表示客户端请求头中的X-Forwarded-For和$remote_addr两部分。这句一般用于非首层代理服务器,以便将客户端和所有经过的代理服务器的IP地址都记录下来。
C中nginx 输出的log-format
log_format main '$http_x_forwarded_for|$realip_remote_addr|$http_x_real_ip|$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for" ''$upstream_addr $request_time $upstream_response_time ';
C中nginx的配置
http {include /etc/nginx/mime.types;default_type application/octet-stream;proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# real_ip_header X-Forwarded-For;# set_real_ip_from 192.168.56.1;# real_ip_recursive on;
}
在这一层中 X-Real-IP 取到的是上层代理的地址,也就是192.168.56.1
X-Forwarded-For 是上两层的地址? : 192.168.0.110,192.168.56.1 (这一层其实就一个值还是192.168.0.110,在下一层才是这两个值,这里有些歧义,原因是这一层接收到值之后 还没有拼接本层获取上一层的地址。这一层只是待发送状态。proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 这个是将头拼接后发给下一层的。所以在下一层取到地址才是 192.168.0.110,192.168.56.1 )
所以在c中的输出日志中打印的值为
192.168.0.110|192.168.56.1|192.168.0.110|192.168.56.1 - - [15/Sep/2023:02:32:43 +0000] "GET /cc/ HTTP/1.0" 200 15539 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" "192.168.0.110" 123.121.155.167:16002 0.326 0.326
如果我使用nginx自带的模块 realip 再固定一层,重点观察$remote_addr的值
http {include /etc/nginx/mime.types;default_type application/octet-stream;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;real_ip_header X-Forwarded-For;set_real_ip_from 192.168.56.1;real_ip_recursive on;
}
如果我将配置改成这样,我们再来观察一下日志输出
192.168.0.110|192.168.56.1|192.168.0.110|192.168.0.110 - - [15/Sep/2023:02:46:38 +0000] "GET /cc/ HTTP/1.0" 200 15539 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" "192.168.0.110" 123.121.155.167:16002 0.796 0.796
上述描述只是两层代理,为了测试出 X-Forwarded-For 的值,我们设置了3层代理。
A -》B-》c-》d
A:192.168.0.110 B:192.168.0.104 C:192.168.0.128(192.168.56.1) D:192.168.56.10
B nginx 配置:
location /testIp/ {# set $current-X-Fowarded-for X-Forwarded-For proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $remote_addr;proxy_pass http://192.168.0.128:6666/testIp/;}
C nginx配置:
location /testIp/ {# set $current-X-Fowarded-for X-Forwarded-For proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.56.10/testIp/;}
D nginx 配置:
http {include /etc/nginx/mime.types;default_type application/octet-stream;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# real_ip_header X-Forwarded-For;# set_real_ip_from 192.168.56.1;# real_ip_recursive on;.....localtion /testIp/ {porxy_pass http://666.com}}
D 中nginx的日志
192.168.0.110, 192.168.0.104|192.168.56.1|192.168.0.104|192.168.56.1 - - [15/Sep/2023:03:26:30 +0000] "GET /testIp/ HTTP/1.0" 200 15539 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" "192.168.0.110, 192.168.0.104" 192.168.0.104:82 0.299 0.299
192.168.0.110, 192.168.0.104 是输出的X-forwarded-for 的值。
real_ip_header X-Forwarded-For;set_real_ip_from 192.168.56.1;real_ip_recursive on;
这三个值一般是加到最后的D中,为了设置授信ip为上层的remot_addr的值,
- set_real_ip_from:用于设置信任的 IP,即请求头中的 IP 中 nginx 认为可信的 IP。一般是前几层代理的 IP。
- real_ip_header:用于告诉 nginx 从哪个请求头字段中获取客户端真实的 IP。一般是 X-Forwarded-For 或 X-Real-IP。
- real_ip_recursive:用于控制 nginx 如何从请求头字段中获取多个 IP 中的一个。当值为 on 时,nginx 会从右往左排除信任的 IP,取最后一个非信任的 IP 作为客户端真实的 IP。
例如,如果您想从 X-Forwarded-For 字段中获取客户端真实的 IP,并且信任 192.168.56.1 这个 IP,您可以在 location 中添加以下代码:
location /test {proxy_pass http://backend;real_ip_header X-Forwarded-For;set_real_ip_from 192.168.56.1;real_ip_recursive on;
}
这样,nginx 就会把 X-Forwarded-For 字段中最后一个非 192.168.56.1 的 IP 赋值给 $remote_addr 变量,作为客户端真实的 IP。
对于nginx 获取客户端真实ip做个总结
- 对于首层代理服务器,使用
proxy_set_header X-Forwarded-For $remote_addr;来将客户端IP赋值给X-Forwarded-For请求头 - 对于非首层代理服务器,使用
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;来将客户端请求头中的X-Forwarded-For和$remote_addr两部分用逗号分隔后赋值给X-Forwarded-For请求头
ursive on;
}
这样,nginx 就会把 X-Forwarded-For 字段中最后一个非 192.168.56.1 的 IP 赋值给 $remote_addr 变量,作为客户端真实的 IP。
对于nginx 获取客户端真实ip做个总结
对于首层代理服务器,使用proxy_set_header X-Forwarded-For $remote_addr;来将客户端IP赋值给X-Forwarded-For请求头
- 对于非首层代理服务器,使用
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;来将客户端请求头中的X-Forwarded-For和$remote_addr两部分用逗号分隔后赋值给X-Forwarded-For请求头 - 如果有多层代理服务器,可以使用nginx的realip模块来从XFF中抛弃指定的可信IP,从而获取用户真实IP
相关文章:
nginx配置获取客户端的真实ip
场景描述: 访问路径: A机器 - > B机器的 ->C虚拟机 : A机器为客户端用户,本地地址为 192.168.0.110 B机器为服务端反向代理服务器 本地地址为192.168.0.128 –>(192.168.56.1) C机器为B主机安…...
1990-2022上市公司董监高学历工资特征信息数据/上市公司高管信息数据
1990-2022上市公司董监高学历工资特征信息数据/上市公司高管信息数据 1、时间:1990-2022年(统计截止日期为 2022年7月) 2、指标:证券代码、统计截止日期、姓名、国籍、籍贯、籍贯所在地区代码、出生地、出生地所在地区代码、性别…...
Java程序连接 Mysql 超时问题 - 数据包过大,导致超时,# 配置网络超时时间 socketTimeout: 1800000
问题 Java程序连接 Mysql 超时问题 解决方法 如果存在 yml 等类似的配置文件,那么可以配置一下 socket 连接超时的参数,例如 # 配置网络超时时间 半小时,计算公式 60秒*1000毫秒*30分钟 socketTimeout: 1800000...
c++分层最短路(洛谷飞行路线)acwing版
分层最短路算法是在SPFA算法的基础上,将每个点分成若干层,从而使得每个点之间的转移只在同一层次或上下两个相邻层次之间进行,减少了每轮的迭代次数,优化了算法的效率。 #include <iostream> #include <cstdio> #inc…...
Python bs4 BeautifulSoup库使用记录
目录 介绍 安装 初始化 解析器 使用方法 优势 Python标准库 lxml HTML lxml XML html5lib 格式化输出 对象 tag Name 多值属性 其他方法 NavigableString BeautifulSoup Comment 遍历 子节点 父节点 兄弟节点 回退和前进 搜索 过滤器 字符串 正则表达…...
Jmeter系列-插件安装(5)
前言 jmeter4.0以上,如现在最新的5.2.1版本是有集成插件的只需要在官网下载 plugins-manager.jar 包,放在jmeter安装路径的lib/ext目录下即可使用:https://jmeter-plugins.org/install/Install/但并不能满足所有需求,仍然需要安装…...
spring aop源码解析
spring知识回顾 spring的两个重要功能:IOC、AOP,在ioc容器的初始化过程中,会触发2种处理器的调用, 前置处理器(BeanFactoryPostProcessor)后置处理器(BeanPostProcessor)。 前置处理器的调用时机是在容器基本创建完成时ÿ…...
使用Unity的Input.GetAxis(““)控制物体移动、旋转
使用Unity的Input.GetAxis("")控制物体移动、旋转 Input.GetAxis("") 是 Unity 引擎中的一个方法,用于获取游戏玩家在键盘或游戏手柄上输入的某个轴(Axis)的值。这里的 "" 是一个字符串参数,表示要…...
【CSS】画个三角形或圆形或环
首先通过调整边框,我们可以发现一些端倪 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><style>.box{width: 150px;height:150px;border: 50px solid black;}</style&g…...
AI项目六:基于YOLOV5的CPU版本部署openvino
若该文为原创文章,转载请注明原文出处。 一、CPU版本DEMO测试 1、创建一个新的虚拟环境 conda create -n course_torch_openvino python3.8 2、激活环境 conda activate course_torch_openvino 3、安装pytorch cpu版本 pip install torch torchvision torchau…...
记录YDLidar驱动包交叉编译时出现的一点问题
由于一不小心把交叉编译的系统根目录破坏了,所以一股脑将交叉编译系统根目录全删了重新安装,安装后,交叉编译发现ydlidar的ros包驱动出现了库无法链接的错误(刚刚还是好好的),但是又想不起来之前是怎么解决的了,所以还…...
嵌入式学习笔记(32)S5PV210的向量中断控制器
6.6.1异常处理的2个阶段 可以将异常处理分为2个阶段来理解。第一个阶段是异常向量表跳转;第二个阶段是进入了真正的异常处理程序irq_handler之后的部分。 6.6.2回顾:中断处理的第一个阶段(异常向量表跳转阶段)处理 (…...
linux下安装qt、qt触摸屏校准tslib
linux下安装qt 在 Linux 系统下安装 Qt,可以通过以下步骤进行操作:1. 下载 Qt 安装包:首先,你需要从 Qt 官方网站(https://www.qt.io/)下载适用于 Linux 的 Qt 安装包。选择与你的系统和需求相匹配的版本&…...
C++之unordered_map,unordered_set模拟实现
unordered_map,unordered_set模拟实现 哈希表源代码哈希表模板参数的控制仿函数增加正向迭代器实现*运算符重载->运算符重载运算符重载! 和 运算符重载begin()与end()实现 unordered_set实现unordered_map实现map/set 与 unordered_map/unordered_set对比哈希表…...
React Router,常用API有哪些?
react-router React Router是一个用于构建单页面应用程序(SPA)的库,它是用于管理React应用中页面导航和路由的工具。SPA是一种Web应用程序类型,它在加载初始页面后,通过JavaScript来动态加载并更新页面内容࿰…...
JVM类加载和双亲委派机制
当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把类加载到JVM,本文主要说明类加载机制和其具体实现双亲委派模式。 一、类加载机制 类加载过程: 类加载的过程是将类的字节码加载到内存中的过程,主要包括…...
P-MVSNet ICCV-2019 学习笔记总结 译文 深度学习三维重建
文章目录 5 P-MVSNet ICCV-20195.0 主要特点5.1 文章概述5.2 研究方法5.2.1 特征提取5.2.2 学习局域匹配置信5.2.3 深度图预测5.2.4 Loss方程MVSNet系列最新顶刊 对比总结5 P-MVSNet ICCV-2019 深度学习三维重建 P-MVSNet-ICCV-2019(原文、译文、批注) 下载 5.0 主要特点 …...
vueshowpdf 移动端pdf文件预览
1、安装 npm install vueshowpdf -S2、参数 属性说明类型默认值v-model是否显示pdf--pdfurlpdf的文件地址String- scale 默认放大倍数 Number1.2 minscale 最小放大倍数 Number0.8 maxscale 最大放大倍数 Number2 3、事件 名称说明回调参数closepdf pdf关闭事件-pdferr文…...
C#根据excel文件中的表头创建数据库表
C#根据excel文件中的表头创建数据库表 private void button1_Click(object sender, EventArgs e){string tableName tableNameTextBox.Text;string connectionString "";using (OpenFileDialog openFileDialog new OpenFileDialog()){openFileDialog.Filter &quo…...
js通过xpath定位元素并且操作元素以下拉框select为例
js也可以使用xpath定位元素,现在实例讲解。 页面上有一个下拉框,里面内容有三个,用F12看一下 一、使用xpath定位这个下拉框select eldocument.evaluate(//select[name"shoppingPreference"], document).iterateNext()二、为下拉框…...
5个核心功能:彻底掌握Nexus Mods App模组管理技巧
5个核心功能:彻底掌握Nexus Mods App模组管理技巧 【免费下载链接】NexusMods.App Home of the development of the Nexus Mods App 项目地址: https://gitcode.com/gh_mirrors/ne/NexusMods.App Nexus Mods App是一款革命性的游戏模组管理器,专为…...
开源协作平台smouj:微内核插件化架构与全栈部署实战
1. 项目概述:一个开源协作平台的诞生与价值 最近在开源社区里,一个名为“smouj/smouj”的项目引起了我的注意。乍一看这个标题,你可能会有点摸不着头脑,这不像我们常见的“vue/vue”或“tensorflow/tensorflow”那样一目了然。但恰…...
Gemini3.1Pro:商业分析框架搭建神器
做咨询的人都知道,真正难的从来不是“找到信息”,而是“把信息组织成框架”。 很多商业分析问题看起来复杂,本质上都是在有限时间内,把零散材料整理成一个能支撑判断的逻辑结构。如果你经常做行业分析、竞品分析、市场调研、经营诊…...
初识java(三):运算符
目录 一:什么是运算符 二:算术运算符 1. 基本四则运算符:加减乘除模( - * / %) 2.增量运算符 - * % 3. ⾃增/⾃减运算符 -- 三:关系运算符 四:逻辑运算符(重点) 1.逻辑与&& 2.逻辑 || …...
Java 程序员第 4 阶段:入门 Embedding 向量嵌入,弄懂大模型语义底层逻辑
前言Embedding(向量嵌入) 是大模型理解语义的核心技术,也是构建 RAG、知识库、语义搜索的基础。理解 Embedding 的原理,是进阶大模型开发的关键。本篇文章将深入讲解 Embedding 向量嵌入技术,从原理到 Java 实现&#…...
号卡系统后台一键生图换图添加随心ai密钥教程
号卡产品全新上线随心ai一键生图、智能换图功能,操作极简,秒出优质素材,告别手动作图。 1.登录号卡系统后台首页先更新版本2.到号卡系统设置——系统系统设置——号卡设置——下滑就可以看到随心AI密钥入口需要填写密钥3.随心ai密钥申请入口h…...
OpenClaw:重新定义 AI 智能体,从对话到执行的全能 “龙虾
在 AI 技术飞速迭代的今天,大语言模型已能流畅对话、生成内容,但多数仍停留在 “只说不做” 的层面。OpenClaw(外号 “龙虾”)的出现,打破了这一僵局 —— 它是一款由奥地利工程师 Peter Steinberger 主导开发…...
STM32F103 IAP实战:从Bootloader设计到远程固件更新
1. 为什么你的STM32需要IAP升级? 第一次接触IAP(In-Application Programming)这个概念时,我正蹲在工厂车间的设备旁边,手里拿着需要升级的STM32板子发愁。产线上30台设备需要更新程序,而每台设备都要拆外壳…...
构建AI智能体技能超市:标准化工作流与多平台适配实践
1. 项目概述:一个面向AI智能体的“技能超市”如果你和我一样,每天都在和Codex、Claude、Cursor这些AI助手打交道,那你肯定也遇到过这样的场景:想让AI帮你生成一份规范的Git提交信息、自动更新文档索引,或者为一个新项目…...
基于GitHub Webhook的自动化协作平台:Octopal架构设计与实现
1. 项目概述:一个面向开发者的开源协作平台最近在GitHub上看到一个挺有意思的项目,叫“pmbstyle/Octopal”。光看名字,你可能会联想到“Octopus”(章鱼)和“GitHub”(其吉祥物是章鱼猫Octocat)&…...
