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

【Java开发】之获取客户端真实 IP 地址

一、应用场景


  • 在投票系统开发中,为了防止刷票,我们需要限制每个 IP 地址只能投票一次;
  • 当网站受到诸如 DDoS(Distributed Denial of Service,分布式拒绝服务攻击)等攻击时,我们需要快速定位攻击者 IP;
  • 在渗透测试过程中,经常会碰到网站有 CDN(Content Distribution Network,内容交付网络),这时我们需要绕过 CDN 查找真实 IP;

二、获取客户端的 IP 地址


服务端获取客户端请求IP地址,常见的包括:remote_addr、x-forwarded-for、client-ip 等请求头参数:

  • remote_addr:指的是当前直接请求的客户端IP地址,它存在于tcp请求体中,是http协议传输的时候自动添加,不受请求头header的控制。因此,当客户端与服务器之间不存在任何代理的时候,通过remote_addr获取客户端IP地址是最准确,也是最安全。remote_addr无法伪造
  • x-forwarded-for,即XFF,是很多代理服务器在请求转发时添加上去的。如果客户端和服务器之间存在代理服务器,那么通过remote_addr获取的IP就是代理服务器的地址,并不是客户端真实的IP地址。因此,需要代理服务器(通常是反向代理服务器)将真实客户端的IP地址转发给服务器,转发时客户端的真实IP地址通常就存在于XFF请求头中。
  • client-ip:同XFF,也是代理服务器添加的用于转发客户端请求的真实IP地址,同样保存与请求头中。

在 Java 中,获取客户端 IP 最直接的方式就是使用 request.getRemoteAddr()。这种方式在中间没有代理的情况下,获取连接到服务器的客户端 IP 的最简单有效的方式。

但是目前互联网 Web 应用很少会将应用服务器直接对外提供服务,一般都会有一层 Nginx 做反向代理和负载均衡,有的甚至可能有多层代理。所以,在有反向代理的情况下,直接使用 request.getRemoteAddr() 获取到的IP地址是Nginx所在服务器的IP地址,而不是客户端的 IP。

为了解决上面的问题,很多 HTTP 代理会在 HTTP 协议头中添加 X-Forwarded-For 头,用来追踪请求的来源,X-Forwarded-For 的格式如下:

X-Forwarded-For: client1, proxy1, proxy2

X-Forwarded-For 包含多个 IP 地址,每个值通过逗号+空格分开,最左边(client1)是最原始客户端的IP地址,中间如果有多层代理,每一层代理会将连接它的客户端IP追加在 X-Forwarded-For 右边。

下面就是一种常用的获取客户端真实IP的方法:

public static String getRealIP(HttpServletRequest request) {String ip = request.getHeader("X-Forwarded-For");if (ip != null) {ip = ip.contains(",") ? ip.split(",")[0] : ip;} else {if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}}return ip;
}

注意,要让 Nginx 支持 X-Forwarded-For 头,需要配置:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

$proxy_add_x_forwarded_for 会将和 Nginx 直接连接的客户端 IP 追加在请求原有 X-Forwarded-Fo r值的右边。

三、IP 伪造及解决方案


1、客户端可以伪造 X-Forwarded-For

一般的客户端(例如浏览器)发送HTTP请求是没有 X-Forwarded-For 头的,当请求到达第一个代理服务器时,代理服务器会加上 X-Forwarded-For 请求头,并将值设为客户端的IP地址(也就是最左边第一个值),后面如果还有多个代理,会依次将IP追加到 X-Forwarded-For 头最右边,最终请求到达Web应用服务器,应用通过获取 X-Forwarded-For 头取左边第一个IP即为客户端真实IP。

但是如果客户端在发起请求时,请求头上带上一个伪造的 X-Forwarded-For,由于后续每层代理只会追加而不会覆盖,那么最终到达应用服务器时,获取的左边第一个IP地址将会是客户端伪造的 IP。

2、解决方案:配置 Nginx 反向代理

