我是如何找到隐藏在防火墙下的源服务器 IP

我是如何找到隐藏在防火墙下的游戏服务器 IP

起因

闲逛的时候看有个discussion说替换了另一个 Cloudflare IP 地址后,就无法工作的情况

这里插一句介绍下Cloudflare CDN 以及 Anycast Cloudflare CDN 是一个内容分发网络,使用了 Anycast 路由技术,这意味着链接任意一个 Cloudflare CDN 的 IP 地址,都可以正确访问目标网站

一开始我并不相信仅仅换一个 IP 就会导致无法访问。为了弄清原因,我决定完整复原一次连接过程。

/upload/20230731/30bf4f741d8760.png

首先该程序会向 https://mjjpgs.mahjongsoul.com:8443/api/v0/recommend_list?service=tcp-gateway&protocol=tcp&ssl=false 发起链接,获得游戏服务器的具体地址

$ curl 'https://mjjpgs.mahjongsoul.com:8443/api/v0/recommend_list?service=ws-gateway&protocol=ws&ssl=true' | jq

{ "servers": [ "mjjpgs.mahjongsoul.com:9663" ] }

探测

到这里傻眼了,虽然是同个域名,但 Cloudflare CDN 对于端口是有要求的,用 nmap 得出的实验结果是一致的

普通 Cloudflare CDN 默认开启的端口如下

$ nmap -sV -p- -T 5 --min-rate 10000 $(dig @1.1.1.1 www.cloudflare.com +short | tail -n 1)

PORT STATE SERVICE VERSION 80/tcp open http cloudflare 443/tcp open ssl/https cloudflare 2052/tcp open clearvisn? 2053/tcp open ssl/http nginx 2082/tcp open infowave? 2083/tcp open ssl/http nginx 2086/tcp open gnunet? 2087/tcp open ssl/http nginx 2095/tcp open nbx-ser? 2096/tcp open ssl/http nginx 8080/tcp open http-proxy cloudflare 8443/tcp open ssl/https-alt cloudflare 8880/tcp open cddbp-alt?

mjjpgs.mahjongsoul.com 使用的 IP 地址比较特殊,使用 nmap 探测出来的端口全都是 tcpwrapped

$ nmap -sV -p- -T 5 --min-rate 10000 $(dig @1.1.1.1 mjjpgs.mahjongsoul.com +short | tail -n 1) 

PORT STATE SERVICE VERSION 1/tcp open tcpwrapped 2/tcp open tcpwrapped 3/tcp open tcpwrapped 4/tcp open tcpwrapped 5/tcp open tcpwrapped 6/tcp open tcpwrapped 7/tcp open tcpwrapped 8/tcp open tcpwrapped 9/tcp open tcpwrapped 10/tcp open tcpwrapped 11/tcp open tcpwrapped 12/tcp open tcpwrapped 13/tcp open tcpwrapped 14/tcp open tcpwrapped 15/tcp open tcpwrapped 16/tcp open tcpwrapped

说明该类型的 IP 会根据你的请求来源、目标和内容来决定是否开启真正连接,这种特定的 IP只允许特定的特定访问类型通过

胡同

在知道了使用了特定的 IP 地址,现在的目标就改为了:找到另一个允许 mjjpgs.mahjongsoul.com:9663 的 Cloudflare CDN IP

便动手写了个简单的 Websocket/TLS 校验工具,模拟下图所示的 http 请求,具体代码在这

/upload/20230731/d12c2d957d6782.png

程序的逻辑如下:

  1. 解析 IP 地址或者按行解析文件的 IP 地址或 CIDR
  2. 对目标 IP:Port 发起 HTTPS 连接
  3. 连接成功后,发起 HTTP 请求升级为Websockets
  4. 升级成功后(HTTP/1.1 → Websocket),会返回Http code 101 表示切换协议成功

程序的选项如下所示

# 你可以指定 IP 地址,或者输入一个只包含 IP 地址或者 CIDR 域的文件
Usage: go run main.go -ip <IP> -port <Port> -file <FileName> -num <Number> -host <HostName>
  • ip: 指定一个 IP 地址,可以跟 -file 一起使用,但必须至少选择一个
  • port: 指定目标的端口
  • file: 每行是 IP 地址或者 CIDR 域的文件,可以跟 -ip 一起使用,但必须至少选择一个
  • num: 并发数
  • host: 指定需要验证的域名

这里我们准备一份Cloudflare ip range 文件,下载到本地后直接运行

$ curl https://www.cloudflare.com/ips-v4 --output ips.txt
# 指定端口 9663,并发 2000,域名为 mjjpgs.mahjongsoul.com
$ go run main.go -port 9663 -file ips.txt -num 2000 -host mjjpgs.mahjongsoul.com

但结果往往都是不出人所料的,得出的结果也只有 172.65.244.96 这么一个 IP 地址

$ go run main.go -port 9663 -file ./ips.txt -num 2000 -host mjjpgs.mahjongsoul.com
**172.65.244.96
All requests completed.**

