在 Linux 环境中测试本机与远程主机端口的网络连通性时我们一般都会使用 telnet 和 nc 进行测试,即使在 telnet 和 nc 工具都没有的前提下也可以使用类似 wget 和 curl 等工具变相实现端口测试的目的。然而最近发现在容器中会有更恶劣的条件,即 telnet nc curl wget nmap socat 等能够想到的工具全都没有,这种情况下似乎没有任何办法了。不过没多久在和几个搞安全的同学聊天的时候意外了解到了反弹 shell 这个操作,由此发现还可以使用 bash 自带的 /dev/tcp/dev/udp 来解决这个问题!

什么是 /dev/tcp/dev/udp

我们都或多或少的听说过在 linux 中 “一切皆文件“,这两个便是 linux 中的特殊文件,可以通过它们使用 TCP 或 UDP 协议与外界(本机也行)进行网络通信。也就是说,我们可以直接向目标主机的指定端口发送数据,而不需要任何额外的程序。下面说明如何使用它们。

测试 TCP 端口连通性

首先,打开你的终端,输入以下命令来测试 TCP 连接:

1
echo hello > /dev/tcp/目标主机/IP/端口

举个例子,假设你想测试与 192.168.1.10 的 80 端口的连接,可以这样写:

1
echo hello > /dev/tcp/192.168.1.10/80

接下来,你可以根据返回检查连接状态:

  • 如果连接成功,终端不会显示任何输出,并且状态码为 0。
  • 如果连接失败,终端会给出错误信息例如 refusedno route to host
  • 如果连接超时,终端则会一直没反应,一般超过三秒没任何动静就可以认为是 timeout 了

测试 UDP 端口连通性

UDP 的测试稍微复杂一点,因为它是无连接的协议,不能像 TCP 那样直接使用 echo 后根据返回值进行判断,即便发送后没有任何返回,这也不一定意味着连接失败。但是我们可以到目标主机上启动一个 udp 端口,然后在源端使用 /dev/udp 的方法给该端口发送数据,如果网络是正常连通的则在目标主机上可以收到源端发送的数据。
比如,在源端使用:

1
echo "hello world" > /dev/udp/192.168.1.30/4888

那么在网络连通的情况下,目标主机 192.168.1.30 的 4888 端口是可以收到源端发送的字符 hello world 的!