在直接对外的Nginx反向代理服务器上配置:

proxy_set_header X-Forwarded-For $remote_addr;

如果有多层Nginx代理,内层的Nginx配置:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

在最外层 Nginx(即直接对外提供服务的Nginx)使用 $remote_addrb代替上面的 $proxy_add_x_forwarded_for,可以防止伪造 X-Forwarded-For。$proxy_add_x_forwarded_forb会在原有 X-Forwarded-For 上追加IP,这就相当于给了伪造 X-Forwarded-Fo r的机会。而 $remote_addr 是获取的是直接 TCP 连接的客户端 IP,这个是无法伪造的,即使客户端伪造也会被覆盖掉,而不是追加。

需要注意的是:如果有多层代理,只在直接对外访问的 Nginx 上配置 X-Forwarded-For 为 $remote_addr,内层的 Nginx 还是要配置为 $proxy_add_x_forwarded_for,不然内层的 Nginx 又会覆盖掉客户端的真实IP。

完成以上配置后,获取X-Forwarded-For最左边的IP地址即为真实的客户端地址,且客户端也无法伪造。

相关文章:

【Java开发】之获取客户端真实 IP 地址

一、应用场景 在投票系统开发中,为了防止刷票,我们需要限制每个 IP 地址只能投票一次;当网站受到诸如 DDoS(Distributed Denial of Service,分布式拒绝服务攻击)等攻击时,我们需要快速定位攻击者…...

Linux RPM包安装、卸载和升级

我们以安装 apache 程序为例。因为后续章节还会介绍使用源码包的方式安装 apache 程序,读者可以直观地感受到源码包和 RPM 包的区别。 RPM包默认安装路径 通常情况下,RPM 包采用系统默认的安装路径,所有安装文件会按照类别分散安装到表 1 所…...

ROS 多级tf坐标转换

题目 现有一移动机器人,该机器人的基坐标系为“base_link”,机器人包含3个子坐标系分别为“joint1”,“joint2”,“joint3”。 要求:利用多坐标转换,实现joint1下的坐标向joint2下的坐标转换,…...

ceph rados对象存储索引残留问题排查与处理

问题现象 对象存储存储桶无法删除,检查发现生命周期过期后存储桶中有文件残留,未完全删除,但实际访问文件时为404,通过s3cmd无法删除对象,且无报错。 问题定位 检查bucket当前状态,发现桶内有大量object…...

十年测试工龄,揭露软件测试痛点以及分析

做软件测试的同学们,你在平时的测试工作中有哪些困惑或困扰呢?你可以自行简单思考一下。下面我梳理一下,大家可以看看自己是不是也有如此的感受。 从测试整体角度分析: 第一个痛点是入门容易深入难。 很多人认为软件测试也就那么…...

【星海出品】flask(三) 组件

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架 wsgiref 因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。 这个…...

关于卷积神经网络的池化层(pooling)

了解池化层 池化层又称“下采样层”或“子采样层”,池化层可以大大降低特征的维度,减少计算量,同时可以避免过拟合问题。 顾名思义,最大池化层就是从输入的矩阵中某一范围内,选择最大的元素进行保留;平均池…...

GNU链接脚本详解

0. 前言 每一个链接都是由链接脚本控制的,链接脚本是用链接命令语言编写的脚本。链接都会用到一个链接脚本,如果你没有指定自己的脚本,就会使用默认的链接脚本。可以用 "--verbose" 命令行选项显示默认的连接脚本。指定命令行参数…...

酷柚易汛ERP-账户管理操作指南

1、应用场景 对账户进行管理,可设置账户当前余额、期初余额和设置是否为默认账户。 2、主要操作 2.1 新增支付账户 打开【资料】-【账款管理】,点击【新增】添加账户类别,输入相关信息并保存,账户编号和名称为必录项。&#x…...

函数的连续性

