Contents

Linux中的SOCAT命令简介

1. 概述

在本教程中,我们将了解 Linux 中的socat 命令。Socat是一种灵活的多用途中继工具。其目的是建立两个数据源之间的关系,其中每个数据源可以是一个文件、一个 Unix 套接字、UDP、TCP 或标准输入。

2. socat的用例

Socat对于连接不同盒子内的应用程序很有用。想象一下,我们有 Box A 和 Box B,在 Box A 内部,有一个数据库服务器应用程序正在运行。此外,盒子 A 不对公众开放,但盒子 B 是开放的。我们的网络将允许从 Box B 到 Box A 的连接。

现在,假设用户想要读取数据库日志。我们不希望用户进入 Box A,但如果用户想进入 Box B,我们就可以了。

Socat可以将 Box A 中的数据库日志与 Box B 中的文本阅读器连接起来。这样,用户就可以阅读 Box B 中的日志。我们不必为了让用户这样做而损害 Box A 的安全性工作。

Socat可以双向工作。Box B 中的用户可能希望将一些数据库查询发送到 Box A 中的数据库服务器应用程序。然后,数据库服务器应用程序可以将结果发送回 Box B 中的用户***。Socat 也*支持双向通信**。

让我们从对socat命令的介绍开始。然后,我们将继续一系列示例。

3. 安装socat

Socat在大多数 Linux 发行版中都可用。

3.1. 先决条件

对于本教程中的示例,我们将使用nc 和Docker,我们可以从他们的用户指南中安装它们。

3.2. 在基于 Debian 的 Linux 中安装socat

要在基于 Debian 的 Linux(例如 Ubuntu)上安装socat ,我们使用apt-get

$ apt-get install -y socat

3.3. 在基于 RHEL 的 Linux 中安装socat

在基于 RHEL 的 Linux(例如 Fedora)上,我们应该使用yum

$ yum install -y socat

4. 双向流

我们可以使用socat连接两个数据源,并在它们之间流式传输数据。

4.1. 连接两个流源

让我们将nc与传输控制协议 (TCP) 连接起来,并从两个方向传输数据。我们需要两个控制台终端来进行这个实验。

在第一个终端上,让我们在监听模式下运行nc

$ nc -l localhost 1234 

-l标志表示nc处于侦听模式。它侦听localhost 端口1234

在第二个终端上,让我们运行socat以使用 TCP 协议将STDIO 连接到具有端口1234localhost

$ socat STDIO TCP4:localhost:1234

在上面的命令中,第一个参数是标准输入,用关键字STDIO表示。第二个参数是具有特殊语法的字符串。正如我们所见,字符串用冒号分隔符分为三部分。第一部分是地址格式TCP4。第二部分是服务器或 IP 地址localhost。最后一部分是端口1234

socat应用程序将来自第一个参数*(STDIO)的流连接到第二个参数(TCP4:localhost:1234)*中提到的流。在这种情况下,我们可以切换参数的顺序,这并不重要,因为它是双向的。

4.2. 测试流

现在,我们在第二个终端上的标准输入连接到nc服务器。我们可以在上面输入一些东西:

Good morning!

然后,我们回到第一个终端。我们可以看到我们在第二个终端上输入的文本打印在第一个终端上

Good morning!

然后,我们可以在*“早上好!”下面输入一些内容。*在第一个终端上:

Life is beautiful.

然后,我们回到第二个航站楼。我们可以看到*“生活是美好的”。*也在那里打印:

Life is beautiful.

4.3. 转发流

socat可以转发将由另一个socat应用程序接收到的数据,而不是自己处理数据。这一次,我们需要三个控制台终端。

在第一个终端上,我们照常运行nc

$ nc -l localhost 1234

在第二个终端上,我们运行socat。但这一次,我们没有将标准输入与第一个终端上的nc应用程序连接起来。相反,我们监听另一个端口:

$ socat TCP4-LISTEN:4321 TCP4:localhost:1234

我们使用了不同的字符串语法TCP4-LISTEN:4321。 这意味着我们监听来自第二个参数TCP4:localhost:1234 的数据,并将其写入端口4321。当我们使用TCP4-LISTEN地址格式时,我们只添加了端口。这与我们必须填写服务器地址的TCP4地址格式不同。

