nc — 任意 TCP 和 UDP 连接以及监听
概要
nc [-46bCDdFhklNnrStUuvZz] [-I length] [-i interval] [-M ttl] [-m minttl] [-O length]
[-P proxy_username] [-p source_port] [-q seconds] [-s sourceaddr] [-T keyword] [-V rtable]
[-W recvlimit] [-w timeout] [-X proxy_protocol] [-x proxy_address[:port]] [destination] [port]
描述
nc(或 netcat)实用程序可用于处理涉及 TCP、UDP 或 Unix 域套接字的几乎所有内容。它可以打开 TCP 连接、发送 UDP 数据包、监听任意 TCP 和 UDP 端口、执行端口扫描,并处理 IPv4 和 IPv6。与 telnet(1) 不同,nc 可以很好地用于脚本编写,并且将错误消息发送到标准错误,而不是像 telnet(1) 在某些情况下那样发送到标准输出。
常见用途包括:
简单的 TCP 代理
基于 shell 脚本的 HTTP 客户端和服务器
网络守护程序测试
作为 [ssh]({filename}../../ssh)(1) 的 SOCKS 或 HTTP ProxyCommand
以及更多
选项如下:
-4 仅使用 IPv4 地址。
-6 仅使用 IPv6 地址。
-b 允许广播。
-C 将 CRLF 作为行尾。输入数据中的每个换行符(LF)字符在写入套接字之前,都会被转换为 CR+LF。如果换行符已经有一个回车符(CR),则不会进行转换。接收到的数据不受影响。
-D 启用套接字的调试。
-d 不要尝试从标准输入读取。
-F 通过 sendmsg(2) 将第一个连接的套接字传递到标准输出,然后退出。这在使用 -X 选项时非常有用,可以使 nc 执行连接设置,然后将其余连接交给另一个程序(例如,使用 ssh_config(5) ProxyUseFdpass 选项的 [ssh]({filename}../../ssh)(1))。不能与 -U 一起使用。
-h 打印 nc 帮助文本并退出。
-I length
指定 TCP 接收缓冲区的尺寸。
-i interval
在发送和接收的文本行之间休眠指定的秒数。还会导致连接到多个端口之间产生延迟。
-k 当连接完成时,监听另一个连接。需要 -l。与 -u 选项一起使用时,服务器套接字不会连接,并且可以从多个主机接收 UDP 数据报。
-l 监听传入连接,而不是启动到远程主机的连接。可以指定要监听的目的地和端口,方法是使用非可选参数,或使用 -s 和 -p 选项。不能与 -x 或 -z 一起使用。此外,使用 -w 选项指定的任何超时都将被忽略。
-M ttl 设置传出数据包的 TTL/跃点限制。
-m minttl
要求内核丢弃 TTL/跃点限制低于 minttl 的传入数据包。
-N [shutdown]({filename}../../shutdown)(2) 在输入流结束时关闭网络套接字。某些服务器需要这样做才能完成其操作。
-n 不执行域名解析。如果无法通过 DNS 解析名称,则会报告错误。
-O length
指定 TCP 发送缓冲区的大小。
-P proxy_username
指定要提供给需要身份验证的代理服务器的用户名。如果未指定用户名,则不会尝试身份验证。目前,代理身份验证仅支持 HTTP CONNECT 代理。
-p source_port
指定 nc 应使用的源端口,这受到权限限制和可用性的限制。
-q seconds
在标准输入流结束时,等待指定的秒数,然后退出。如果秒数为负数,则永久等待(默认)。指定一个非负的秒数意味着启用了 -N 选项。
-r 在范围内或系统分配它们的顺序中,随机选择源和/或目标端口,而不是按顺序选择。
-S 启用 RFC 2385 TCP MD5 签名选项。
-s sourceaddr
设置用于发送数据包的源地址,这在具有多个接口的机器上很有用。对于 Unix 域数据报套接字,指定要创建和使用的本地临时套接字文件,以便可以接收数据报。不能与 -x 选项一起使用。
-T keyword
更改 IPv4 TOS/IPv6 流量类值。keyword 可以是 critical、inetcontrol、lowcost、lowdelay、netcontrol、throughput、reliability 中的一个,也可以是以下 DiffServ 代码点之一:ef、af11 ... af43、cs0 ... cs7;或者是一个十六进制或十进制数。
-t 发送 RFC 854 DON'T 和 WON'T 响应,以响应 RFC 854 DO 和 WILL 请求。这使得可以使用 nc 脚本化 telnet 会话。
-U 使用 Unix 域套接字。不能与 -F 或 -x 选项一起使用。在 Linux 上,如果名称以“@”符号开头,则将其视为抽象命名空间套接字:在绑定或连接之前,将前导“@”替换为 NUL 字节。有关详细信息,请参阅 unix(7)。
-u 使用 UDP 而不是 TCP。不能与 -x 选项一起使用。对于 Unix 域套接字,使用数据报套接字而不是流套接字。如果使用 Unix 域套接字,则会在 /tmp 中创建一个临时接收套接字,除非提供了 -s 标志。
-V rtable
设置要使用的路由表。
-v 生成更详细的输出。
-W recvlimit
在从网络接收到 recvlimit 个数据包后终止。
-w timeout
无法建立或空闲的连接将在 timeout 秒后超时。-w 标志对 -l 选项没有影响,即 nc 将永久侦听连接,无论是否使用 -w 标志。默认情况下没有超时。
-X proxy_protocol
在使用代理服务器时,使用 proxy_protocol。支持的协议包括 4(SOCKS 4,4A(SOCKS v.4A),5(SOCKS v.5)和 connect(HTTPS 代理)。如果未指定协议,则使用 SOCKS 版本 5。请注意,SOCKS v.4 协议非常有限,只能在目标主机可以解析为 IPv4 地址时使用。其他协议将目标作为字符串传递给远程代理进行解释,并且没有此限制。
-x proxy_address[:port]
使用位于 proxy_address 和端口处的代理连接到目标。如果未指定端口,则使用代理协议的知名端口(SOCKS 为 1080,HTTPS 为 3128)。可以通过将 proxy_address 括在方括号中来指定 IPv6 地址。代理不能与 -lsuU 中的任何选项一起使用。
-Z DCCP 模式。
-z 仅扫描正在侦听的守护进程,而不向其发送任何数据。不能与 -l 一起使用。
destination 可以是数字 IP 地址或符号主机名(除非给定了 -n 选项)。通常,必须指定一个目标,除非给定了 -l 选项(在这种情况下,使用本地主机)。对于 Unix 域套接字,需要一个目标,并且是连接的套接字路径(或者如果给定了 -l 选项,则是用于侦听的套接字路径)。
端口可以指定为数字端口号或服务名称。端口范围可以指定为数字端口号,格式为 nn-mm。通常,必须指定目标端口,除非给定了 -U 选项。对于某些选项,值 0 请求系统选择端口号。
客户端/服务器模型
使用 nc 构建一个非常基本的客户端/服务器模型非常简单。在一个控制台中,启动 nc 以侦听特定端口的连接。例如:
$ nc -l 1234
现在,nc 正在监听端口 1234 以等待连接。在第二个控制台(或第二台机器)上,连接到正在侦听的机器和端口:
$ nc -N 127.0.0.1 1234
现在应该在端口之间建立连接。在第二个控制台中键入的任何内容都将连接到第一个控制台,反之亦然。连接建立后,nc 实际上并不关心哪一侧用作“服务器”,哪一侧用作“客户端”。可以使用 EOF(“^D”)终止连接,因为给定了 -N 标志。
这里没有 -c 或 -e 选项,但你仍然可以通过重定向文件描述符来在建立连接后执行命令。请小心,因为打开一个端口并让任何人连接到你的站点并执行任意命令是危险的。如果你真的需要这样做,这里有一个例子:
在“服务器”端:
$ rm -f /tmp/f; mkfifo /tmp/f
$ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f
在“客户端”端:
通过执行此操作,您会在 /tmp/f 创建一个 FIFO,并使 nc 在地址 127.0.0.1 的端口 1234 上侦听。 在“客户端”成功建立到该端口的连接后,“服务器”端将执行 /bin/sh,并向“客户端”端提供 shell 提示符。
当连接终止时,nc 也会退出。如果您希望它继续侦听,请使用 -k,但如果命令退出,此选项不会重新启动它或使 nc 保持运行。此外,请不要忘记在不再需要时删除文件描述符:
$ rm -f /tmp/f
数据传输
上一节中的示例可以扩展为构建一个基本的数据传输模型。任何输入到连接一端的都会输出到另一端,并且输入和输出可以很容易地捕获,以便模拟文件传输。
首先,使用 nc 侦听特定端口,并将输出捕获到文件中:
$ nc -l 1234 > filename.out
使用第二台机器,连接到侦听 nc 进程,并向其提供要传输的文件:
$ nc -N host.example.com 1234 < filename.in
文件传输完成后,连接将自动关闭。
与服务器通信
有时,直接与服务器通信而不是通过用户界面会很有用。这可以帮助进行故障排除,在这种情况下,可能需要验证服务器在响应客户端发出的命令时发送的数据。例如,要检索网站的主页:
$ printf "GET / HTTP/1.0\r\n\r\n" | nc host.example.com 80
请注意,这也会显示 Web 服务器发送的标头。如果需要,可以使用 sed(1) 之类的工具对其进行过滤。
当用户知道服务器所需的请求格式时,可以构建更复杂的示例。例如,可以使用以下命令将电子邮件提交到 SMTP 服务器:
$ nc [-C] localhost 25 << EOF
HELO host.example.com
MAIL FROM:<_>
RCPT TO:<_>
DATA
电子邮件正文。 . QUIT EOF
端口扫描
了解目标机器上哪些端口是打开的并且正在运行服务可能是有用的。可以使用 -z 标志来告诉 nc 报告打开的端口,而不是发起连接。通常,最好将详细输出设置为 stderr,方法是将此选项与 -v 选项一起使用。
例如:
$ nc -zv host.example.com 20-30
Connection to host.example.com 22 port [tcp/ssh] succeeded! Connection to host.example.com 25 port [tcp/smtp] succeeded!
端口范围指定为将搜索限制为端口 20-30,并且按递增顺序扫描(除非设置了 -r 标志)。
您还可以指定要扫描的端口列表,例如:
$ nc -zv host.example.com http 20 22-23
nc: connect to host.example.com 80 (tcp) failed: Connection refused
nc: connect to host.example.com 20 (tcp) failed: Connection refused
Connection to host.example.com port [tcp/ssh] succeeded! nc: connect to host.example.com 23 (tcp) failed: Connection refused
端口按您指定的顺序进行扫描(除非设置了 -r 标志)。
或者,了解正在运行的服务器软件及其版本可能很有用。 此信息通常包含在问候横幅中。 为了检索这些信息,首先需要建立连接,然后在检索到横幅后中断连接。 这可以通过使用 -w 标志指定较小的超时时间来实现,或者可以通过向服务器发送“QUIT”命令来实现:
$ echo "QUIT" | nc host.example.com 20-30
SSH-1.99-OpenSSH_3.6.1p2
Protocol mismatch.
220host.example.com IMS SMTP Receiver Version 0.84 Ready
示例
打开到 host.example.com 的 42 端口的 TCP 连接,使用 31337 作为源端口,超时时间为 5 秒:
$ nc -p 31337 -w 5 host.example.com 42
打开到 host.example.com 的 53 端口的 UDP 连接:
$ nc -u host.example.com 53
打开到 host.example.com 的 42 端口的 TCP 连接,使用 10.1.2.3 作为本地连接的 IP 地址:
$ nc -s 10.1.2.3 host.example.com 42
创建并侦听 Unix 域流套接字:
$ nc -lU /var/tmp/dsocket
通过位于 10.2.3.4 的 8080 端口的 HTTP 代理连接到 host.example.com 的 42 端口。 此示例也可以由 ssh(1) 使用;有关更多信息,请参阅 ssh_config(5) 中的 ProxyCommand 指令。
$ nc -x10.2.3.4:8080 -Xconnect host.example.com 42
相同的示例,这次启用代理身份验证,如果代理需要,则使用用户名“ruser”:
$ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42
参见
作者
原始实现:*Hobbit* <_>。 由 Eric Jackson <_> 重写,添加了 IPv6 支持。 由 Aron Xu ⟨_⟩ 修改,用于 Debian 端口。
注意事项
使用 -uz 标志组合进行 UDP 端口扫描,无论目标机器的状态如何,始终会报告成功。 但是,与目标机器或中间设备上的流量捕获器结合使用,-uz 标志组合可用于通信诊断。 请注意,由于硬件资源和/或配置设置,生成的 UDP 流量量可能会受到限制。