Skip to main content

如何使用 Netcat 建立并测试 TCP 和 UDP 连接

作者 Justin Ellingwood

导言

Linux 以拥有大量完善好用的命令行工具而闻名,在大多数发行版中,这些工具是开箱即可使用的。系统管理员通常可以使用内置的工具来完成大部分的工作,而不需要安装额外的软件。 在本指南中,我们将讨论如何使用 netcat 工具。这个多功能的命令可以帮助你通过网络连接监控、测试和发送的数据。 Netcat 在几乎所有的现代 Linux 发行版上都可以使用。Ubuntu 带有 BSD 版本的 netcat,也是本指南所使用的。其他版本的操作可能会有所不同,或者可能提供其他选项。

一般句法

默认情况下,netcat通过启动一个 TCP 连接到一个远程主机。 最基本的句法是:

$ netcat [options] host port

以上代码试图在指定的端口号上启动一个 TCP 以连接到定义的主机。它的功能类似于以前的 Linux telnet 命令。请记住,你的连接是完全未加密的。 如果你想发送一个 UDP 数据包而不是启动一个 TCP 连接,可以使用 -u 选项:

$ netcat -u host port

你可以指定一个端口范围,方法是在第一个和最后一个端口之间放置一个破折号:

$ netcat host startport-endport

它通常和一些额外的标志一起使用。 在大多数系统中,netcatnc 可以互换使用。它们实际上是同一个命令的不同名称。

如何使用 Netcat 进行端口扫描

Netcat 最常见的用途之一是端口扫描器。 尽管对于端口扫描,netcat 可能不是最先进的工具(大多数情况下nmap 是一个更好的选择),但它可以执行简单的端口扫描来轻松识别开放的端口。 我们通过指定要扫描的端口范围来实现这一目的,就像我们上面所做的那样,再加上 -z 选项来执行扫描,而不是试图启动一个连接。 例如,我们可以通过发出这个命令来扫描1000以下的所有端口:

$ netcat -z -v domain.com 1-1000

-z 选项外,我们还指定了 -v 选项,来让 netcat 提供更多详细信息。 输出看起来像是这样:

Output
nc: connect to domain.com port 1 (tcp) failed: Connection refused
nc: connect to domain.com port 2 (tcp) failed: Connection refused
nc: connect to domain.com port 3 (tcp) failed: Connection refused
nc: connect to domain.com port 4 (tcp) failed: Connection refused
nc: connect to domain.com port 5 (tcp) failed: Connection refused
nc: connect to domain.com port 6 (tcp) failed: Connection refused
nc: connect to domain.com port 7 (tcp) failed: Connection refused
. . .
Connection to domain.com 22 port [tcp/ssh] succeeded!
. . .

如你所见,netcat 提供了大量的信息,并告诉你每个端口的扫描是否成功。 如果你使用的是一个域名,那么必须要使用这种形式。 然而,如果你知道所需的IP地址,扫描会快很多。然后可以使用 -n 标志来明确表示你不需要使用 DNS 来解析 IP 地址。

$ netcat -z -n -v 198.51.100.0 1-1000

返回的信息实际上被发送到了“标准错误”。我们可以将标准错误信息发送到标准输出,这样更容易过滤结果。 使用 bash 语法 2>&1 把标准错误重定向到标准输出。然后用 grep 来过滤这些结果:

$ netcat -z -n -v 198.51.100.0 1-1000 2>&1 | grep succeeded
Output
Connection to 198.51.100.0 22 port [tcp/*] succeeded!

这里我们可以看到,在远程计算机上1-1000范围内唯一开放的端口是22端口,即传统的 SSH 端口。

如何通过 Netcat 通信

Netcat 不仅限于发送 TCP 和 UDP 数据包。它也可以在一个端口上监听连接和数据包。因此我们能够以客户-服务器关系连接两个 netcat 实例。 哪台计算机是服务器,哪台计算机是客户端,这种区别只体现在初始配置阶段。连接建立后,两个方向上的通信是完全相同的。 在一台机器上,你可以让 netcat 侦听一个特定端口的连接。提供形参 -l 并选择一个端口:

$ netcat -l 4444

这将告诉 netcat 侦听 4444 端口的 TCP 连接。作为一个普通的(非root)用户,出于安全措施的限制,你将不能打开任何低于1000的端口。 在第二台服务器上,我们可以通过选择的端口号连接到第一台机器。用之前建立连接的方式来做这件事:

$ netcat domain.com 4444

看起来好像什么都没有发生。然而实际上,你现在可以在连接的任何一方发送消息,在两端都能看到。 输入一条信息并按下 ENTER 键。该信息将同时出现在本地和远程屏幕上。在相反的方向上也是如此。 完成信息传递后,你可以按 CTRL-D 关闭 TCP 连接。

如何通过 Netcat 发送文件

在前面例子的基础上,我们可以完成更多有用的任务。 我们正在建立的是一个常规的 TCP 连接,因此我们可以通过该连接传输几乎任何类型的信息。这并不局限于用户输入的聊天信息。我们可以利用这些知识把 netcat 变成一个文件传输程序。 我们依然需要选择连接的一端来监听连接。然而,我们不是像上一个例子中那样把信息打印到屏幕上,而是把所有的信息直接放到一个文件中:

$ netcat -l 4444 > received_file

这个命令中的 > 将 netcat 的所有输出重定向到指定的文件名。 在第二台电脑上,输入以下内容创建一个简单的文本文件:

$ echo "Hello, this is a file" > original_file

现在这个文件可以作为我们将与监听计算机建立的 netcat 连接的输入。该文件将被传送过去,与以交互方式输入十分相似:

$ netcat domain.com 4444 < original_file

我们可以看到,在等待连接的计算机上有了一个新的文件,叫做 received_file,里面有我们在另一台计算机上输入的文件内容。

$ cat received_file
Output
Hello, this is a file

正如你所看到的,我们可以很容易地利用这种管道连接来传输各种东西。 例如,我们可以飞速创建一个未命名的 tarball,将其传送到远程系统并解压到远程目录,这样就能够传输整个目录的内容。 在接收端,我们预期见到一个需要解压和提取的文件,可输入以下内容来解压和提取:

$ netcat -l 4444 | tar xzvf -

结尾的短横(-)意味着 tar 将在标准输入上操作,连接建立后,标准输入会通过网络从 netcat 输送过来。 在另一边,我们可以把我们想传输的目录内容打包成一个 tarball,然后通过 netcat 把它们发送到远程计算机上:

$ tar -czf - * | netcat domain.com 4444

这一次,tar 命令中的短横意味着对由*通配符指定的当前目录的内容进行压缩,并将结果写到标准输出。 然后目录内容被直接写入 TCP 连接,再由另一端接收,并解压到远程计算机的当前目录中。 关于将更复杂的数据从一台计算机传输到另一台计算机,这只是其中一个例子。另一个常见的想法是使用 dd 命令在一侧对磁盘进行镜像,并将其传输到远程计算机上。不过我们不会在这里讨论如何操作。

如何将Netcat作为一个简单的 Web 服务器

刚刚我们一直在配置 netcat 来监听连接,以便进行通信和传输文件。我们可以使用同样的想法将 netcat 作为一个非常简单的 web 服务器。这可以用来测试你创建的网页。 首先,让我们在服务器上制作一个简单的 HTML 文件:

$ nano index.html

这里有一些简单的HTML,可以在你的文件中使用: index.html

<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1>Level 1 header</h1>
<h2>Subheading</h2>
<p>Normal text here</p>
</body>
</html>

保存并关闭该文件。 如果没有root权限,就不能在默认的网络端口80上提供这个文件。可以用普通用户的身份选择8888端口。 如果你只想提供一次这个页面以检查它的渲染效果,可以运行以下命令:

$ printf 'HTTP/1.1 200 OK\n\n%s' "$(cat index.html)" | netcat -l 8888

现在你可以在浏览器上通过以下地址访问其内容:

http://server_IP:8888

提供该页面后,netcat 连接将关闭。如果你试图刷新该页面,它就会消失。

我们可以将最后一条命令包裹在一个无限循环中,让 netcat 无限期地提供该页面,就像这样:

$ while true; do printf 'HTTP/1.1 200 OK\n\n%s' "$(cat index.html)" | netcat -l 8888; done

以上代码将允许 netcat 在第一个连接关闭后继续接收连接。 我们可以通过在服务器上输入 CTRL-C 来停止循环。 这可以让你看到一个页面在浏览器中的渲染情况,但它并不提供更多的功能。永远不要用它来提供真正的网站。因为它不具备安全性,而且一些简单的东西(比如链接)都不能正常运行。

结语

你现在应该对 netcat 的用途有了很好的了解。它是一个功能丰富的工具,可以用来诊断问题,并验证 TCP/UDP 连接的基本功能是否正常工作。 使用netcat,你可以十分轻松地在不同的计算机之间进行传输,实现快速互动。Netcat 试图让形成连接的过程不那么复杂,使计算机之间的网络互动变得透明。