在第三个终端上,我们将运行socat,这一次,我们将标准输入连接到第二个终端上的socat应用程序:

$ socat STDIO TCP4:localhost:4321 

现在,当我们在第一个终端上键入内容时,我们可以看到文本出现在第三个终端上。这三个终端通过作为中继的第二个终端联网

4.4. 连接 Docker 和socat

为了使我们的示例更实用,我们将在一个单独的终端中将 Web 服务器与 Web 客户端连接起来。首先,我们需要拉取 Nginx Docker 镜像:

$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
1fe172e4850f: Pull complete 
35c195f487df: Pull complete 
213b9b16f495: Pull complete 
a8172d9e19b9: Pull complete 
f5eee2cb2150: Pull complete 
93e404ba8667: Pull complete 
Digest: sha256:859ab6768a6f26a79bc42b231664111317d095a4f04e4b6fe79ce37b3d199097
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

我们确保端口80未被占用。然后,我们运行nginx Docker 镜像

$ docker run -p 80:80 nginx

run参数是运行 Docker 镜像。-p选项将容器上的端口80映射到主机上的端口80 。如果我们不这样做,我们将无法从主机访问网络服务器。

然后,在第二个终端上,我们运行socat来连接 Nginx 服务器

$ socat TCP-LISTEN:1234,reuseaddr,fork TCP:localhost:80

我们之前学过第一个论点。TCP-LISTEN用于监听端口1234中的数据移动。但是在这里,参数语法中还有其他部分:reuseaddrfork。他们的意思是socat分叉一个子进程到连接到这个端口的进程

在第三个终端上,让我们运行socat将标准输入连接到端口1234

$ socat STDIO TCP4:localhost:1234

最后,在第四个终端,让我们再次运行相同的命令

$ socat STDIO TCP4:localhost:1234

请注意,我们将两个socat应用程序连接到同一个端口。这是因为我们在TCP-LISTEN参数中使用了 reuseaddrfork 。如果我们不使用它们,第四个终端上的相同命令将失败:

$ 2022/04/14 02:37:17 socat[4017376] E connect(5, AF=2 127.0.0.1:1234, 16): Connection refused

我们可以输入任何内容来测试连接。我们可以在第三个终端或第四个终端上执行此操作。让我们测试一下网络连接。我们可以使用GET请求:

GET /

我们将在同一个终端中获得输出:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
</html>
```bash
`On the first terminal, we can see that *socat* passed the data just fine:
```shell
172.17.0.1 - - [28/Apr/2022:16:51:34 +0000] "GET /" 200 615 "-" "-" "-"

5. 单向流

我们了解到socat默认是一个双向流协议。但我们可以使用它的单向模式。

5.1. -u 标志

我们可以使用socat创建一个文件。让我们运行下面的命令,输入一些内容,然后按Enter,最后退出:

$ socat -u STDIO FILE:test.txt,create
Hello socat!

我们可以检查test.txt文件的内容:

$ cat test.txt
Hello socat!

-u标志表示**数据流从第一个参数STDIO运行到第二个参数文件text.txt。**第二个参数使用FILE地址格式。正如我们可以猜测的,这种格式接受文件名和打开文件的模式。在我们的示例中,模式是create。在此模式下,没有数据从第二个流传输到第一个流。

顺序或参数很重要。如果我们交换参数,命令的结果将会不同:

$ socat -u FILE:test.txt,create STDIO
Hello socat!

这次,该命令显示了文件的内容。如果我们尝试使用不同的新文件,输出将为空:

$ socat -u FILE:blogdemo.txt,create STDIO

当第一个参数是文件并且STDIO是第二个参数时,socat读取文件的内容并将其显示在stdout中。但是当它相反时,socat会将来自stdin的输入写入文件中。

5.2. -U 标志

还有另一个标志执行*-u* 标志的相反操作。-U 标志与*-u* 标志相同,但参数的顺序相反。

让我们运行前面的命令,但使用 -U 标志,输入一些内容,然后按Enter,最后退出:

$ socat -U FILE:test.txt,create STDIO
Hello socat! This time we use the -U flag.

然后我们可以检查文件的内容:

$ cat test.txt
Hello socat! This time we use the -U flag.

所以基本上,socat -u arg1 arg2socat -U arg2 arg1相同。