去年 HW 时,我有幸做了一些后勤保障工作,主要是工具类的支持和部分漏洞武器化的工作。在用到某 webshell 的正向代理功能时,其速度和稳定性实在令我抓狂,经常用着用着就断掉了,多级代理更是不敢想。终于在一次莫名其妙崩掉后且无法恢复后,我决定花点时间写一个新的 HTTP Socks5 代理工具,这个工具就是 Suo5 的雏形。
基本原理
—
HTTP 代理隧道是什么,简单来说就是当你拥有了一个 webshell,想进一步探索内网时,可以借助该 webshell 构建一个 socks5 代理,使流量经由该 webshell 发送到内网。实现这一功能的经典的工具是 reGeorg 和 Neo-reGeorg,后者是前者的继承和延续,做了比较多拓展和更新,我们就以它为例看下基本原理。
使用时需要先上传一个服务端 tunnel.jsp 到目标 Web 服务中,在这里为了好听就叫他 ProxyBridge(PB) ,然后在本机启动一个客户端去连接这个 tunnel.jsp,连接成功后就在本机开启了一个 Sock5 服务,可以借助该服务访问 Inner Server 中做进一步测试。
要实现图中的这个通信链路,Socks5Handler(SH)需要实现一个 socks5 服务并监听,当有连接到来时,将连接信息封装为 HTTP 请求发送给 PB中,PB解析出要连接的目标然后尝试与目标建立 TCP 连接,并把连接状态通过 HTTP 响应反馈给 SH。
当用户写入数据时,SH->PB->InnserServer,当远端返回数时 InnerServer->PB->SH。如此循环往复,一条虚拟的 TCP 连接就构建出来了。这条通信链路关键的点在于 SH和PB之间的通信,本质上是在用 HTTP 包来构建 TCP 数据流,具体的只需要通信两端处理好连接的建立、数据交换和连接断开即可。但由于中间链路使用了 HTTP 请求响应来中转流量,实际使用过程往往感觉延迟比较高,速度也不太理想。
单车变摩托
—
去年 Beichen 师傅提出了一种新的方式来改善上述问题,具体可以看下这篇文章 Chunk-Proxy:仅需一条http请求创建的Socks代理隧道
这里总结一下结论:利用 HTTP/1.1 的 Transfer-Encoding: Chunked 模式来发送 Body,如果发送端不主动关闭 Body,在获取到服务端响应后可以继续发送 Body 数据,继续获取服务器响应,如此往复是不是很像裸的 TCP 通信!
这种通信模式相当于中间链路也是直连的,在使用体验上近似于 FRP 这类工具开的 Socks5 代理。
然而这个工具的实现有个比较大的问题是无法在反向代理的场景使用,最常见的 Nginx + Tomcat 的场景就无法使用。原因在于 Nginx 在处理 Chunked-Encoding类型的 Body 时会缓存 Body,直到发送端写完再把完整的 Body 发送给上游服务器:
When HTTP/1.1 chunked transfer encoding is used to send the original request body, the request body will be buffered regardless of the directive value unless HTTP/1.1 is enabled for proxying.
还有办法抢救一下吗?
Buffering can also be enabled or disabled by passing "yes" or "no" in t he "X-Accel-Buffering" response header field.
-
写数据通过 TCP HTTP 的请求拆包发送,借助 Keepalive 机制也能获得很不错的性能以及较低延迟
-
读数据通过 Chunked 的响应包实现,效果上类似 TCP 直连
作者:koalr
原文地址:https://koalr.me/posts/suo5-a-hign-performace-http-socks/
原文始发于微信公众号(刨洞技术交流):Suo5 - 高性能 HTTP 代理隧道
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论