netcat 号称 TCP/IP 的瑞士军刀,以体积小(可执行文件约 200KB)、功能灵活著称,各大发行版默认安装。netcat 主要有 GNU 版本和 OpenBSD 版本,两者在 debian/ubuntu 下均可安装(Windows 下只有 GNU 版本)。
检查版本
readlink -f $(which nc)
结果会有两种:
/bin/nc.traditional:默认 GNU 基础版本,一般系统自带;/bin/nc.openbsd:openbsd 版本,功能强大很多。
可用 apt-get install nc-traditional 或 apt-get install nc-openbsd 选择安装。GNU 与 OpenBSD 版本都有新老区别——老版本传文件时 stdin 遇 EOF 会自动断开,新版本则会一直保持连接(两年前 debian jessie 统一升级后,网上教程几乎同时失效)。下文以最新 GNU 版本为主,对照 OpenBSD 版本说明。
端口测试
服务器 A(192.168.1.2)的 8080 端口启动了服务,想在 B 主机上检测端口是否可达:
nc -vz 192.168.1.2 8080
-v 显示更多信息(verbose),-z 不发送数据。连不上就检查网络和安全设置,连得上再去查服务日志。端口可写成范围扫描:
nc -v -v -w3 -z 192.168.1.2 8080-8083
两次 -v 报告更详细,-w3 设置 3 秒超时。
传输测试
配置了 iptables/安全组策略(只开放 8080),想验证设置是否生效。在 A 主机监听:
nc -l -p 8080
B 主机连接:
nc 192.168.1.2 8080
两边即可会话。注意:OpenBSD 版本 -l 后可省略 -p(写成 nc -l 8080),但 GNU netcat 无法运行,所以推荐都加上 -p,两版本通用。老版本 Ctrl+D 发 EOF 即断开,新版本要 Ctrl+C 结束;OpenBSD 版本可用 -k 让服务端持续工作。
测试 UDP 会话
两台主机 UDP 不通时,先用 netcat 确认 UDP 可达。A 主机:
nc -u -l -p 8080
B 主机:
nc -u 192.168.1.2 8080
文件传输
A 主机接收:
nc -l -p 8080 > image.jpg
B 主机发送:
nc 192.168.1.2 8080 < image.jpg
netcat 即”通过网络 cat 过去”。老版本在文件结束(stdin 遇 EOF)时发送端会关闭连接,新版本不会,需另开窗口比较接收文件尺寸判断是否传完。新版 OpenBSD 的 -N 参数可让 stdin 遇 EOF 就关闭连接(与老版本一致):
/bin/nc.openbsd -N 192.168.1.2 8080 < image.jpg
GNU 版本的 -q0 参数可达到同样效果:
/bin/nc.traditional -q0 192.168.1.2 8080 < image.jpg
搭配 tar 还可传输整个目录。
网速吞吐量测试
方法一(GNU 版):A 主机监听:
/bin/nc.traditional -v -v -n -l -p 8080 > /dev/null
B 主机:
time nc -n 192.168.1.2 8080 < /dev/zero
执行约十秒后 Ctrl+C 结束,A 主机显示接收字节数,除以 time 时间即得吞吐量。注意 GNU netcat 统计值是 32 位 int,传输过多会溢出为负数。
方法二(OpenBSD 版):A 主机:
nc -l -p 8080 > /dev/null
B 主机:
dd if=/dev/zero bs=1MB count=100 | /bin/nc.openbsd -n -N 192.168.1.2 8080
等效 GNU 版:
dd if=/dev/zero bs=1MB count=100 | /bin/nc.traditional -n -q0 192.168.1.2 8080
方法三(最精确):搭配 pv 命令实时统计带宽。A 主机:
nc -l -p 8080 | pv
B 主机:
nc 192.168.1.2 8080 < /dev/zero
pv 会输出实时带宽:
353MiB 0:00:15 [22.4MiB/s] [ <=> ]
前两种方法都把握手时间和 TCP 慢启动时间算进去了,pv 方式最准确。
系统后门
假设 A 主机很原始(无包管理、sshd/telnetd 都跑不起来),想从 B 主机网络登录。GNU netcat 的 -e 参数可在连接建立时执行程序并重定向其标准 IO:
/bin/nc.traditional -l -p 8080 -e /bin/bash
B 主机:
nc 192.168.1.2 8080
即可登录 A 主机 shell。OpenBSD 版本删除了 -e,可用管道实现:
mkfifo /tmp/f
cat /tmp/f | /bin/bash 2>&1 | /bin/nc.openbsd -l -p 8080 > /tmp/f
用完后删除 /tmp/f。
结语
netcat 可以直接操作 tcp/udp 进行监听、连接、数据传输,搭配管道可灵活实现各种网络测试。还有很多用法:用 netcat + shell 写 http 服务器、用 fifo 搭配两层 nc 做端口转发、搭配 openssl 把 ssl 套接字解码映射为裸 socket 端口等。