上篇我们介绍了服务网格 osm-edge 出口网关使用的 HTTP 隧道,其处理方式与另一种代理有点类似,就是今天要介绍的 SOCKS 代理。二者的主要差别简单来说就是前者使用 HTTP CONNECT
告知代理目的地址,而后者则是通过 SOCKS 协议。值得一提的是,SOCKS 也是出口网关的可选协议之一。
SOCKS 是一种网络传输协议,是 Socket Secure 的缩写,主要用于客户端与外网服务器之间通讯的中间传递。根据 OSI 模型,SOCKS 是会话层的协议,位于表示层与传输层之间。
SOCKS 协议的最新版本是 SOCKS5,在 SOCKS4 的基础上增加了 UDP、认证 和 IPv6 的支持。因此,后面提到的 SOCKS 都是使用最广泛的 SOCKS5。
先看一下 SOCKS 代理的工作流程。
![null b9003b6ec899d8190e941fab5669b6ac.png](https://img-blog.csdnimg.cn/img_convert/b9003b6ec899d8190e941fab5669b6ac.png)
1. 协商阶段:客户端与代理建立连接,并进行协商,包括协议版本、认证的方式等等。
2. 连接阶段:客户端告知代理要连接的目的地址和端口(SOCKS 报文),代理使用报文中的地址和端口与服务端创建连接,并将结果作为状态返回给客户端。
3. 数据传输阶段:客户端向代理发送数据,代理将数据发送到服务端;然后将服务端返回的数据返回给客户端。
Demo
![null fd5da69f36a0e4804f5ea784ba3fd5d4.png](https://img-blog.csdnimg.cn/img_convert/fd5da69f36a0e4804f5ea784ba3fd5d4.png)
还是使用上篇中的例子,在防火墙后有个 TCP 服务端,由于监听在 127.0.0.1:8081
还能在本地访问。同样,使用 Pipy 来模拟这个服务。
pipy().listen('127.0.0.1:8081').replaceData(() => new Data('Hi, TCP!\n'))
接下来,在服务端一侧建立一个 SOCKS 代理。
![null 96890e3f7edd1d09e9728f0bc1dea68f.png](https://img-blog.csdnimg.cn/img_convert/96890e3f7edd1d09e9728f0bc1dea68f.png)
PipyJS 编码
我们的代理监听在 8000
端口,使用 acceptSOCKS
过滤器[1] 来处理 SOCKS 协议报文,从报文中获取目的地址和端口,然后使用该地址和端口创建到服务端的连接。
pipy({_host: null,_port: null,
})//socks.listen(8000).acceptSOCKS((host, port) => (_host = host,_port = port,true // return true to accept the session)).to($ => $.connect(() => `${_host}:${_port}`))
测试
在主机 192.168.1.110
上运行我们的代理以及服务端,客户端 curl
运行在主机 192.168.1.11
上。使用下面的命令进行测试:
curl -x socks5://192.168.1.110:8000 telnet://127.0.0.1:8081
![null 6bcf9d0e56ea4615afd6b4808df028ec.gif](https://img-blog.csdnimg.cn/img_convert/6bcf9d0e56ea4615afd6b4808df028ec.gif)
引用链接
[1]
acceptSOCKS
过滤器: https://flomesh.io/pipy/docs/zh/reference/api/Configuration/acceptSOCKS