如何使用 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
它通常和一些额外的标志一起使用。
在大多数系统中,netcat
和 nc
可以互换使用。它们实际上是同一个命令的不同名称。
如何使用 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 试图让形成连接的过程不那么复杂,使计算机之间的网络互动变得透明。