netcat
netcat具有“网络瑞士军刀“之称,支持从命令行跨网络读取和写入数据。
netcat 有 GNU 版本和 OpenBSD版本。两者都可以在 Linux下面安装,但是 Windows 下面只有 GNU 版本。 不管是 GNU 版本还是 OpenBSD 版本,都有新老的区别,主要是传送文件时 stdin 发生 EOF 了,老版本会自动断开,而新的 gnu/openbsd 还会一直连着 。
NcatNmap项目套件中有一个ncat程序。Ncat最初是用来支持Nmap而开发的,是对古老的Netcat重新实现的一个大大改进。它与netcat类似,使用TCP和UDP进行通信,可为其他应用程序和用户提供网络连接。这三个版本功能类似,都简称nc。
readlink -f $(which nc)
查看nc版本。两个版本在使用时常用功能区别不大,如果遇到什么问题,查看系统自带手册(网上教程、博客可能不准)。
软件使用思路
netcat 可以操作 tcp/udp 进行原始的监听、连接、数据传输等工作。然后搭配管道,实现灵活多样的功能,或者进行各种网络测试。 下面是nc常用功能。
端口测试
测试端口第一个想到的是telnet,但是有一定局限性:telnet不一定安装,需要有额外主机测试。
使用nc可以在本机测试端口是否监听nc -l -p port
。如果报端口已占用,表示端口已经监听。
本机端口已监听,如果还以网络不通,可在第二台主机上执行nc -vz ip port
。v 表示verbose,显示多点信息。z 表示不发送数据。
nc 命令后面的 8080 可以写成一个范围进行扫描: nc -v -v -w3 -z ip port1-port2
。两次 v 会显示更详细的内容,w3是设置扫描超时时间为3秒。
传输测试
在A主机(192.168.1.2)上执行nc -l -p 8080
,开始监听本地8080端口。然后在B主机上连接A:nc 192.168.1.2 8080
。 两边就可以会话了,随便输入点什么按回车,另外一边应该会显示出来 。
openbsd 版本 netcat 用了 -l
以后可以省略 -p
参数,写做:nc -l 8080
,但在 GNU netcat 下面无法运行,所以推荐写法是加上 -p
参数,两个版本都通用。 老版本的 nc 只要 CTRL+D 发送 EOF 就会断开,新版本一律要 CTRL+C 结束,不管是服务端还是客户端只要任意一边断开了,另一端也就结束了,但是 openbsd 版本的 nc 可以加一个 -k 参数让服务端持续工作。
测试UDP
排查两台主机 UDP 数据发送不通问题。在A主机(192.168.1.2)上执行nc -u -l -p 8080
,监听udp的8080端口。然后B主机测试连接nc -u 192.168.1.2 8080
。
类似上面测试,看看一边输入消息另外一边能否收到,收得到的话可能是你自己的服务原因,收不到的话,检查网关、防火墙等配置。
文件传输
两台服务器传输文件,可以用scp、szrz,也可以安装FTP服务,甚至可以动手用Python实现http上传。用nc也可以轻松实现。
在A主机(192.168.1.2)上监听端口nc -l -p 8080 > image.jpg
。然后在B主机上发送文件 nc 192.168.1.2 8080 < image.jpg
。
注意,老版本 GNU / OpenBSD 的 netcat 再文件结束(标准输入碰到 EOF),发送文件一端就会关闭连接,而新版本不会,需要验证传输文件和源文件是否大小一致。openbsd版可以使用-N
参数,指明stdin遇到EOF就关闭连接(完成传输),GNU版本可以用-q0
参数。
nc进行文件传输,在极端环境下很有用。
网速吞吐量测试
GNU版本使用-v -v
参数,在结束时会统计接受和发送的字节。
在A主机(192.168.1.2)上监听8080 nc -v -v -n -l -p 8080 > /dev/null
。-n是不要解析域名,避免解析域名造成时间误差。然后在B主机上执行 time nc -n 192.168.1.2 8080 < /dev/zero
。执行一段时间后 CTRL+C 结束,就可以在A主机上查看字节数,在根据B主机的时长就可以计算。
对于 OpenBSD 版本的 nc 我们可以用管道搭配 dd 命令进行统计,服务端运行:
nc -l -p 8080 > /dev/null
客户端运行 dd 搭配 nc,结束以后会有结果出来:
dd if=/dev/zero bs=1MB count=100 | /bin/nc.openbsd -n -N 192.168.1.2 8080
其实上面两种方法都把建立连接的握手时间以及 TCP 窗口慢启动的时间给计算进去了,不是特别精确,最精确的方式是搭配 pv 命令(监控统计管道数据的速度),在 A 主机运行:
nc -l -p 8080 | pv
然后再 B 主机运行:
nc 192.168.1.2 8080 < /dev/zero
此时 A 主机那端持续收到 B 主机发送过来的数据并通过管道投递给 pv 命令后,你就能看到实时的带宽统计了,pv 会输出一个实时状态:
353MiB 0:00:15 [22.4MiB/s] [ <=> ]
让你看到最新的带宽吞吐量,这是最准确的吞吐量测试方法,在不需要 iperf 的情况下,直接使用 nc 就能得到一个准确的数据。
系统后门
假设A 主机十分原始,包管理系统都没有,sshd/telnetd 都跑不起来,这时候可以用nc 来实现B 主机通过网络登录 A 主机。
GNU 版本的 netcat 有一个 -e 参数,可以在连接建立的时候执行一个程序,并把它的标准输入输出重定向到网络连接上来,于是我们可以在 A 主机上 -e 一下 bash:
/bin/nc.traditional -l -p 8080 -e /bin/bash
按回车打开系统后门,然后再 B 主机那里照常:
nc 192.168.1.2 8080
你就可以在 B 主机上登录 A 主机的 shell 了,操作完成 CTRL+C 结束。
对于 openbsd 版本的 netcat,-e 命令被删除了,没关系,我们可以用管道来完成,和刚才一样,在 A 主机上:
mkfifo /tmp/fcat /tmp/f | /bin/bash 2>&1 | /bin/nc.openbsd -l -p 8080 > /tmp/f
然后 B 主机和刚才一样:
nc 192.168.1.2 8080
即可访问,用完注意将 /tmp/f
这个 fifo 文件删除。
还有很多用途
还有很多其他用法,比如可以用 netcat + shell script 写一个 http 服务器,使用 fifo 搭配两层 nc 可以实现 tcp 端口转发,搭配 openssl 命令行工具和 nc 加管道可以把 ssl 的套接字解码并映射成裸的 socket 端口供没有 ssl 功能的工具访问。 这些功能比较考验基本能力,可能有些复杂,可以在极端恶劣环境下使用,平时用专用软件很容易实现。