【全方位解析】如何获取客户端/服务端真实 IP

一、应用场景

1.比如在投票系统开发中,为了防止刷票,我们需要限制每个 IP 地址只能投票一次

2.当网站受到诸如 DDoS(Distributed Denial of Service,分布式拒绝服务攻击)等攻击时,我们需要快速定位攻击者 IP

3.在渗透测试过程中,经常会碰到网站有 CDN(Content Distribution Network,内容交付网络),这时我们需要绕过 CDN 查找真实 IP

二、解决方案

服务端(CDN)

验证是否具有 CDN

1、使用超级 Ping 网站,查看对应 IP 地址是否唯一,如果不唯一多半是使用了 CDN ,诸如:

2、使用 nslookup 进行检测,如果返回域名解析对应多个 IP 地址多半是使用了 CDN

检测方式,直接命令行输入nslookup,随后输入对应域名

有 CDN 如下

无 CDN 如下

方法1:查询历史 DNS 记录

查看 IP 与 域名绑定的历史记录,可能会存在使用 CDN 前的记录,相关查询网站:

DNS查询:https://dnsdb.io/zh-cn/

在线域名信息查询:http://toolbar.netcraft.com/site_report?url=

DNS、IP等查询:http://viewdns.info/

CDN查询 IP:https://tools.ipip.net/cdn.php

方法2:查询子域名

毕竟 CDN 还是不便宜的,所以很多站长可能只会对主站或者流量大的子站点做了 CDN,而很多小站子站点又跟主站在同一台服务器或者同一个C段内,此时就可以通过查询子域名对应的 IP 来辅助查找网站的真实IP。

dnsdb 查询https://www.dnsdb.io/)

只需输入baidu.com type:A就能收集百度的子域名和ip

方法3:网络空间搜索引擎

网络空间搜索引擎是为了解决个人每次进行渗透测试是都要进行的信息收集过程,通过全网扫描的方式,将基础数据进行格式化存储,供安全人员按需搜索使用,提升了安全人员的工作效率。

常用的网络空间搜索引擎:fofashodan、zoomeye、censys

每种搜索引擎都有对应的搜索语法,例如 fofa ,只需输入:title:"网站的title关键字"或者body:"网站的body特征"就可以找出 fofa 收录的有这些关键字的 ip 域名,获取能获取网站的真实 ip,其他搜索引擎语法请看推荐阅读

方法4:利用 SSL 证书寻找真实原始 IP

假如你在xyz123boot.com上托管了一个服务,原始服务器IP是136.23.63.44。 而CloudFlare则会为你提供DDoS保护,Web应用程序防火墙和其他一些安全服务,以保护你的服务免受攻击。为此,你的Web服务器就必须支持SSL并具有证书,此时CloudFlare与你的服务器之间的通信,就像你和CloudFlare之间的通信一样,会被加密(即没有灵活的SSL存在)。这看起来很安全,但问题是,当你在端口443 https://136.23.63.44:443 上直接连接到IP时,SSL证书就会被暴露。

此时,如果攻击者扫描0.0.0.0/0,即整个互联网,他们就可以在端口443上获取在xyz123boot.com上的有效证书,进而获取提供给你的Web服务器IP。

Censys 工具为例,我们仅仅需要做的就是把上面用文字描述的搜索词翻译成实际的搜索查询参数,如下

  • xyz123boot.com证书的搜索查询参数为:parsed.names:xyz123boot.com

  • 只显示有效证书的查询参数为:tags.raw:trusted

  • 组合后的搜索参数为:parsed.names: xyz123boot.com and tags.raw: trusted

但是缺点就是很多非法网站根本没有 SSL 证书,无法获取 IP。

方法5:使用国外主机解析域名

国内很多 CDN 厂商因为各种原因只做了国内的线路,而针对国外的线路可能几乎没有,此时我们使用国外的主机直接访问可能就能获取到真实IP。

方法6:网站漏洞查找

1)目标敏感文件泄露,例如:phpinfo之类的探针、GitHub信息泄露等。

2)XSS盲打,命令执行反弹shell,SSRF等。

3)无论是用社工还是其他手段,拿到了目标网站管理员在CDN的账号,从而在从CDN的配置中找到网站的真实IP。

方法7:网站邮件订阅查找

RSS邮件订阅,很多网站都自带 sendmail,会发邮件给我们,此时查看邮件源码里面就会包含服务器的真实 IP 了。

方法8:用 Zmap 扫全网

需要找 xiaix.me 网站的真实 IP,我们首先从 apnic 获取 IP 段,然后使用 Zmap 的 banner-grab 扫描出来 80 端口开放的主机进行 banner 抓取,最后在 http-req 中的 Host 写 xiaix.me

方法9:F5 LTM解码法

当服务器使用F5 LTM做负载均衡时,通过对set-cookie关键字的解码真实ip也可被获取,例如:Set-Cookie: BIGipServerpool_8.29_8030=487098378.24095.0000,先把第一小节的十进制数即487098378取出来,然后将其转为十六进制数1d08880a,接着从后至前,以此取四位数出来,也就是0a.88.08.1d,最后依次把他们转为十进制数10.136.8.29,也就是最后的真实ip。

