前言

在日常开发中,我们经常需要获取请求的客户端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. 前端解决跨域问题的8种方案(最新最全)
  2. Kali Linux Web 渗透测试— 第十二课-websploit
  3. IdentityServer4 知多少
  4. 微型计算机重点,微型计算机理期末重点.doc
  5. python 操作微信定时发信息
  6. 字典树模板+洛谷P2580 于是他错误的点名开始了
  7. 前端开发面试题收集(html部分)
  8. 验证码一(验证码生成)
  9. SAP License:糟糕的用户比任何系统问题都要危险
  10. 势高,则围广:TiDB 的架构演进哲学
  11. 分享30个网页设计色彩搭配的优秀案例
  12. 修改linux kernel参数 semopm
  13. php curl使用
  14. Visual Studio 2015 专业版安装方法
  15. 案例分析 | 贝壳找房:自我颠覆的整合式创新引领产业数字化
  16. MySQL数据库插入中文时出现Incorrect string value: '\xE6\x97\xB7\xE5\x85\xA8' for column 'sz_name' at row 1...
  17. day04 java学习
  18. HILDON手册(转载自CSDN)
  19. php网线入侵,普通网线能poe供电吗
  20. 灵界的科学丨六、星际通信新科技──寻找外星人

热门文章

  1. 【经典算法题】单词搜索
  2. python进程和线程是什么_python的进程与线程
  3. pytorch稀疏矩阵
  4. 修改TTF文件或者otf文件或者woff文件内的字体名称
  5. JImmy的文档: 搭建集群版openshift origin-3.9
  6. Http中你必须知道那点事
  7. ones' complement 和 two's complement
  8. CF817D Imbalanced Array(单调栈)
  9. Flink SQL空闲状态保留时间(idle state retention time)实现原理
  10. c语言程序如何调用标准库函数,如何调用C标准库的exit函数详解