端口转发是一个你不常会遇到的情况,但是一旦他来了,手头的工具要么太重,要么不趁手。举个简单的例子,你可能需要外网流量转发到本地内网,也有可能需要把IPv6流量转移到外网的IPv4,甚至可能需要UDP转发,面对这多样的情况,iptables的性能上不去,配置太麻烦,后期维护不方便等等问题很容易成为阻碍。面对这样的情况,我们需要 socat来解决这一切。

介绍&安装

netcat是个计算机网络公用程式,用来对网络连线TCP或者UDP进行读写。
socat 是 netcat 较复杂的姊妹程式。它比起netcat更大更复杂,并且有更多的选项得在给定作业前先设定。

事实上socat的功能非常强大,能做到的不仅仅是端口转发这样简单的事情。

安装没什么好说的

apt-get install socat

实践

要注意,socat只是一个命令行工具,要守护运行你可能需要nohup或者supervisor,这里着重介绍socat的参数与功能。

socat的上手难度并不高,你只需要记住这个固定的语法,就可以把参数和变量套进去,即

socat [options] <address> <address>

不要把 address仅仅想成网络地址,由于Linux的万物皆文件,这里的 address也可以是某个pipe或者某个文件。

一般来说,address有这么几个常用的类型

  • TCP/UDP:建立一个TCP/UDP连接作为数据流
  • TCP-LISTEN/UDP-LISTEN:监听一个端口
  • 文件:任意路径的文件

在地址后面可以加一些选项,这个我们放在后面详细说。

对于端口转发,我们需要监听一个地址,同时把监听到的数据发送给另外一个地址,这里就有了两个 address类型,举例来说,就好比这样

socat TCP-LISTEN:8080 TCP:192.168.1.2:8080

这样我们就实现了监听本地8080端口,并将该端口的数据转发到192.168.1.2的对应端口上,socat会自己帮我们把反向的链路建立,所以不需要类似 iptables的多余操作。

正如前面所说,socat是一个命令行程序,这就意味着他不能在同一个终端下建立多个进程,这对于高并发场景来说意味着多条TCP抢socat,延迟也会因此有着不可忍受的波动,所以我们使用 reuseaddr参数绑定一个本地端口,同时使用 fork参数将socat转变为多链接模式,即当一个链接建立后,自动复制一个同样的端口监听,这样就能有效提高高并发场景下的性能表现。

但是在实际的生产场景中,为了避免 root用户执行某些程序,我们还要给 socat指定一个运行权限。所以,最终是这个样子的

socat TCP-LISTEN:8080,reuseaddr,fork,su=nobody TCP:192.168.1.2:8080

这里你可以把TCP换成UDP或者简单的变为TCP6/UDP6,可以指定对应的协议进行监听和转发,或者可以只用TCP或者UDP,在 option中使用 -4-6参数来指定偏好的协议。

特别的,对于UDP这样的链接来说,最好在命令中加入 -T参数,尽快关闭不活跃的链接。

socat -T 120 UDP-LISTEN:8080,reuseaddr,fork,su=nobody UDP:192.168.1.2:8080

这样,在UDP链路不活跃120s之后,这个fork出来的子进程就会被关闭,但是主进程仍然保留。

进阶

由于 address的变化性,我们甚至可以把 socat作为Web Server或者一个文件服务器,

socat -d -d /dev/sda1,rawer,nonblock,ignoreeof,cr,echo=0 TCP-LISTEN:55555,reuseraddr

这样,一个监听在55555端口上的文件服务器就有了,其中

  • -d -d:输出调试信息
  • rawer:直接读取/写入,这样可以提升速度。
  • nonblock:使用non-block IO模式防止拥塞
  • ignoreeof:忽略EOF,这让这台文件服务器一直在线,而不是每传输完一个文件后就关闭
  • cr:换行符转换
  • ehco=0:关闭echo(根据rawer的要求)

总之,你可以使用做端口转发,做文件服务器,做任何有关两点间通信的任何事情。

最后修改:2021 年 07 月 10 日
如果觉得我的文章对你有用,请随意赞赏