更多方法请看推荐阅读

客户端

获取 IP 方式

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

介绍如何获取客户端 IP 之前我们需要了解 Nginx 负载均衡 方式,从协议上分为如下:

  • 七层复杂均衡(HTTP/HTTPS协议),工作在第七层"应用层"。

  • 四层负载均衡(TCP/UDP协议),工作在"网络层"和"传输层"。

七层复杂均衡

配置 Nginx (支持X-Forwarded-For)
bash 复制代码
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

$proxy_add_x_forwarded_for会将和Nginx直接连接的客户端IP追加在请求原有X-Forwarded-For值的右边。形式如下:

bash 复制代码
X-Forwarded-For: client1, proxy1, proxy2

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

获取 IP 代码段
java 复制代码
public String getClientIp(HttpServletRequest request) {
String xff = request.getHeader("X-Forwarded-For");
if (xff == null) {
return request.getRemoteAddr();
} else {
return xff.contains(",") ? xff.split(",")[0] : xff;
}
}
缺点:客户端可以伪造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。也就是上面的Java代码中getClientIp()方法获取的IP地址很有可能是伪造的IP地址

解决方案 :配置 Nginx 反向代理(必须是直接对外的 Nginx)
bash 复制代码
proxy_set_header X-Forwarded-For $remote_addr;

$proxy_add_x_forwarded_for会在原有X-Forwarded-For上追加IP,这就相当于给了伪造X-Forwarded-For的机会。

而$remote_addr是获取的是直接TCP连接的客户端IP(类似于Java中的request.getRemoteAddr()),这个是无法伪造 的,即使客户端伪造也会被覆盖掉,而不是追加。

需要注意的是,如果有多层代理 ,那么只要在直接对外访问的Nginx上配置X-Forwarded-For为 r e m o t e a d d r ∗ ∗ , ∗ ∗ 内部层的 N g i n x 还是要配置为 remote_addr**,**内部层的Nginx还是要配置为 remoteaddr∗∗,∗∗内部层的Nginx还是要配置为proxy_add_x_forwarded_for,不然内部层的Nginx又会覆盖掉客户端的真实IP。

四层负载均衡

四层负载均衡基于 TCP/UDP协议 ,X-Forwarded-For的方式获取客户端 IP 方式将会失效,此时可以配置 Nginx 开启 透传功能

bash 复制代码
stream {
	server {
		# 开启透传
        proxy_protocol on ;
    }
}

添加这个配置后Nginx建立TCP连接时会主动发送一段报文,会包含客户端真实Ip

携带客户端IPv4地址的Proxy Protocol v2二进制头格式如下所示:

携带客户端IPv6地址的Proxy Protocol v2二进制头格式如下所示:

补充

代理 IP

  • 透明代理

其实即便使用了透明代理IP,还是会发送真实IP。这种一般是用来突破网络浏览限制,比如说一般用户不能随意访问的教育网,使用代理IP就可以突破的。

  • 匿名代理(普通匿名代理和高匿名代理)

普通代理IP是否能查到真实IP。普通代理IP相比于透明代理IP会安全很多,有的服务器是无法识别真实IP的,但这也不是绝对的,还是会有服务器识别到使用了代理IP的。

高匿代理IP的可以模拟真正的客户浏览器访问目标网站,不容易识别出使用了代理IP,会直接认为代理IP就是你用的IP。使用高匿名代理,经过高级加密后,在网络难以查找信息,但是仍可以从现实查找。想要查真实IP,可以直接从代理IP商那里,通过查看服务器日志等方式找出他的真实IP地址。

参考文章

http获取客户端真实ip的原理及利用X-Forwarded-For伪造客户端IP漏洞成因及防范 - lovearpu - 博客园 (cnblogs.com)

11种绕过CDN查找真实IP方法 - STARTURN - 博客园 (cnblogs.com)

如何获取来访者的真实IP (huaweicloud.com)

通过Proxy Protocol获取客户端真实IP(四层监听) (aliyun.com)

解决Nginx代理TCP获取不到客户端真实IP的问题

推荐阅读

渗透测试|玩转网络空间搜索引擎 - FreeBuf网络安全行业门户

技术|互联网扫描器 ZMap 完全手册 (linux.cn)

F5 BIG-IP LTM 负载均衡器 功能介绍 下篇-阿里云开发者社区 (aliyun.com)

Nginx 理解四层/七层负载均衡 - Awecoder - 博客园 (cnblogs.com)

用代理IP后还能追踪到真实IP吗 - 掘金 (juejin.cn)

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
qq_3643717232 分钟前
Vue 内置组件 keep-alive 中 LRU 缓存淘汰策略和实现
前端·vue.js·缓存
y先森1 小时前
CSS3中的弹性布局之侧轴的对齐方式
前端·css·css3
y先森6 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy6 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189117 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿8 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡9 小时前
commitlint校验git提交信息
前端
虾球xz9 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇9 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒9 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript