nc 是一个功能强大的网络工具,被誉为“网络工具中的瑞士军刀”,它既能作为客户端,也能作为服务器,可以用于 TCP 和 UDP 协议,UDP 是一种无连接、不可靠的协议,与 TCP 的工作方式有很大不同,因此在 nc 中使用 UDP 也有一些特定的注意事项。

核心概念:UDP vs TCP
在使用 nc 之前,理解 UDP 和 TCP 的区别至关重要:
-
TCP (Transmission Control Protocol):
- 面向连接: 在传输数据前,必须先通过“三次握手”建立一个连接。
- 可靠传输: 通过序列号、确认应答、重传机制等确保数据无差错、不丢失、不重复,且按序到达。
- 有边界: 数据以报文段(Segment)为单位传输,
nc能清晰地看到数据的开始和结束。 - 速度较慢: 因为需要建立连接和维护状态,所以开销较大。
-
UDP (User Datagram Protocol):
- 无连接: 发送数据前不需要建立连接,直接将数据包(Datagram)发送出去。
- 不可靠传输: 不保证数据包的顺序、不保证不丢失、不保证不重复,它只管“尽力而为”地发送。
- 无边界: 数据流是连续的,
nc无法自动判断一个数据包的结束和下一个的开始。 - 速度快: 开销小,传输效率高,适用于对实时性要求高但能容忍少量丢包的场景(如视频、语音、DNS 查询等)。
nc 命令的基本 UDP 语法
要使用 nc 进行 UDP 通信,关键在于使用 -u 选项。

