使用 HTTP Piping Server 做通用的 TCP 内网穿透/反向代理
-
原文:Secure TCP tunnel from anywhere with curl and nc for single connection(原理介绍)
(另一篇文章 The Power of Pure HTTP – screen share, real-time messaging, SSH and VNC 举了大量浏览器前端中实现 ssh、屏幕共享、VNC的例子,没有讲述原理,但是这种基于 HTTP 的 TCP 管道式代理方法本身不仅限于浏览器中使用)
Github 项目:https://github.com/nwtgck/piping-server原理不复杂,就是用 HTTP 转发 TCP 流量。这个只需要 HTTP 服务器就可以用(绝大多数 CDN 都只支持 HTTP)
举例:假设 https://ppng.io 是部署了原文所说的 piping-server,在自己的 Server 上(比如在 22 端口启动了 sshd),使用如下命令启动入站和出站 TCP 隧道:
# server host curl -sSN https://ppng.io/aaa | nc localhost 22 | curl -sSNT - https://ppng.io/bbb
然后在要自己的 Client 端,使用如下命令启动出站和入站 TCP 隧道:
# client host curl -sSN https://ppng.io/bbb | nc -lp 2222 | curl -sSNT - https://ppng.io/aaa
最后在 Client 端连接到本地的 2222 端口:
ssh -p 2022 root@127.0.0.1
中间使用了辅助的命令 curl 和 nc 作为 TCP 流量管道。
Server 端:
curl -sSN https://ppng.io/aaa
:让 curl 从https://ppng.io/aaa
读取输入,安静输出(-sS
)并流式(-N
)输出到 stdout(Server 监听 /aaa)nc localhost 22
:将上一步的输出管道接到 Netcat 并发送到localhost
的 22 端口curl -sSNT - https://ppng.io/bbb
:将上一步的输出管道接到 curl 并上传(-T
)到https://ppng.io/bbb
,流式(-N
)安静输出(-sS
),中间的-
表示从 stdin 输入(Server 返回结果到 /bbb)
Client 端:
curl -sSN https://ppng.io/bbb
:让 curl 从https://ppng.io/bbb
读取输入,安静输出并流式输出到 stdout(Client 监听 /bbb)nc localhost 22
:将上一步的输出管道接到 Netcat,同时让 Netcat 监听(-l
)本地的 2222 端口curl -sSNT - https://ppng.io/bbb
:将上一步的输出管道接到 curl 并上传到https://ppng.io/bbb
,流式安静输出,中间的-
表示从 stdin 输入(Client 发送请求到 /aaa)
上面两步只是建立了 TCP 流量转发流程,并未真正启动 ssh 会话,最终的 ssh 会话由 ssh 客户端启动:
ssh -p 2022 root@127.0.0.1
整个流程图示如下:
---------------------------------------------------------------------------------- | [Client] | https://ppng.io | [Server] | |--------------------------------------------------------------------------------- | (Client TCP Upload) | | (Server TCP Download) | | ----> ---> curl ---|--> /aaa ---|--> curl ---> ----> | | ssh nc | | nc sshd | | <---- <--- curl <--|--- /bbb <--|--- curl <--- <---- | | (Client TCP Download) | | (Server TCP Upload) | ----------------------------------------------------------------------------------
-
需要和基于 frp 的方案做更细致的比较。比较明显的一个优势是 HTTP 服务器可用性更高,特别是大量 CDN 都只支持 HTTP
-
另外 piping-server 的一个问题是 /aaa 和 /bbb 等等 URL 每次只能一个 TCP 入站/出站连接配对,即不能多个 TCP 连接都连接到 /aaa 和 /bbb。这个可能会让部署略显复杂,需要更精巧的脚本去自动生成这些 URL 避免冲突,而且还需要 Server 端主动监听这些 URL(各种内网穿透的方案都需要被穿透方主动配合,因为 piping-server 或者 frp 都不能主动对被穿透方发起 TCP 连接)