nc的用法

最早接触到这个命令是在18年12月,和同学聊天的时候聊到了这个命令,但是我不知道这个命令,被他一通鄙视…当时就去简单看了一下,现在过了一年了,打算在这篇博客里面好好整理一下。

总体介绍

ncnetcat 的缩写, 它是类unix系统下一个功能强大的命令行网络工具,被用来在两台主机之间建立TCP或者 UDP连接,并能够通过标准输入输出进行读和写,日常可以配合管道符来进行重定向使用。

我在我的ubuntu下面看到nc其实是一个软连接,分别是/bin/nc -> /etc/alternatives/nc -> /bin/nc.openbsd,而在centos下面则是/usr/bin/nc -> /etc/alternatives/nmap -> /usr/bin/ncat,但是不论在哪里,你都可以使用nc来执行。

选项介绍

  • -p source_port:指定nc与远程主机建立连接的源端口;如果不指定此选项,则随机指定一个可用的端口
  • -s source_ip_address:指定nc与远程主机建立连接的IP,如果不使用此选项,默认为使用0.0.0.0
  • -u:指定使用的UDP协议;如果不使用此选项,默认为使用TCP协议
  • -w:指定超时时间,单位是秒。不指定的话nc默认是会永久监听连接
  • -l [ip]:port:监听端口port,相当于在本机启动了一个服务;其中ip是可选的,如果不指定,默认为 0.0.0.0
  • -v:显示详细信息,一般都会带这个选项
  • 更多的选项等到用到的时候再介绍

建立tcp连接

比如与某一个网站的80端口建立链接:

1
nc example.com 80

这个时候你就能和监听example.com这个网站的服务器的80端口的程序进行通信了,而这个一般是一个网页,所以直接输入:GET / HTTP/1.0,再敲两下回车,就能看到首页的返回信息了。之前也说到了nc是可以使用管道符来进行输入的,所以其实我们可以直接:

1
echo "GET / HTTP/1.0\r\n\r\n" | nc www.baidu.com 80

就可以得到百度的首页的html代码了。

如果想要建立udp连接只需要加上-u即可。

一旦连接上两台机器,你在一台机器上输入任何的数据都会被传送到另外一台上面,反之同理。所以你其实是可以发送数据给服务器,只是它不理你而已。一般来说^D发送的EOF即可终止会话。

端口扫描

这个功能其实我以前一直使用nmap,但是nmap不太方便。

nc就比较方便,比如需要扫描某台主机的80端口是否开放:

1
nc example.com -v -z 80

简单的tcp服务器

只需要让nc监听本机的某一个端口就行了。

1
nc -l 34567

然后另外一台机器只需要正常建立TCP链接即可。

简单的FTP服务器

其实不应该说是FTP服务器,而是文件传输比较合理一点。上面介绍了能够建立tcp服务器,那么我们只需要把某一个文件通过重定向发送过去,另外一端进行接收即可,这里注意一下首先需要在接收端监听,否则发送端就直接发送过去了而接受不到。

接收端:nc -l 34567 > file.txt

发送端:nc target_ip 34567 < file.txt,可以加上-N这个选项来让服务器遇到EOF的时候关闭socket连接。

如果需要传输文件夹,那就需要配合tar命令。(当然你也可以把文件夹压缩成一个文件然后按照文件来进行传输)

发送端:tar -cvf - 文件夹名字 | nc -l 34567

接收端:nc 发送端的ip 34567 | tar xvf -

上面的可能有点难理解,为什么是先发送端然后再是接收端,而且为什么发送文件是接收端监听而发送文件夹是发送端监听的呢?

首先发送端会压缩文件并输出到标准输出中(就是那个-),通过管道重定向发送给nc监听的端口。接收端则是问发送端索要,然后再重新解压。

这两种文件的发送方式其实是本质上是一样的,一个是接收端准备好接受了,发送端直接发过去,另外一个是发送端把自己的数据发给nc,然后接受方来取。只需要牢记一点即可:先nc -l准备好数据,这样就不会错。

使用代理

我没想到这么小一个玩意儿里面居然实现了http代理、socks4/5。使用的方法也很简单:

1
2
nc -x 127.0.0.1:1080 www.baidu.com 80
这里假设本地有socks5的代理,端口号为1080
  • -x:指定代理服务器的ip和端口
  • -X:指定所使用的协议,socks4=4socks5=5https=connect,默认是socks5

还有可以配合ssh使用,只需要在config文件中写入ProxyCommand nc -v -x 127.0.0.1:1080 %h %p,其中%h会被目标主机名字代替,而%p会被端口号代替,这样就刚好完美符合nc的规则。

SHELL

首先不同的nc版本对这个支持的不太一样,像我用的centos7的就支持-e command这种选项,但是ubuntu上的nc就不支持。所以这里打算介绍一种比较通用的方法:

被控端:

1
2
rm -f /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc -l 1234 > /tmp/f

控制端:

1
nc host.example.com 1234

这里可能会对这个mkfifo这个命令有点陌生,这个命令是用来创造命名管道的,如果你用ll /tmp/f来查看这个文件的话,会发现它的第一位是p,就是pipe管道的意思。

补充

怕有人不太了解,这里介绍下nc所工作的层。之前有说到nc默认是用tcp进行连接的,而一个数据包的结构是这样子的:

1
IP头   |  TCP头  |  你输入的内容

你可以理解为nc会为你自动加上ip头部tcp头部,让你只需要关注内容就行。