前言

在日常开发中,我们经常需要获取请求的客户端ip,对请求ip做白名单配置,或者ip维度的接口限流。服务端获取客户端ip地址的常用方法有两种:

  • Remote Address
  • X-Forwarded-for

java中,获取客户端ip地址最简单的方式就是 request.getRemoteAddr(),即第一种方式。这种方式可以直接获取到连接服务器的客户端ip(在中间没有代理的情况下,的确是最简单有效的方式)。但是当今的互联网web应用很少会将应用服务器直接对外服务,有的甚至可能有多层代理。在有反向代理的情况下 直接使用 request.getRemoteAddr(),获取到的ip地址是Nginx(或其他的代理服务器的ip地址),而不是客户端的ip地址。

HTTP协议是基于TCP协议的,由于request.getRemoteAddr()获取到的是TCP层直连的客户端ip,对于web应用服务器来说直接连接它的客户端实际上是Nginx,也就是说TCP层是拿不到真实的客户端的ip的。为了解决上面的问题,很多 HTTP代理 会在HTTP协议头中添加 X-Forwarded-for头,用于追踪请求来源最真实的ip地址。

何为XFF漏洞

下面列举了java种获取客户端ip的写法,其他语言写法思想都是一样的,都是先获取请求头中的X-Forwarded-for,如果X-Forwarded-for值没有的话,再去取Remote Address值。这种写法本身没啥问题,但是需要Nginx配置正确。

public static String getClientIP(HttpServletRequest request) {String forwardedIp = request.getHeader("X-Forwarded-For");String ip;if (!StringUtils.isEmpty(forwardedIp)) {String[] forwardedIpSp = forwardedIp.split(",");ip = forwardedIpSp[0];} else {ip = request.getHeader("X-Real-IP");}if (StringUtils.isEmpty(ip)) {ip = request.getRemoteAddr();}return ip;}

看过Nginx多级代理,如何获取客户端真实IP的同学都知道X-Forwarded-for是采用后置添加的方式来记录多级代理的ip地址,ip地址用逗号隔开,所以在获取客户端ip的时候,直接取最左边就ok了,但是X-Forworded-for是请求头中的拓展字段,在实际请求中是否可以伪造呢?

首先,我们知道 Remote Address 是无法伪造的,因为它是直接从TCP连接信息中获取到的,而建立TCP连接需要三次握手。如果伪造了源ip,便无法建立TCP连接,更不会有后面的HTTP请求。但是,X-Forwarded-For头是可以伪造的。一般的客户端(如:浏览器)在发送请求的时候是没有X-Forwarded-For头的,当请求到达第一个代理服务器的时候,代理服务器会加上X-Forwarded-For请求头,并将值设为客户端的ip地址(也就是最左边的第一个值),后面如果还有多个代理,则会依次将ip追加到X-Forwarded-For都的最右边,最终当请求到达web应用服务器时,应用通过获取X-Forwarded-For头取左边第一个ip即为客户端真实ip但是如果客户端在发送请求时,就在请求头上带上一个伪造的X-Forwarded-For,由于后续的每层代理只会追加而不会覆盖ip,那么最终到达应用服务器时,获取的最左边第一个ip地址将会是客户端伪造的ip。也就是上面的java代码中getClientIp()方法获取的ip地址很有可能是伪造的ip地址。该漏洞如果没有加以限制,则会造成巨大的安全隐患,可以利用工具Postman或burpsuite进行XFF攻击。

如何避免XFF漏洞

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

proxy_set_header X-Forwarded-For $remote_addr;

这里使用$remote_addr替代上面的$proxy_add_x_forwarded_for。$proxy_add_x_forwarded_for会在原有X-Forwarded-For上追加IP,这就相当于给了伪造X-Forwarded-For的机会。而$remote_addr是获取的是直接TCP连接的客户端IP(类似于Java中request.getRemoteAddr()),这个是无法伪造的,即使客户端伪造也会被覆盖掉,而不是追加。需要注意的是,如果有多层代理,那么只要在直接对外访问的Nginx上配置X-Forwarded-For为$remote_addr,内部层的Nginx还是要配置为$proxy_add_x_forwarded_for,不然内部层的Nginx又会覆盖掉客户端的真实IP。

