Clash实现IP秒级切换(含简易源码分析)

群马5513954

免责声明

本文所提供的程序(方法)可能带有攻击性,仅供安全研究与教学之用。文章作者无法鉴别判断读者使用信息及工具的真实用途,若读者将文章中的工具或信息做其他用途,由读者承担全部法律及连带责任,segmentfault和本文作者不承担任何法律及连带责任。

注:此文章适用于对Clash有一定使用经验的读者  不再对基础配置说明

0x00 意外

一直以来都使用酸酸乳自带的负载均衡功能配合Airport实现IP秒切
主要用途是对站点进行渗透测试时路径爆破和扫描端口

2021-08-23-23-23-36.png

直到有一天Airport跑路了
兜兜转转换了一家  发现他们使用Clash作为客户端

2021-08-23-23-27-07.png

为方便使用  我选择了Clash-For-Windows简称CFW
Clash支持跨平台  后文以Clash进行分析(主要是CFW不开源)

2021-08-23-23-27-58.png

拿到机场配置文件导入  简单配置下就能正常使用了

但是却始终没有找到和负载均衡有关的设置

百度一下  找到了负载均衡的配置样例

  # load-balance: The request of the same eTLD+1 will be dial to the same proxy.
  - name: "load-balance"
    type: load-balance
    proxies:
      - ss1
      - ss2
      - vmess1
    url: 'http://www.gstatic.com/generate_204'
    interval: 300

按照样例配置好负载均衡  拿起dirsearch跑一跑  然后就被封了

2021-08-23-23-36-55.png

用VPS起个WEB服务扫描看一看  原来IP根本就没变!

2021-08-23-23-44-18.png

0x01 深入

继续翻文档  最终把目光停留在这个注释上

  # load-balance enables the same eTLD requests on the same proxy

eTLD没接触过  补个课先

Top-level domains (TLDs) ,顶级域名,例如.com、.net、.cn、.tw、.top等。

effective TLDs(eTLDs),有效顶级域名,对于如.com.cn或.github.io这样的域名,仅仅使用.jp或.io的顶级域名是不够细化的,不足以识别 "同一个网站",目前没有统一的标准确定某个顶级域名的可注册等级。这就是为什么创建了一个 "有效顶级域名"(eTLDs)的列表。 (eTLDs列表在publicsuffix.org/list上维护)

举例:给定的URL是https://my-project.github.io,则eTLD是.github.io,eTLD+1是my-project.github.io

换句话说,eTLD+1是有效的顶级域名和域名之前的部分。
eTLD的概念主要应用于同源跨域的判断上,在页面转换、fetch()请求、cookies、打开弹出窗口、嵌入式资源和iframe的应用较多。

引用自web.dev/same-site-same-origin

根据注释推测是使用了eTLD的原因

那么让负载均衡不使用eTLD就可以在扫描的时候实现秒切IP了❓

0x02 分析

打开Clash-1.6.5源码  全局搜索etld

运气不错  只有loadbalance.go在一个函数内部声明了etld

2021-08-23-23-48-02.png

继续分析  首先声明了变量etld

调用publicsuffix.EffectiveTLDPlusOne()方法对metadata.Host进行处理并赋值给etld

然后定义了一个函数getKey()来接收处理后的metadata.Host

2021-08-23-23-55-52.png

那么函数getKey()返回的值可以是目的IP  也可以是eTLD(eTLD+1)
(其实分析到这里  已经隐约感觉到问题没有出在eTLD

继续搜索  发现函数strategyConsistentHashing()调用了getKey()

根据函数名判断strategyConsistentHashing()是一致性哈希算法策略

2021-08-24-00-03-20.png

一致性哈希算法是负载均衡调度算法的其中一种

以Nginx负载均衡的算法进行类比  相当于ip_hashurl_hash的结合

ip_hash:每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。

url_hash:按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率。如果需要这种调度算法,则必须安装Nginx的hash软件包。

分析到这步  基本可以确定IP秒切失败的原因是使用了一致性哈希调度算法导致的
那么只要使用轮询调度算法来分配每次请求  就可以实现IP秒切效果

轮询调度(Round-Robin,RR):最简单的调度算法,LB按照顺序将请求依次转发给后端的RS,并没有考量后端RS的状态(处理速度以及响应时间)。

带权重的轮询调度(Weighted Round-Robin,WRR):在轮询算法的基础上加上权重设置,权重越高的RS被分配到的请求越多。

上下随便翻翻  发现函数strategyConsistentHashing()上方已经写好了Round-Robin调度算法

本来还想尝试写一个呢hhh  既然如此  那就来看下两个函数之间的差异

直接的原因就在于变量idx的值  而idx的值又是由两种算法决定的

一致性哈希会把同一个IP/URL的请求分配到同一个代理上  idxgetKey()的返回值相关

轮询调度会把每一次请求分配到不同的代理上  idx仅和代理的数量相关

两者在策略失效的情况下  都会默认选择第1个代理

2021-08-24-00-08-56.png

调度算法已经有了  现在只要找到哪里调用了strategyRoundRobin()

粗略读一下代码  发现函数NewLoadBalance()对调度算法进行了分支选择

2021-08-24-00-11-51.png

继续跟进 函数parseStrategy()从字典config[]strategy键值对读取解析策略

推测字典对象config[]对应Clash的配置文件*.yaml

如果在字典中没有读取到strategy键值对  就会默认使用consistent-hashing作为解析策略

(后续经过测试strategy键值对要写在配置文件load-balance的内部才会生效)
2021-08-24-00-15-45.png

那么这里就有两种解决方法:

  1. 将函数parseStrategy()的默认返回值由consistent-hashing更改为round-robin
  2. 在配置文件里新增键值对strategy并赋值为round-robin

显然方法2更加便捷灵活

(安福仔一枚基本不接触开发 分析缺陷的地方还请师傅们多指教)
(RR是作者后期增加的一个调度算法  早期的配置文档里没有样例  所以才有了这篇文章)

0x03 调试

将配置文件修改以后  简单进行一下测试

2021-08-24-19-30-53.png

使用浏览器连接代理访问cip.cc  通过不断刷新页面来观察IP的切换情况

然而在每次刷新之后IP依旧固定不变

2021-08-24-00-18-43.png

再三阅读代码确认没有问题之后  在一次测试中无意间点开了CFW的连接

原来在访问网站之后  TCP连接没有立即断开  而是处于保持连接状态

2021-08-24-00-21-30.png

F12呼出控制台 --> 刷新  果然  请求和响应头部都被设置了Connection: keep-alive

2021-08-24-00-23-33.png
2021-08-24-00-23-58.png

突然想到Burpsuite默认会把Connection字段值改写为close

于是起Burp --> 挂代理 --> 抓包 --> 重放 --> 重放 --> 重放  OK

2021-08-24-00-37-22.png
2021-08-24-00-38-47.png
2021-08-24-00-40-07.png

最后  VPS起个WEB服务  拿dirsearch跑一跑验证效果

2021-08-24-00-29-59.png

这样又可以放心大胆的干活了

阅读 564

平(安)是(服)

1 声望
0 粉丝
0 条评论
你知道吗?

平(安)是(服)

1 声望
0 粉丝
文章目录
宣传栏