函数在某一点极限存在,不一定连续 函数的左极限 函数的右极限 函数在某点连续需要满足三个条件 1、左右极限存在 2、左右极限相等 3、函数在该点的极限值等于在该点的函数值 满足1、2两个条件函数在该点极限存在。...

Pandas groupby方法中的group_keys属性

pandas版本1.5.3中groupby方法,当设置group_keysTrue时,会以groupby的字段为第一级索引,如下述代码中time_id作为第一级索引,同时保留了原dataframe(df)中的索引作为第二级索引。 >>> df.groupby…...

win 命令替代鼠标的操作

操作方式都是在 winR 输入框输入或者终端输入 1、快速打开 控制面板 运行control 2、快速打开 电源选项 运行powercfg.cpl 3、快速打开 网络连接 运行ncpa.cpl 4、快速打开 程序和功能 运行appwiz.cpl 5、快速打开 Windows Defender防火墙 运行Firewall.cpl 6、快速打开 鼠标 …...

Shopee活动取消规则是什么?shopee官方促销活动怎么取消?

作为一家知名的电商平台,shopee官方对于消费者取消促销活动的请求给予了相应的规定和处理流程。 shopee活动取消规则是什么? 首先,消费者应该明确了解虾皮的促销活动取消规则。根据虾皮的官方规定,消费者在参与促销活动之前&…...

安卓常见设计模式2------构建者模式(Kotlin版)

1. W1 是什么,什么是构建者模式? 构建者模式(Builder Pattern)是一种创建复杂对象的设计模式。它通过使用链式调用的方式,逐步构建对象,使得代码更易读、可维护,并且可以处理许多可选参数的情况…...

redis主从复制+哨兵

1.主从复制 redis配置文件redis.conf master机器:IP 192.168.1.5 ,端口 6379 设置配置参数 daemonize yes #bind 127.0.0.1 -::1 protected-mode no port 6379 dbfilename "dump.rdb" dir "/root/redis/my_redis_conf/dumpdir" l…...

html动态爱心超文本标记代码,丝滑流畅有特效,附源码

没想到现在看个剧&#xff08;点燃我&#xff0c;温暖你&#xff09;要的同款居然是代码&#xff0c;李峋 这盛世如你所愿啊&#xff01;李峋的同款爱心代码来啦&#xff0c;拿走试试吧&#xff5e; <!DOCTYPE html> <html><head><title></title&g…...

力扣:162. 寻找峰值(Python3)

题目&#xff1a; 峰值元素是指其值严格大于左右相邻值的元素。 给你一个整数数组 nums&#xff0c;找到峰值元素并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回 任何一个峰值 所在位置即可。 你可以假设 nums[-1] nums[n] -∞ 。 你必须实现时…...

【Python】20大报告生成词云

这个我其实写过一篇类似的博客&#xff0c;但是那个的文件对象是.csv&#xff0c;对应到.docx文件的话&#xff0c;就不太适用了。如下&#xff1a; Python生成词云-CSDN博客 代码&#xff1a; import jieba import os import wordcloud import numpy as np from PIL import…...

目标检测YOLO实战应用案例100讲-基于无人机的轻量化目标检测系统设计

目录 前言 国内外研究现状 国外研究现状 国内研究现状...

ansible-第二天

ansible 第二天 以上学习了ping、command、shell、script模块&#xff0c;但一般不建议使用以上三个&#xff0c;因为这三个模块没有幂等性。举例如下&#xff1a; [rootcontrol ansible]# ansible test -a "mkdir /tmp/1234"[WARNING]: Consider using the file …...

高效脚本编写:用Codex告别重复造轮子

技术文章大纲&#xff1a;告别重复造轮子——Codex写脚本的高效实践引言&#xff1a;自动化脚本的意义与Codex的潜力重复性工作的痛点与脚本的价值OpenAI Codex在代码生成领域的突破性能力本文目标&#xff1a;如何利用Codex快速生成实用脚本Codex基础&#xff1a;理解其工作原…...

