获取客户端真实IP

news/2024/9/17 18:56:49/ 标签: 运维

  出于安全考虑,近期在处理一个记录用户真实IP的需求。本来以为很简单,后来发现没有本来以为的简单。这里主要备忘下,如果服务器处于端口回流(hairpin NAT),keepalived,nginx之后,如何取得客户端的外网IP。

  来自客户端PC的流量路径如上,在这样的拓扑中,在应用服务中取得,客户端PC的外网ip,可能会遇到哪些问题呢?(ip 编的随意,为便于说明,不考虑合理)。

  • 编程实现

  Java 为例,这个我会。

    public static String getClientIP(HttpServletRequest request) {String remoteAddr = request.getRemoteAddr();return remoteAddr;}

  运行一下,输出呢是 3.3.3.3 。 这是因为这个API所取得的是IP数据包的源地址。Nginx的反向代理时工作在应用层的,当他收到一个http请求时,会对应生成一个新的请求,发送给应用服务,这个请求的IP包的源地址是Nginx服务器的IP即3.3.3.3。

  • Nginx头部注入

  因为是应用层,那这个请求ip包的源地址肯定就是3.3.3.3了,但是在应用层我们可以附加一点信息,以便后面的应用服务,可以通过这个附加信息,了解这个请求对应的原始源地址。这个我也会。

  在Nginx 中配置。

server {...proxy_set_header X-Real-IP $remote_addr;

  在应用层http协议中,加一个http header。X-Real-IP:$remote_addr. $remote_addr 是一个预设变量,代表所代理转发请求的原始源ip地址。

  在Java 程序中,读取对应的附加信息

    public String getRealIp(HttpServletRequest request) {String realIp = request.getHeader("X-Real-IP");if (realIp != null && !realIp.isEmpty()) {return "Client's Real IP: " + realIp;} return "";}    

  运行一下,此时输出2.2.2.2。 显然我们向前推进了一步。

  • Keepalived负载均衡模式

  印象里这里keepalived的主要作用应该是解决nginx 代理服务器的单点问题的,似乎也被配置为负载均衡了?翻了下配置文件,实际的情况如下。

  运维大壮说他配置keepalived 时候多考虑了一步,如果机器活着,nginx 挂了怎么办,于是又做了一层负载均衡(这种情况虚拟IP不会漂移到右边的备机)。他说的也确实不是没有道理。keepalived 的负载均衡貌似是工作在第三层的,那肯定在负载均衡的时候,又对ip包的源地址进行了修改。这是网络层,向nginx 这样附加信息肯定是不行了。于是,翻了翻手册发现,keepalived 的负载均衡支持三种路由模式,NAT,Direct Routing 和 Tunneling。

  NAT 模式,会修改源IP,出入流量都会经过负载均衡器。而DR模式,会直接修改MAC地址,那回程流量就不再经过负载均衡器了,也就意味这种模式,源地址不会被修改,回程流量会直接发送给源ip地址。

  DR模式有个要求,就是负载均衡器需要能知道后端服务的MAC地址,这是依赖于ARP实现的,也就是,要求负载均衡器和后端服务器在同一广播域。恰好我门可以满足。于是。

virtual_server 192.168.11.242 80 {
……
lb_kind DR
……

  将负载均衡路由模式切换为DR模式。重新看一下这次,取得客户端地址变成了 1.1.1.1, 这一步一坑。为什么到达keepalived的ip包的源地址会变成,出口路由器的外网地址呢?

  • 路由器端口回流(Hairpin NAT)

  离胜利是不远了,此时见多识广的大壮说,这应该是跟端口回流有关,之前有个系统也是类似问题, 你的web端口配置了端口回流,如果关掉端口回流就可以取得外网地址了。什么是端口回流?

   首先,路由器做了端口映射,1.1.1.1:80->192.168.0.2:80

  服务器A,由于某些原因,不方便使用内网地址192.168.0.2访问B,而要通过外网IP或者域名访问服务器B,即访问1.1.1.1:80, 按端口转发规则,路由器会将这个来自于内网接口的流量再次转发回内网服务器B,形成了一个180度的急弯——发卡弯,这也就是Haripin NAT的名字由来,十分形象。

  如果不做设置,服务器A通过访问1.1.1.1:80 是无法正常访问服务器B的。原因是,hairpin会影响Tcp连接建立的握手过程。

  1. A发送握手请求给入口路由器,路由器修改目的ip为192.68.0.2 ,发送到服务器B。

  2.B收到握手请求后,回复握手确认应答给这个握手请求的源IP地址,此处是A的地址192.168.0.1

  3.因为A,B同一网络,握手确认会直接到达A。

  4.A发现这个握手确认回复的源ip(192.168.0.2)并不是我期望与之建立连接的握手请求目的地址(1.1.1.1),A并不认识B,只认识路由器,导致TCP连接无法建立。

  解决以上问题的关键,就是让握手确认应当同样经过路由器,发送给A。因此,需要在之前将握手请求转发给B时,同时修改源ip地址为(1.1.1.1),如此,B服务器作出确认回复时,自然也会发送给1.1.1.1。

  但是这个源地址转化(SNAT)的过程,实际上只对于来自内网的流量是有必要的。对于外网流量,其源IP本身就处于网络外部,必然会经过再次经过路由器返回。

  于是联系管路由器的小明,请他不要偷懒,规则配置的细致一点,不要做无差别的源地址转换。即

  1.对内网接口流量进行源地址和目标地址转换2.对外网流量只进行目标地址转化。

  重新测试。 终于输出实际了客户PC实际ip地址0.0.0.0

    

  OK,一波三折,跌宕起伏,写到这里~


http://www.ppmy.cn/news/1507368.html

相关文章

nlohmann::json使用中文字符闪退,使用try-catch得到invalid UTF-8

nlohmann::json的字符串需要的编码是UTF-8,我使用wmi得到的信息字符串中的字符编码与其不相符,从而出现Exception。 参考文章链接: github中大佬的解决方法: nlohmann::json评论区 对于我使用的字符wchar_和函数WideCharToMultiBy…

C++设计模式(代理模式)

1. 电话虫 在海贼中,有一种神奇的通信工具叫做电话虫(Den Den Mushi),外形如蜗牛,身上带有斑点或条纹或通体纯色,壳顶上有对讲机或按键,不接通时会睡觉,接通时会惊醒,并发…

LVS 调度器 nat和DR模式

lvs-nat 修改请求报文的目标IP,多目标IP的DNAT 配置网络 LVS主机 注意网卡的顺序 (nat和主机模式) [rootlvs ~]# cat /etc/NetworkManager/system-connections/ens160.nmconnection [connection] idens160 typeethernet interface-nameens160 ​ [ip…

Java封装原生ES

文章目录 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)🌟 亮点功能📦 spring cloud模块概览常用工具 🔗 更多信息1.spring-data-es操作ES1.引入依赖2.application.yml配置uris3…

【Story】编译器的基础概念与类型分类

目录 编译器详解1. 编译器的工作流程1.1 词法分析(Lexical Analysis)词法分析的例子 1.2 语法分析(Syntax Analysis)语法分析的例子 1.3 语义分析(Semantic Analysis)语义分析的例子 1.4 中间代码生成&…

漏洞复现-Atlassian Confluence Data Center 与 Server 存在权限绕过漏洞 (CVE-2023-22518)

1.漏洞描述 Atlassian Confluence Server是澳大利亚Atlassian公司的一套具有企业知识管理功能,并支持用于构建企业WiKi的协同软件的服务器版本。 Atlassian Confluence Data Center 和 Confluence Server存在安全漏洞,该漏洞源于授权管理不当。 2.影响…

vscode 快速生成vue 格式

1.用快捷Ctrl Shift P唤出控制台 输入“Snippets”并选择 Snippets: Configure User Snippets 2.输入vue,选中vue.json vs code自动生成vue.json文件 3.在 vue.json 中添加模板 {"Print to console": {"prefix": "vue2","b…

大数据-69 Kafka 高级特性 物理存储 实机查看分析 日志存储一篇详解

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

SQL Zoo 5.SUM and COUNT

以下题目均来自sql zoo 1.Show the total population of the world.(显示世界总人口) select sum(population) from world 2.List all the continents - just once each.(列出所有的大洲——每个只列出一个) select distinct(continent) from world…

前端面试题——RN篇

文章目录 前言1.RN和React有什么区别2.RN核心组件3.scrollView和FlatList区别scrollViewList item 4.RN应用导航5.虚拟dom作用是什么目的是什么工作原理 6.RN相对于原生的ios和Android有哪些优/劣势优势劣势 7.RN生命周期8.li列表中有3条数据,删除第二条会发生什么9…

ES6模块化简明笔记

1、什么是模块化 详见看上一篇笔记CommonJs模块化简明笔记 2、为什么需要模块化 详见看上一篇笔记CommonJs模块化简明笔记 3、导入和导出的概念 详见看上一篇笔记CommonJs模块化简明笔记 4、模块导出(暴露) 4.1 导出(暴露)方式1&…

基于粒子群优化GRU神经网络的多输入回归分析,基于粒子群优化GRU网络多输入回归分析,基于粒子群优化GRU神经网络

目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 gru的原理 粒子群算法原理 粒子群优化GRU神经网络的多输入回归分析 结果分析 展望 参考论文 背影 传统的方法回归分析容易陷入局部最优准确率低,为提高精度,本文用粒子群优化GRU神经网络的多输入回归分析 摘要 LSTM原理,…

攻防世界-web-ctf-upload

题目场景 查看源码 毫无有效的数据 官方WriteUp 本题需要利用文件上传漏洞点,通过绕过服务器的安全防护,达到getshell的目的 本题的主要考点为利用fastcgi的.user.ini特性进行任意命令执行 这里需要绕过的点如下 检查文件内容是否有php字符串 检查…

Less 教程:从入门到精通

Less 教程:从入门到精通 1. 引言 Less 是一种流行的动态样式表语言,它扩展了 CSS 的功能,使其更加强大和灵活。通过本教程,我们将深入探讨 Less 的基本概念、特性以及如何在项目中实际应用它。 2. Less 的基本概念 2.1 变量 …

vue3父组件向子组件传参的具体写法

在Vue 3中,父组件向子组件传参(也称作传递props)是一种非常基本的通信方式。下面我将详细解释如何在Vue 3中实现这一功能。 1. 定义子组件并接收props 首先,你需要在子组件中定义你想要接收的props。这通过在组件的props选项中完…

通过java.netHttpURLConnection类实现java发送http请求

import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public static String postForBody(String param) { try { URL url new URL(“https://usapp-open.ulifecam.com”)…

axios中的baseURL与跨域问题

axios中的baseURL 01. baseURL与跨域02. axios的baseurl为相对地址03. axios的baseURL是使用绝对路径还是相对路径04. API 请求跨域05. 生产环境代理问题我理解的baseURL 01. baseURL与跨域 三种模式配置: 开发环境 .env.development测试环境 .env.production生产…

游戏在抖音只有一个答案,都选C

经过2023年至2024年间多个案例的曝光,游戏开发商与硬核联盟之间的分歧已不再是秘密。而与此同时,抖音游戏发行的影响力也日益凸显,开始被市场所看重。 抖音能否成为取代硬核联盟的下一个渠道窗口? 从产品角度分析,抖…

Python教程:Python线程池与进程池入门

目录 1. 线程与进程的基本概念 1.1 线程 1.2 进程 1.3线程池与进程池的选择 2. Python 中的线程池与进程池 2.1 线程池 2.2 进程池 3. 实战示例 3.1 使用线程池 3.2 使用进程池 4.max_workers 详解 4.1什么是 max_workers 4.2如何设置 max_workers 4.2.1 根据任务…

自动化专业英语

前言 电子信息、电气工程、自动化专业英语词汇汇总,不定期更新 常用 Asynchronous:异步synchronous:同步notification:通知blade:平面shaft:轴magnetic:磁场的bearing:轴承valve&…