# nc -u [选项] 主机名 端口号
-u: 指定使用 UDP 协议。这是最重要的选项。
UDP 服务器(监听和接收数据)
UDP 服务器会绑定到一个指定的端口,并等待接收来自任何客户端的数据。
步骤:
-
启动服务器:在终端 A 中运行以下命令。
-l表示监听(listen),-u表示 UDP。# nc -lu -p 端口号 # 监听本机的 9999 端口 nc -lu -p 9999
-l: 监听模式。-u: UDP 模式。-p: 指定端口号。
-
发送数据:在另一个终端 B 中,使用
nc作为 UDP 客户端向服务器的 IP 和端口发送数据。
(图片来源网络,侵删)# nc -u 服务器IP地址 端口号 # 向本机(127.0.0.1)的 9999 端口发送 "Hello, UDP Server!" nc -u 127.0.0.1 9999
现在在终端 B 中输入任何文本并按回车,这些数据就会被发送到终端 A。
-
查看接收:回到终端 A,你会看到刚刚发送过来的数据。
# 终端 A (nc -lu -p 9999) Hello, UDP Server! This is another message.
重要提示:UDP 服务器在接收到数据后,默认情况下不会自动退出,它会一直运行,等待更多的数据,你可以使用 Ctrl + C 来终止它。
UDP 客户端(发送数据)
在上面的场景二中,我们已经展示了如何作为客户端发送数据,客户端非常简单,就是指定 -u 选项、目标 IP 和端口。
示例:
# 向 192.168.1.100 的 12345 端口发送一条测试消息 echo "This is a test" | nc -u 192.168.1.100 12345
这个命令通过管道 将 echo 命令的输出作为 nc 的输入,然后发送出去。
UDP 端口扫描(探测端口)
虽然 nc 主要用于数据传输,但也可以用来扫描一个 UDP 端口是否开放,UDP 端口扫描比 TCP 扫描要复杂和不可靠,因为 UDP 没有像 TCP 那样的“三次握手”或“RST”包来明确表示端口关闭。
原理:
- 开放端口:如果端口开放,目标主机会返回一个 ICMP "端口不可达" 的错误消息(在某些系统上可能不返回任何消息)。
- 关闭/过滤的端口:如果端口关闭,目标主机会返回一个 ICMP "端口不可达" 消息,如果被防火墙过滤,则没有任何响应。
由于响应不明确,UDP 扫描的结果通常是不可靠的。-z 选项可以用来扫描而不发送任何数据。
示例:
# 扫描 192.168.1.100 的 161-163 端口(SNMP 常用端口) nc -uzv 192.168.1.100 161-163
-z: 表示扫描模式,只报告开放的端口,不发送数据或读取数据。-u: UDP 模式。-v: 详细输出,显示扫描过程。
输出可能如下:
nc: connect to 192.168.1.100 port 161 (udp) failed: Connection refused
nc: connect to 192.168.1.100 port 162 (udp) failed: Connection refused
nc: connect to 192.168.1.100 port 163 (udp) failed: Connection refused
注意:Connection refused 这个消息在某些系统上可能意味着端口是关闭的,但在另一些系统上也可能意味着被防火墙拦截了,不能完全依赖这个结果来判断端口是否开放。
实际应用案例:模拟 DNS 查询
DNS (Domain Name System) 是使用 UDP 协议的经典应用,我们可以用 nc 手动发送一个 DNS 查询请求。
-
获取 DNS 请求的二进制数据 我们需要一个 DNS 查询的原始数据包,通常可以从网络抓包(如使用
tcpdump或Wireshark)获取,或者使用dig命令生成并抓包,这里我们假设你已经有了一个dns_query.bin文件。 -
发送查询 使用
nc将这个二进制文件发送到 DNS 服务器的 53 端口。# 假设 DNS 服务器是 8.8.8.8 # 使用 -w 设置超时时间,因为 UDP 可能没有响应 nc -u -w 1 8.8.8.8 53 < dns_query.bin
-
接收响应 DNS 服务器会返回一个 DNS 响应,你可以将响应重定向到一个文件中,然后用
Wireshark或其他工具分析。nc -lu -p 5353 -w 1 > dns_response.bin
然后在另一个终端运行发送命令:
nc -u -w 1 8.8.8.8 53 < dns_query.bin
响应就会被保存到
dns_response.bin文件中。
nc 处理 UDP 的关键注意事项
- 无连接性:客户端不需要先“连接”到服务器,你可以在任何时候向任何 IP 和端口发送数据,即使那里没有任何人在监听。
- 无边界性:这是
nc处理 UDP 最大的挑战,如果你一次性发送大量数据,nc在另一端接收时可能会将它们全部读入一行,或者根据缓冲区大小进行分割,它无法知道一个“消息”在哪里结束,对于结构化协议(如 DNS),通常每个数据包是独立的,对于文本消息,可能需要约定分隔符(如换行符\n)。 - 不可靠性:发送的数据包可能会丢失、重复或乱序。
nc本身不会处理这些情况,如果你需要可靠性,必须在上层应用中实现确认和重传机制。 - 防火墙:UDP 端口很容易被防火墙过滤,如果你的
nc服务器无法接收数据,首先要检查防火墙是否阻止了相应端口的 UDP 流量。 - 超时:在进行 UDP 通信时,特别是扫描或等待响应时,建议使用
-w选项设置一个超时时间,否则nc可能会无限期地等待下去。nc -u -w 5 127.0.0.1 9999 # 等待 5 秒,如果没有数据连接,则退出
| 功能 | 命令 | 说明 |
|---|---|---|
| 启动 UDP 服务器 | nc -lu -p <port> |
在指定端口上监听并接收 UDP 数据。 |
| 启动 UDP 客户端 | nc -u <host> <port> |
向指定主机的端口发送 UDP 数据。 |
| 带超时的客户端 | nc -u -w <seconds> <host> <port> |
发送数据后等待指定秒数后超时退出。 |
| UDP 端口扫描 | nc -uzv <host> <port> |
尝试扫描 UDP 端口,结果不可靠。 |
| 发送文件内容 | cat <file> \| nc -u <host> <port> |
作为数据发送。 |
nc 是学习和测试 UDP 协议的绝佳工具,因为它简单直接,但在生产环境中,对于需要可靠性、复杂协议或高性能的场景,通常会使用更专业的库或应用程序。