放弃

其实到这里其实差不多该放弃了,如果你是 Clouflare 会员用户,可能用过一款叫做 Spectrum | DDoS Protection for Apps | Cloudflare 的产品

Cloudflare Spectrum 是一种反向代理产品,它可以将 Cloudflare 的优势扩展到所有 TCP/UDP 应用程序,在本文里面就是用作游戏加速以及抵御 DDoS 攻击

这里再展开讲讲跟 Cloudflare CDN 的区别,像我们正常使用 Cloudflare CDN 的时候,其实是 Cloudflare 反向代理了请求连接到源服务器

/upload/20230731/9701d500f59e36.png

只是 Cloudflare CDN 主要是针对 HTTP/HTTPS 协议,并且只允许特定的端口(80,443,8443)进行链接

并且 Cloudflare CDN 可以缓存静态内容,而 Spectrum 不会缓存任何内容,只是将流量(TCP or UDP)代理到源服务器,并且 Spectrum 还可以设置特定的 IP 地址作为该服务的唯一的入口

这就导致了普通的 Cloudflare CDN IP 无法进行正确的反向代理(因为设置了只允许特定 IP 进行访问),从而隐藏起了源服务器 IP 地址以及抵御了大规模的 DDos 攻击

整体效果图如下

/upload/20230731/497d93cb6a9833.png

路转

在我百无聊奈一篇又一篇的查阅资料的时候,原来讨论贴的作者的一句话提醒了我

/upload/20230731/cf6030214b1556.png

换了一个 IP 地址后,mjjpgs.mahjongsoul.com:8443 没问题

如果你还记得上面的知识,8443 端口是一个允许被 Cloudflare CDN 代理的端口,这么说明其实我们可以通过一般的 Cloudflare CDN IP 去访问 [mjjpgs.mahjongsoul.com]( http://mjjpgs.mahjongsoul.com) 服务器?

说干就干,直接使用其他的 Cloudflare CDN IP 去访问

$ curl 'https://mjjpgs.mahjongsoul.com:8443/api/v0/recommend_list?service=ws-gateway&protocol=ws&ssl=true' --resolve mjjpgs.mahjongsoul.com:8443:104.25.9.80 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    43  100    43    0     0    161      0 --:--:-- --:--:-- --:--:--   161

{ "servers": [ "mjjpgs.mahjongsoul.com:9663" ] }

结果符合预期,是可以通过正常连接的,那么有没有一种可能:

如果服务器的管理员只是设置好了Specturm,导致正常途径情况下只能通过特定 IP 地址去链接,但是没有限制来源 IP 必须是 Cloudflare IP 呢?

找寻

顺着这个思路,只需要将可能的 IP 进行一次 SSL 证书验证和 Websocket 升级后成功,就是我们要找的游戏源服务器 IP 地址

剩下就是猜他所使用的是哪家公有云了,尝试解析一下首页的 IP 的公有云归属

$ nslookup www.mahjongsoul.com | nali

2023/07/30 21:47:32 文件不存在,尝试从网络获取 ipv4.dat Downloading... 5251 KB / 5252 KB
2023/07/30 21:47:33 已将 ipv4.dat 保存到本地 Server: 127.0.0.53 [局域网 IP] Address: 127.0.0.53 [局域网 IP]#53

Non-authoritative answer: Name: www.mahjongsoul.com Address: 47.245.38.201 [日本 东京阿里云]

那么我们把目标转为阿里云旗下所属的 IP 域,我们可以直接通过 https://ipinfo.io/AS45102 来找到分配给阿里云的所有 IP 地址,接下来只需要找到符合要求的 IP 地址即可

ipinfo.io 下载需要注册,我把具体的 CIDR 地址转换成文本文件并上传在在这了 如果你想自己从 ipinfo.io 下载并导出为文本,可以参考这个转换脚本

接下来,就是验证的时刻了

# 下载 Alicloud ip range
$ curl https://gist.githubusercontent.com/charSLee013/66055696579ceda7066487c4c099cbda/raw/e325a32336f239c8ecf21b74ae450547d76f1683/ali_ips.txt --output ali_ips.txt

开始执行

$ go run main.go -port 9663 -file alicloud_netblocks.txt -num 10000 -host mjjpgs.mahjongsoul.com

139.95.4.55 47.252.21.16 47.89.136.64 All requests completed.

使用 openssl 验证证书检验成果

$ openssl s_client -connect 139.95.4.55:9663 -servername mjusgsbk.mahjongsoul.com < /dev/null 2>/dev/null | openssl x509 -text -noout |grep 'Subject: CN'

Subject: CN = *.mahjongsoul.com

结语

以上就是我找寻隐藏在防火墙后面源 IP 地址的整个过程,一开始觉得都知道开启 Specturm 了,想必防御措施拉满,但没想到千里之堤,溃于蚁穴

一直用于验证网站身份的 SSL 证书,成为了这次寻找中最大的帮手。 ;-)