今天有一个这样的需求:
- 我们提供 HTTP 服务给另一个团队,在联合调试的时候,客户端只能从服务器发起请求;
- 我们想把服务部署在本地的笔记本上,用于调试,但是,服务器和笔记本之间有 NAT 和防火墙,在服务器上的客户端只能访问服务器,不能访问到我们的笔记本;
- 但是我们的笔记本也可以文档服务器;
这就是一个典型的内网穿透的需求了。我今天发现,socat 就可以做这样的事情。
如下图所示:server 端的 5.5.5.5
的 IP 可以被访问,但是笔记本上的 IP 不可以。
思路是:
- 我们打开两个 socat 进程,一个在本地笔记本上,另一个在 server 端;
- Server 端的 socat 做一件事情:Listen
8075
端口,一旦有连接建立,就开始 listen5678
端口,然后将所有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
;
客户端运行的命令是:
1 |
socat -d -d -d -v tcp:5.5.5.5:5678,forever,intervall=1,fork,reuseaddr tcp:192.168.0.9:8000 |
服务端运行的命令是:
1 |
socat -d -d -d tcp-l:8075,reuseaddr,bind=0.0.0.0,fork tcp-l:5678,bind=0.0.0.0,reuseaddr,retry=10 |
这样,运行在本地 192.168.0.9:8000
的服务就通过 5.5.5.5:8075
暴露出来了,当用户访问 5.5.5.5:8075
的时候,就如同访问 192.168.0.9:8000
一样:
- 用户和
5.5.5.5:8075
建立 TCP 连接,将请求发送给5.5.5.5:8075
,此时,收到 HTTP 请求的实际上是 Server 端 Socat 进程; - Server 端的 Socat 开始 listen
5.5.5.5:5678
; - Client 端的 Socat 不断尝试连接
5.5.5.5:5678
(按照上文中的参数,是每 1s 尝试一次), 这时候,因为第 (2) 步,Client 的 Socat 同5.5.5.5:5678
的连接建立成功,因此 Client 端 Socat 也和192.168.0.9:8000
建立了连接; - Server 端的 Socat 将 HTTP 请求发送给了 Client 端 Socat;
- Client 端 Socat 将 HTTP 请求发送给了
192.168.0.9:8000
; - 当笔记本上的 HTTP Server 发送了 HTTP Response,Client 端 Socat 将 HTTP Response 发送给了
5.5.5.5:5678
,收到这个响应的是 Server 端的 Socat; - Server 端的 Socat 将 HTTP 响应发送给客户端;
- 客户端收到 HTTP Response。
参考:
思路那个部分第二点有个typo:Cerver->Server
谢谢!已经改正。
如果laptop 能够ssh访问server,通过ssh 远程转发似乎也可达到类似效果。
ssh -R 8075:192.168.0.9:8000 -N 5.5.5.5
是的。但是情况还稍微有一些特殊,我们的环境中可以 ssh 但是不可以做端口转发,ssh 端口转发这个功能是可以单独禁用而不影响 ssh 原本的功能的。