5年经验,没听过XFF漏洞相关推荐

  1. 升级过log4j,却还没搞懂log4j漏洞的本质?

    摘要:log4j远程代码漏洞问题被大范围曝光后已经有一段时间了,今天完整讲清JNDI和RMI以及该漏洞的深层原因. 本文分享自华为云社区<升级过log4j,却还没搞懂log4j漏洞的本质?为你完 ...

  2. 大哥你怕是没听过:头上没毛,代码不牢!

    小编从某论坛上看到一个让我半夜笑醒的话题,一个小伙儿问:程序员该理什么发型?想整个背头怕被嫌弃~ 你有头发吗?我的哥儿某骚气十足的程序员哥哥说:程序员应该学会打扮自己.大多数程序员都穿的跟个二赖子似的 ...

  3. 数一数你连听都没听过的古典小说有多少?

    作者:www.gudianxiaoshuo.com 数一数你连名字都没听过的古典小说有多少? 先秦 先秦汉魏晋南北朝诗 屈原全集 汉代诗歌 诗经 词 [全唐五代词] 宋词三百首 晏几道词全集 欧阳修词 ...

  4. 咬文嚼字的有趣例子_十个你可能没听过的成语,藏着十个有趣的故事

    原标题:十个你可能没听过的成语,藏着十个有趣的故事 成语,是我国传统文化百花园中的一朵奇葩,可以说每一个成语都是一个故事.今天我们要说的成语,它们虽然可能不为人知,但个个有着丰富的情节与故事- cǎn ...

  5. JAVA梅森旋转随机算法,你没听过的梅森旋转算法

    (标准开头) 如果单独提梅森旋转算法可能大家都很陌生,但如果说到C++11的random可能大家就都熟悉多了.事实上,C++,python等多种计算机语言的随机数都是通过梅森旋转算法产生的.(也有一个 ...

  6. 他,生物系毕业,刚入职连Java都没听过,却在马云的要求下,三周写出淘宝网雏形...

    生物信息学习的正确姿势 NGS系列文章包括NGS基础.高颜值在线绘图和分析.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流 ...

  7. 你居然用计算机玩csgo,新潮流,用CSGO来测试电脑性能!最后一个你一定没听过...

    原标题:新潮流,用CSGO来测试电脑性能!最后一个你一定没听过 很多的玩家们都很在意自己的电脑性能到达什么样的水平,大家也会钟情于用很多的跑分软件来测试自己的电脑性能与数值.但是今天小编给各位带来如何 ...

  8. 他,生物系毕业,刚入职连 Java 都没听过,却在马云的要求下,三周写出淘宝网雏形......

    公众号关注 "GitTick" 设为 "星标",带你了解技术圈内新鲜事! 今天为大家介绍一位阿里巴巴早期的程序员--蔡景现. 在阿里内部,蔡景现可是一位传奇人物 ...

  9. 你可能没听过“智能制造”,但它肯定改变了你的生活

    "智能制造"这词儿有点新鲜,一听感觉和咱们没什么关系嘛,平时也很少接触到相关的行业.可能学工科的同学.从事工业生产的朋友们会熟悉一些,那为啥说它改变了我们的生活呢?咱们慢慢道来. ...

最新文章

  1. Golang实现简单爬虫框架(4)——队列实现并发任务调度
  2. common_test使用注意事项
  3. 共享马扎的火爆,原来是一场营销!
  4. npm ERR! Please try running this command again as root/Administrator.
  5. centos6.5配置Hadoop环境,运行wordcount例子
  6. linux下的malloc申请的是虚拟还是物理的,关于malloc申请内存
  7. Java发送邮件(QQ邮箱)
  8. CMake macOS安装
  9. 北京国企软件开发公司有哪些?哪家比较好呢
  10. 怎样安装linux中文字体,linux如何安装中文字体库
  11. winform日历控件
  12. 【教程】Tomcat 的catalina.out 日志按照自定义日期格式进行切割
  13. 【PyTorch深度学习项目实战100例】—— 基于UNet实现血管瘤超声图像分割 | 第30例
  14. win10 C盘扩大容量
  15. 趁我们还年轻,就应该奋斗
  16. FileBrowser文件浏览器部署
  17. 微信输入法,终于来了。。。
  18. Parrot OS 4.6渗透测试系统安装与基础环境搭建
  19. [学习笔记-FPGA]Vivado出现信号差分问题
  20. typora免费版,无需破解,安装直接使用

热门文章

  1. SourceTree 添加工作副本,提示不是一个有效的工作副本路径
  2. put词组(put词组搭配初中)
  3. Vue3中自定义ref
  4. python-分割线
  5. Vue中的template标签的使用和在template标签上使用v-for
  6. geoserver修改默认密码
  7. 【饥荒】本地服务器+内网穿透
  8. linux 添加源的方法
  9. 2022 Pycharm 不同版本镜像源添加
  10. 关于未完全Root的Android系统如何彻底ROOT