漫画迷的离线宝库:一键构建你的私人漫画图书馆

漫画迷的离线宝库&#xff1a;一键构建你的私人漫画图书馆 【免费下载链接】comics-downloader tool to download comics and manga in pdf/epub/cbr/cbz from a website 项目地址: https://gitcode.com/gh_mirrors/co/comics-downloader 还在为网络不稳定无法畅快阅读漫…...

如何通过游戏化编程轻松掌握Python与JavaScript:CodeCombat终极指南

如何通过游戏化编程轻松掌握Python与JavaScript&#xff1a;CodeCombat终极指南 【免费下载链接】codecombat Game for learning how to code. 项目地址: https://gitcode.com/gh_mirrors/co/codecombat 想要让编程学习变得像玩游戏一样有趣吗&#xff1f;CodeCombat正是…...

数据结构复习(第五章):树与二叉树

树与二叉树&#xff1a;从层次关系到递归结构的一整套理解 这一章讨论的主题是树与二叉树。和前面的线性表、串相比&#xff0c;这里的结构不再是单一的前后次序&#xff0c;而是开始进入层次化组织的世界。一个结点之下可以分出多个后继&#xff0c;不同分支之间彼此并列&…...

4月18日腾讯云「龙虾公开课」落地合肥!免费线下AI实战课,还有限定周边等你拿

合肥线下&#xff1a;免费AI实战课的吸引力4月18日&#xff0c;腾讯云开发者社区「龙虾公开课」将在合肥高新区中安创谷科技园二期H1栋国际会客厅举办。此次活动提供免费的线下AI Agent实战课&#xff0c;即使是零基础的参与者也能参与。课程涵盖1对1装机指导、现场实操工坊&am…...

OLED字库的构建与移植:从点阵数据到嵌入式显示

1. OLED字库的基础概念与工作原理 第一次接触OLED字库时&#xff0c;我也被那一串串十六进制数字搞得头晕眼花。直到后来才发现&#xff0c;这些看似复杂的数据背后&#xff0c;其实是一套非常直观的图形表达方式。OLED字库本质上就是字符的图形化表示&#xff0c;每个字符都被…...

STM32点蜂鸣器

这是一个峰鸣器&#xff0c;GND接stm32的GND&#xff0c;VCC接3.3V&#xff0c;i/o接你设置的引脚代码如下void Bear_int(){GPIO_InitTypeDef Bear_initstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);Bear_initstruct.GPIO_PinGPIO_Pin_3;Bear_initstruct.GPIO…...

15kw充电桩模块设计,源代码,原理图,pcb 1. 某达15kw充电桩模块,提供AD设计的电...

15kw充电桩模块设计&#xff0c;源代码&#xff0c;原理图&#xff0c;pcb 1. 某达15kw充电桩模块&#xff0c;提供AD设计的电路图和pcb&#xff0c;源代码&#xff0c;并包括三相PFC程序参数变量的计算书。 2 .某默生15kw充电桩模块&#xff0c;PFCDCDC双DSP控制&#xff0c;原…...

从玩具小车到智能台灯:用STM32和光敏电阻DIY一个自动追光/避光的小项目

从玩具小车到智能台灯&#xff1a;用STM32和光敏电阻DIY自动追光系统 周末整理储物间时&#xff0c;翻出儿子淘汰的玩具小车底盘&#xff0c;看着那些还能转动的轮子和电机&#xff0c;突然想到可以用它做个会"追太阳"的智能小车。这个想法让我兴奋不已——用最基础的…...

隆力奇羊奶商城小程序多少钱一套

隆力奇羊奶商城小程序价格隆力奇羊奶商城小程序的具体价格因功能需求、开发方式和服务商不同而有所差异。以下是一些常见的价格范围和影响因素&#xff1a;定制开发价格基础版小程序&#xff08;展示型&#xff09;&#xff1a;约1万-3万元&#xff0c;包含产品展示、购物车、支…...