Socat 魔法:内网穿透

今天有一个这样的需求:

  • 我们提供 HTTP 服务给另一个团队,在联合调试的时候,客户端只能从服务器发起请求;
  • 我们想把服务部署在本地的笔记本上,用于调试,但是,服务器和笔记本之间有 NAT 和防火墙,在服务器上的客户端只能访问服务器,不能访问到我们的笔记本;
  • 但是我们的笔记本也可以文档服务器;

这就是一个典型的内网穿透的需求了。我今天发现,socat 就可以做这样的事情。

如下图所示:server 端的 5.5.5.5 的 IP 可以被访问,但是笔记本上的 IP 不可以。

socat 内网穿透原理

思路是:

  • 我们打开两个 socat 进程,一个在本地笔记本上,另一个在 server 端;
  • Server 端的 socat 做一件事情:Listen 8075 端口,一旦有连接建立,就开始 listen 5678 端口,然后将所有 8075 端口收到的内容全部复制到 5678 ,将 5678 的内容复制到 8075
  • Client 端的 socat 做一件事情:不断去尝试连接 5.5.5.5:5678 这个地址,一旦能够建立连接,就跟 192.168.0.9:8000 (或者 127.0.0.1 建立连接),然后将 5.5.5.5:5678 的内容复制到 192.168.0.9:8000 ,将 192.168.0.9:8000 的内容复制到 5.5.5.5:5678;

客户端运行的命令是:

服务端运行的命令是:

这样,运行在本地 192.168.0.9:8000 的服务就通过 5.5.5.5:8075 暴露出来了,当用户访问 5.5.5.5:8075 的时候,就如同访问 192.168.0.9:8000 一样:

  1. 用户和 5.5.5.5:8075 建立 TCP 连接,将请求发送给 5.5.5.5:8075,此时,收到 HTTP 请求的实际上是 Server 端 Socat 进程;
  2. Server 端的 Socat 开始 listen 5.5.5.5:5678;
  3. Client 端的 Socat 不断尝试连接 5.5.5.5:5678(按照上文中的参数,是每 1s 尝试一次), 这时候,因为第 (2) 步,Client 的 Socat 同 5.5.5.5:5678 的连接建立成功,因此 Client 端 Socat 也和 192.168.0.9:8000 建立了连接;
  4. Server 端的 Socat 将 HTTP 请求发送给了 Client 端 Socat;
  5. Client 端 Socat 将 HTTP 请求发送给了 192.168.0.9:8000;
  6. 当笔记本上的 HTTP Server 发送了 HTTP Response,Client 端 Socat 将 HTTP Response 发送给了 5.5.5.5:5678,收到这个响应的是 Server 端的 Socat;
  7. Server 端的 Socat 将 HTTP 响应发送给客户端;
  8. 客户端收到 HTTP Response。

参考:



Socat 魔法:内网穿透”已经有4条评论

  1. 如果laptop 能够ssh访问server,通过ssh 远程转发似乎也可达到类似效果。
    ssh -R 8075:192.168.0.9:8000 -N 5.5.5.5

    • 是的。但是情况还稍微有一些特殊,我们的环境中可以 ssh 但是不可以做端口转发,ssh 端口转发这个功能是可以单独禁用而不影响 ssh 原本的功能的。

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用*标注