早些时候了解过nc,但是那时候还没有博客,今天来专门做个记录对于这把鼎鼎大名的网络瑞士军刀——netcat。
以下内容主要转载 编程随想
以下内容主要参考 编程随想
以下内容主要参考 编程随想
NC(netcat)被称为网络工具中的瑞士军刀,体积小巧,但功能强大。
它诞生于1995年,在网络安全社区的名气很大(就如同 AK47 在军事领域的名气)。长期在安全圈内混的人,应该都知道它。想当年,insecure.org 网站在本世纪初搞过几次“年度投票”,评选优秀的安全工具。每次投票,netcat 都能排进前几名。
简而言之,nc 是一个【命令行】工具,能够让你很方便、很灵活地地操纵【传输层协议】(TCP & UDP)。
考虑到本文的读者中,有些是技术菜鸟,稍微普及一个小知识:
==================== 华丽的分割线========================
在谈到“网络协议分层”这个话题时,有一个大名鼎鼎的“OSI 7层模型”。这个模型相当牛逼,任何一种具体的网络协议实现,都可以套用其中。
在如今这个互联网时代,大伙儿经常听说的“TCP/IP 协议”以及周边的协议,也可以套用到“OSI 7层模型”之上。大致如下:
比如:HTTP、DNS、FTP、SMTP、POP3、SSH ……
与用户直接打交道的,大都在这层)
PPTP(常用于:VPN)
命名管道(常用于:进程间通讯)
NetBIOS
UDP(数据报协议)
ICMP(互联网控制消息协议)
IGMP(互联网组管理协议)
IPSec(常用于:VPN)
ARP & RARP(MAC 地址的解析与反向解析)
SLIP、PPP、PPPoE(常用于:拨号上网)
L2TP(常用于:VPN)
蓝牙协议
RS-232(串口标准协议)
===================== 华丽的分割线 ==============================
基于上述“小知识”,当你听到“IP 地址”这个词的时候,指的是“OSI 第3层”;相应的,“MAC 地址”指的是“OSI 第2层”。
由于 nc 是如此牛逼,而它本身又很小(不但软件很小,源代码也很少)。很容易就衍生出一大堆【变种】。不同的变种,会在原有 nc 的基础上增加一些新功能。
由于变种之间存在差异。在本文的开头部分,有必要先声明一下:这篇教程的内容,主要基于 OpenBSD 社区的变种(也叫“OpenBSD netcat”或“netcat-openbsd”)
顾名思义,这是由 OpenBSD 社区重写的 netcat,主要增加了对“IPv6、proxy、Unix sockets”等功能的支持。另外,在细节上也有若干完善。
虽然它出自 OpenBSD 社区,但很多主流 Linux 发行版的官方软件仓库已包含这个变种(比如说:Debian 家族、Arch 家族、openSUSE 家族、Gentoo 家族……)。
“OpenBSD netcat”官网的帮助页面在“这里”,其官方代码仓库在“这里”。截止写本文时,其版本为 1.206,上个月刚更新(看 commit history,更新还挺勤快滴)
为了打字省力,本文后续部分提到的 nc,除非专门注明,否则都是指:netcat 的 OpenBSD 变种。如果要称呼原始的那个 netcat,会称之为“原版 nc”(洋文叫做“traditional netcat”)。
Windows下可以使用我找的这个安装包
链接:https://pan.baidu.com/s/164vN_WkA6AaWnJqEoDCjmA
提取码:31zs
Linux下请使用命令安装
这里有个坑,参考文章。
很多朋友会发现自己的Linux主机自带这 nc 工具,其实这是两个工具,现在的nc,并不是netcat的nc:
nc与netcat是一个玩意儿,ncat是nmap下面的一个玩意儿,是一个组件
首先我们安装真正的nc,参考文章
1.下载
下载地址:http://sourceforge.net/projects/netcat/files/netcat/0.7.1/(下载的是netcat-0.7.1.tar.gz版本)
2.解压:
tar -zxvf netcat-0.7.1.tar.gz -C /usr/local
3.改名:
cd /usr/local
mv netcat-0.7.1 netcat
4.安装
切换目录:cd /usr/local/netcat
配置,把文件存放在/opt/netcat下,删除时,卸载软件时,只要删除这个文件就行了:
https://blog.csdn.net/m0_46378049/article/details/configure –prefix=/opt/netcat
编译:make
安装:make install
5.配置
vim /etc/profile
添加以下内容:
# set netcat path
export NETCAT_HOME=/opt/netcat
export PATH=$PATH:$NETCAT_HOME/bin
保存,退出,并使配置生效:
source /etc/profile
然后,我们替换现在的假nc(nmap的组件)为真正的nc(netcat)
首先先确定有真正的nc(/usr/bin/nc 这个nc只是一个软链接,即快捷方式)
删除原软链接,重建
rm /usr/bin/nc
ln -s /opt/netcat/bin/nc /usr/bin/nc
使用–help查看nc命令是否已经改为netcat了(同理也可以将/usr/bin/netcat中的链接指向nc)
nc –help
要使用 nc,你就需要在【命令行】中与它打交道(它所有的功能,都以命令行的方式呈现给你用)。
一般来说,nc 的命令行包括如下几个部分:
nc 命令选项 主机 端口
- 命令选项
这部分可能包含 0~N 个选项
(注:这部分最复杂,下一个小节单独聊) - 主机
这部分可能没有,可能以“点分十进制”形式表示,也可能以“域名”形式表示。 - 端口
这部分可能没有,可能是单个端口,可能是端口范围。
对于“端口范围”,以两个数字分别表示“开始和结束”,中间以【半角减号】相连。举例:
简单来说,nc 提供了一大堆【命令行选项】,分别对应它提供的功能。每个选项都是“单字母”滴。有些选项需要带【选项值】,有些不需要。
你要使用的选项都放在 这个命令之后,每个选项前面要有一个【半角减号】,选项之间以空格分开。
举例:
在下面这个例子中,分别用到了三个选项(),其中 是选项 所带的【选项值】。nc -l -p 12345 -v
如果你的系统中已经有 nc(且 nc 已添加到【PATH 环境变量】),在命令行中执行如下,就可以看到它支持的全部命令选项的列表。
nc -h
顺便说一下:在上述命令的输出中,如果第一行包含 这个单词,就说明你当前用的“网猫”是 OpenBSD 变种。
注:建议新手多用该选项,出错时帮你诊断问题
注:如果“主机”是“点分格式”的 IP 地址,需要用该选项;
如果“主机”是“域名”形式,【不能】用该选项
注:如不加该选项,nc 默认作为客户端
注:如不加该选项,默认是 TCP 协议
注:该选项仅用于“端口扫描”,后面会聊到
注:“原版 nc”的该选项用来开启“TCP keepalive”
这是“原版 nc”与“OpenBSD 变种”之间的差异之一
注:“原版 nc”【没有】该选项。这是“原版 nc”与“OpenBSD 变种”之间的差异之一
注:“原版 nc”【没有】该选项。这是“原版 nc”与“OpenBSD 变种”之间的差异之一
注:通常用该选项开启一个网络后门
“OpenBSD 变种”基于安全考虑,已去掉该选项,
但还是能用间接的方式达到同样的效果 🙂
汇总上述表格,只是用来【速查】
有时候要同时用到多个选项,可以“合写在一起”,在前面共用一个【半角减号】。
还拿刚才俺举的例子,以下几种写法是【等价】滴。
nc -lp 12345 -v nc -l -v -p 12345 nc -lv -p 12345 nc -lvp 12345
一般来说,在命令行环境下,你可以用【Ctrl C】这个组合键来强行终止当前运行的进程。
对 nc,你同样可以这么干。
情景说明
经常有这种需求,要判断某个主机的监听端口是否能连上。
导致监听端口【无法】,通常有两种原因:
其一,这个监听端口根本就【没开启】;
其二,监听端口虽然开启,但是被防火墙阻拦了。
- 对第1个原因,(如果你能在该主机上运行命令)可以直接用 这个命令查看监听端口是否开启
- 对于第2个原因, 就用不上了。这时候就可以用 nc 来帮你搞定。
方法
用如下命令可以测试某个 IP 地址()上的某个监听端口()是否开启。
nc -nv x.x.x.x xx
上述命令用到了如下几个选项:
选项
如果你是 nc 的新手,建议总是带上这个选项——通过更详细的输出,能帮你搞明白状况。
选项
由于测试的是【IP 地址】,用该选项告诉 nc,【无须】进行域名(DNS)解析;
反之,如果你要测试的主机是基于【域名】,就【不能】用“选项 -n”。
补充
- 超时设置 在测试链接的时候,如果你没使用 这个超时选项,默认情况下 nc 会等待很久,然后才告诉你连接失败。如果你所处的网络环境稳定且高速(比如:局域网内),那么,你可以追加“ 选项”,设置一个比较小的超时值。在下面的例子中,超时值设为3秒。
nc -nv -w 3 x.x.x.x xx
- UDP 通常情况下,要测试的端口都是 TCP 协议的端口;如果你碰到特殊情况,需要测试某个 UDP 的端口是否可达。nc 同样能胜任。只需要追加 选项。
情景说明
前一个章节(招数1)的场景是——已经有某个网络软件开启了监听端口,然后用 nc 测试端口是否可达。
现在换另一个场景:
假设你正在配置防火墙规则,禁止 TCP 的 端口对外监听。那么,你如何【验证】自己的配置是 OK 滴?
更进一步说:如果当前【没有】任何软件开启 这个监听端口,你如何判断:该端口号是否会被防火墙阻拦?
为了叙述方便,设想如下场景:
有两台主机——“主机C”充当客户端,“主机S”充当服务端。
然后要判断“主机S”上的防火墙是否会拦截其它主机对 TCP 端口的连接。
方法
在“主机S”上运行 nc,让它在 8080 端口,命令如下:
nc -lv -p 8080
- 选项
这个选项会让 nc 进入监听模式。 - 选项
这个选项有“选项值”,也就是具体端口号。
然后在“主机C”上运行 nc,测试“主机S”上的 8080 端口是否可达
补充
- 是否省略“-p” 某些 nc 的变种,在开启监听模式时,可以省略“”
- 如何让 nc 的监听端口【持续开启】在默认情况下,nc 开启 listen 模式充当服务端,在接受【第一次】客户端连接之后,就会把监听端口关闭。
为啥会这样捏?因为当年设计 nc 更多的是作为某种网络诊断/配置工具,并【不是】真拿它当服务端软件来用的。
如果你想要让 nc 始终监听模式,使之能【重复】接受客户端发起的连接,可以追加 选项 - UDP 上述举例是基于 TCP 协议。如果你要测试 UDP 协议,要记得【两边】的 nc 都要追加 选项。
情景说明
在“招数1”里面介绍了:如何测试【单个】端口是否可达。
扩展一下:如果你要测试的不止一个端口,而是某个【范围】的端口。这种行为有个专门的术语叫【端口扫描】。
“端口扫描”是一把双刃剑——“黑帽子”用这招进行信息收集,为后续的入侵做铺垫;“白帽子”用这招来进行“渗透测试”,以排查自己系统中【尚未屏蔽】的对外监听端口。
作为一款牛逼的网络瑞士军刀,nc 当然可以用来干这事儿啦。
顺便说一下:
不论是 TCP 还是 UDP,协议规定的【有效】端口号范围都是: ~
方法
下面这个命令,用来扫描 IP 地址为 的主机,扫描的端口范围从 到
nc -znv x.x.x.x 1-1024
- 选项
意思是:开启“zero-I/O 模式”。该模式指的是:nc 只判断某个监听端口是否能连上,连上后【不】与对端进行数据通讯。 - 选项
(前面已聊过,参见“招数1”) - 选项
选项前面也聊过,这里要特地强调一下。
对 nc 的其它用法, 选项是可加可不加滴;但对于“端口扫描”而言,一定要有这个选项——否则你【看不到】扫描结果
补充
- 优化输出 玩“端口扫描”的时候,“ 选项”会把“成功/失败”的结果统统打印出来。
通常大伙儿关注的都是“扫描成功”的那些端口。因此,可以用如下命令过滤一下,只打印扫出来的端口。nc -znv x.x.x.x 1-1024 2>&1 | grep succeeded
由于“ 选项”产生的输出位于【stderr】,上述命令中的 用来把【stderr】合并到【stdout】(注:这种写法只适用于 POSIX 系统上的 shell)
命令用来进行【过滤】。对于 Windows 系统,默认【没有】 命令,需改用 命令过滤 - 超时设置 如果你要扫描的端口范围,跨度比较大,超时值要【恰到好处】——
超时值太大,会浪费时间;超时值太小,可能会遗漏某些端口(端口本身开放,但 nc 还没来得及连上就超时了) - 【并发】扫描 如果你设置了较小的超时值,依然嫌慢,还可以用【并发】扫描的方式,进一步提升效率。简而言之就是:同时运行多个 nc,分别扫描不同的端口范围。
情景说明
为了支持代理,nc 的“OpenBSD 变种”增加了两个选项: 与
方法
- 选项
该选项表示【代理的位置】,以 的形式表示(中间是【半角冒号】)。 - 选项
该选项表示【代理的类型】,含义如下:
nc -X 5 -x 127.0.0.1:9050 -q 3 -v program-think.blogspot.com 443 Connection to program-think.blogspot.com 443 port [tcp/https] succeeded!
补充
- 延时退出 在上述举例中,用到了一个新的 选项。主要考虑到:本博客的 Web Server 位于【公网】。
当你用 nc 连接【公网】上的服务器,考虑到网络环境的诸多因素,最好加 选项,让 nc【延时】退出。
示例中,延时3秒。实际操作时,要根据你的网络环境调整。 - 设置别名(alias) 如果你比较懒,觉得每次都输入上述两个代理选项太麻烦,可以为 nc 设置一个【别名】
alias nc-tor='nc -X 5 -x 127.0.0.1:9050'
使用场景
如今要【远程管理】服务器,最常用的大概就是 SSH 这种方式了。
方法
如果某个服务器运行了 SSH 服务端(默认监听端口是 ),那么用如下命令可以看出:该服务器的操作系统类型,以及 SSH server 的版本。
echo "EXIT" | nc -v -n 服务器IP 22 echo "EXIT" | nc -v 服务器域名 22
补充
- 批处理 & 自动化 某些“有心人”甚至可以搞一个脚本,批量探测某个 IP 地址段的 22 端口,然后把找到的服务器信息保存在某个文件中。
另外,
有的系统管理员会把 sshd 的监听端口从 改为其它数值,想要迷惑攻击者。但这么干,【效果不大】。
攻击者可以先进行端口扫描,拿到所有已开启的 TCP 监听端口;然后利用上述方法,对这些 TCP 端口进行【自动化】探测,从而判断出哪个端口是 SSH Server。
使用场景
nc 再度派上用场——你可以用 nc 直接抓取页面,保存到本机。
这种玩法相当于——让 nc 在【裸 TCP】层面执行 HTTP 协议的命令。在整个过程中,浏览器完全【不】参与其中。既【不会】暴露浏览器的信息,也【不会】暴露操作系统的信息。
方法
先执行下列两个命令的其中一个(具体看你想用“IP”还是“域名”)
echo -e "GET / HTTP/1.0 " | nc-tor -vq 5 服务器域名 端口 echo -e "GET / HTTP/1.0 " | nc-tor -vq 5 -n 服务器IP 端口
然后 nc 就会把这个页面抓下来,打印到命令行终端。这时候你看到的是【HTML 源代码】。
上述命令访问的是 Web Server 的【根路径】。如果你想要看其它路径的页面(比如说:),稍微修改成如下:
echo -e "GET /index.html HTTP/1.0 " | nc-tor -vq 5 服务器域名 端口 echo -e "GET /index.html HTTP/1.0 " | nc-tor -vq 5 -n 服务器IP 端口
由于正常人类是无法直接阅读【HTML 源代码】滴。为了更加人性化,你可以把 nc 抓下来的 HTML 源代码,(在命令行中用“大于号”)重定向到某个 HTML 文件,然后就可以用你本机的浏览器阅读之。
补充
- 协议版本 有些同学会奇怪——为啥上述的示例用的是 1.0 而不是 1.1?
主要是为了偷懒——按照 RFC 的规范,HTTP 1.1 的 Request 中, 是【必须】的字段;而在 HTTP 1.0 中,这个字段是【可选】滴。另外,nc 的“OpenBSD 变种”还不支持 HTTPS(SSL/TLS)。 - 局限性
- 关于“页面的【外部】元素”
用这招,nc 只抓取页面本身,不包括页面中的外部元素(JS、CSS …)。
这种方式拿到的页面,阅读的时候会显得比较丑陋(你就凑合着看吧) - 关于“JS 引擎”
由于这招只是在 TCP 层面模拟了简单的 HTTP 协议。所以只能得到【静态 HTML】。
如果某个页面的内容是依靠【前端 JS】动态生成(所谓的 AJAX 风格),那这招就不灵啦(因为 nc【没有】JS 引擎)。
- 关于“页面的【外部】元素”
使用场景
所谓的“端口转发”,通俗地说就是让 A 监听端口的数据转发到 B 监听端口。
原理
用 nc 进行端口转发,需要运行【两个】nc 进程,一个充当“服务端”,另一个是“客户端”,然后用【管道】让把两个进程的“标准输入输出”交叉配对。所谓的“交叉配对”就是——每一个 nc 进程的“标准输出”都【对接】到另一个 nc 进程的“标准输入”。如此一来,就可以完美地建立【双向通讯】。
玩过命令行的同学,应该都知道:大部分 shell 都支持【管道符】(就是那个竖线符号 ),可以把某个进程的标准输出,重定向给另一个进程的标准输入。但是 shell 的“管道符”只能做到“单向配对”,【无法】做到“交叉配对”。所以还需要再借助另一个管道——也就是“命名管道”。
“命名管道”洋文叫做“named pipe”,是一种进程间通讯(IPC)的机制。顾名思义,“命名管道”就是有名号滴,而 shell 中使用的那个【管道符】,其本质上是“匿名管道”(无名管道)。
主流的操作系统(Windows、Linux、UNIX)都支持“命名管道”这种机制。
方法
步骤1:创建命名管道
用下面这个简单的命令创建一个“命名管道”,其名称叫做 。(这个名称只是为了举例,你也可以用别的名称)
mkfifo nc_pipe
步骤2:同时启动两个 nc
nc -l -p 1234 < nc_pipe | nc 127.0.0.1 5678 > nc_pipe
运行上述命令之后,就可以把本机的 端口重定向到本机的 端口。
这个命令有点复杂。技术菜鸟如果看不懂,就算了(没关系滴,不影响你看后续的章节)。
如果你比较喜欢刨根问底,稍微解释一下:
上述命令行中,前一个 nc 充当【服务端】,后一个 nc 充当【客户端】。命令行中的“管道符”使得“服务端 nc”的输出绑定到“客户端 nc”的输入。然后再用 这个命名管道做中转,使得“客户端 nc”的输出绑定到“服务端 nc”的输入。从而完成了【交叉配对】。
补充
- 监听端口持续开启 -k
使用场景
有时候,你需要在两台电脑之间传输文件。也可以用 nc 搞定。
某些技术小白会问:为啥不用 Windows 的共享目录?
反驳的理由很多——
反驳1:这个玩意儿只能在 Windows 上用。
反驳2:为了使用“共享目录”,需要启用(Enable)系统中的好几个 service,这会增加你系统的【攻击面】。
反驳3:启用的 service 越多,占用的内容也越多,影响性能。
……
还有些同学会问:为啥不用 FTP、SSH(或诸如此类的东东)?
1、如果只是临时传一个文件,还要额外再去装某某软件的客户端/服务端,岂不是很蛋疼?
2、任何服务端软件,(从某种意义上说)都是在【增加攻击面】。
方法
为了叙述方便,假设你有两台主机 A 与 B,你要把 A 主机上的文件 file1 传输到 B 主机上,保存为 file2
你先在【接收端】(B 主机)运行如下命令(其中的 是端口号)
记得把开启监听端的防火墙放通端口,Linux关闭防火墙:systemctl stop firewalld.service
nc -l -p xxx > file2
然后在【发送端】(A 主机)运行如下命令。
nc x.x.x.x xxx < file1
第二条命令中的 是端口号,要与第一条命令中的端口号相同;第二条命令中的 是【主机 B】的 IP 地址。
补充
- 性能优势 用 nc 传输文件,相当于是:直接在【裸 TCP】层面传输。你可以通俗理解为:【没有】应用层。如果你传输的文件【超级大】或者文件数量【超级多】,用 nc 传输文件的性能优势会很明显(相比“FTP、SSH、共享目录…”而言)
暂时先记录这些了