netcat——网络的瑞士军刀

前言:

早些时候了解过nc,但是那时候还没有博客,今天来专门做个记录对于这把鼎鼎大名的网络瑞士军刀——netcat。

以下内容主要转载 编程随想

以下内容主要参考 编程随想

以下内容主要参考 编程随想

 

 

 

 

 

 


概念

NC(netcat)被称为网络工具中的瑞士军刀,体积小巧,但功能强大。

它诞生于1995年,在网络安全社区的名气很大(就如同 AK47 在军事领域的名气)。长期在安全圈内混的人,应该都知道它。想当年,insecure.org 网站在本世纪初搞过几次“年度投票”,评选优秀的安全工具。每次投票,netcat 都能排进前几名。

简而言之,nc 是一个【命令行】工具,能够让你很方便、很灵活地地操纵【传输层协议】(TCP & UDP)。

 

考虑到本文的读者中,有些是技术菜鸟,稍微普及一个小知识

==================== 华丽的分割线========================

 

在谈到“网络协议分层”这个话题时,有一个大名鼎鼎的“OSI 7层模型”。这个模型相当牛逼,任何一种具体的网络协议实现,都可以套用其中。
在如今这个互联网时代,大伙儿经常听说的“TCP/IP 协议”以及周边的协议,也可以套用到“OSI 7层模型”之上。大致如下:

 

层次 名称 协议举例
7 应用层 (注:位于这层的协议非常多。
比如:HTTP、DNS、FTP、SMTP、POP3、SSH ……
与用户直接打交道的,大都在这层)
6 表示层 (注:这层的协议很少见,此处省略)
5 会话层 SOCKS(代理)
PPTP(常用于:VPN)
命名管道(常用于:进程间通讯)
NetBIOS
4 传输层 TCP(传输控制协议)
UDP(数据报协议)
3 网络层 IP(互联网协议)
ICMP(互联网控制消息协议)
IGMP(互联网组管理协议)
IPSec(常用于:VPN)
2 链路层 MAC(常用于:以太网、移动通讯、等)
ARP & RARP(MAC 地址的解析与反向解析)
SLIP、PPP、PPPoE(常用于:拨号上网)
L2TP(常用于:VPN)
1 物理层 USB 协议
蓝牙协议
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下,删除时,卸载软件时,只要删除这个文件就行了:

./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 的命令行包括如下几个部分:

nc 命令选项 主机 端口
  • 命令选项
    这部分可能包含 0~N 个选项
    (注:这部分最复杂,下一个小节单独聊)
  • 主机
    这部分可能没有,可能以“点分十进制”形式表示,也可能以“域名”形式表示。
  • 端口
    这部分可能没有,可能是单个端口,可能是端口范围。
    对于“端口范围”,以两个数字分别表示“开始和结束”,中间以【半角减号】相连。举例:1-1024

 

何为“命令行选项”?

简单来说,nc 提供了一大堆【命令行选项】,分别对应它提供的功能。每个选项都是“单字母”滴。有些选项需要带【选项值】,有些不需要。
你要使用的选项都放在 nc 这个命令之后,每个选项前面要有一个【半角减号】,选项之间以空格分开。

举例:
在下面这个例子中,分别用到了三个选项(l、p、v),其中 12345 是选项 p 所带的【选项值】。

nc -l -p 12345 -v

如果你的系统中已经有 nc(且 nc 已添加到【PATH 环境变量】),在命令行中执行如下,就可以看到它支持的全部命令选项的列表。

nc -h

顺便说一下:在上述命令的输出中,如果第一行包含 OpenBSD 这个单词,就说明你当前用的“网猫”是 OpenBSD 变种。

常用命令选项

 

选项 是否有“选项值” 说明
h NO 输出 nc 的帮助
v NO 在网络通讯时,显示详细的输出信息
注:建议新手多用该选项,出错时帮你诊断问题
n NO 对命令行中的“主机”,【不】进行域名解析
注:如果“主机”是“点分格式”的 IP 地址,需要用该选项;
如果“主机”是“域名”形式,【不能】用该选项
p YES 指定“端口号”
l NO 开启“监听模式”,nc 作为【服务端】
注:如不加该选项,nc 默认作为客户端
u NO 使用 UDP 协议
注:如不加该选项,默认是 TCP 协议
w YES 设置连接的超时间隔(N 秒)
q YES 让 nc 延时(N 秒)再退出
z NO 开启“zero-I/O 模式”
注:该选项仅用于“端口扫描”,后面会聊到
k NO 配合 -l 选项使用,可以重复接受客户端连接。
注:“原版 nc”的该选项用来开启“TCP keepalive”
这是“原版 nc”与“OpenBSD 变种”之间的差异之一
X YES 指定代理的类型(具体用法,后面会聊到)
注:“原版 nc”【没有】该选项。这是“原版 nc”与“OpenBSD 变种”之间的差异之一
x YES 以 IP:port 的格式指定代理的位置。
注:“原版 nc”【没有】该选项。这是“原版 nc”与“OpenBSD 变种”之间的差异之一
e YES 启动某个进程,把该进程的“标准输入输出”与网络通讯【对接】
注:通常用该选项开启一个网络后门
“OpenBSD 变种”基于安全考虑,已去掉该选项,
但还是能用间接的方式达到同样的效果 🙂

汇总上述表格,只是用来【速查】

“合写”形式

有时候要同时用到多个选项,可以“合写在一起”,在前面共用一个【半角减号】。
还拿刚才俺举的例子,以下几种写法是【等价】滴。

nc -lp 12345 -v
nc -l -v -p 12345
nc -lv -p 12345
nc -lvp 12345

如何强行终止 nc?

一般来说,在命令行环境下,你可以用【Ctrl C】这个组合键来强行终止当前运行的进程。
对 nc,你同样可以这么干。

 

招数1:(网络诊断)测试某个远程主机的【监听】端口是否可达

情景说明

经常有这种需求,要判断某个主机的监听端口是否能连上。
导致监听端口【无法】,通常有两种原因:
其一,这个监听端口根本就【没开启】;
其二,监听端口虽然开启,但是被防火墙阻拦了。

  1. 对第1个原因,(如果你能在该主机上运行命令)可以直接用 netstat 这个命令查看监听端口是否开启
  2. 对于第2个原因,netstat 就用不上了。这时候就可以用 nc 来帮你搞定。

方法

用如下命令可以测试某个 IP 地址(x.x.x.x)上的某个监听端口(xx)是否开启。

nc -nv x.x.x.x xx

上述命令用到了如下几个选项:

选项 -v
如果你是 nc 的新手,建议总是带上这个选项——通过更详细的输出,能帮你搞明白状况。

选项 -n
由于测试的是【IP 地址】,用该选项告诉 nc,【无须】进行域名(DNS)解析;
反之,如果你要测试的主机是基于【域名】,就【不能】用“选项 -n”。

 

补充

  • 超时设置 在测试链接的时候,如果你没使用 -w 这个超时选项,默认情况下 nc 会等待很久,然后才告诉你连接失败。如果你所处的网络环境稳定且高速(比如:局域网内),那么,你可以追加“-w 选项”,设置一个比较小的超时值。在下面的例子中,超时值设为3秒。
    nc -nv -w 3 x.x.x.x xx
  • UDP 通常情况下,要测试的端口都是 TCP 协议的端口;如果你碰到特殊情况,需要测试某个 UDP 的端口是否可达。nc 同样能胜任。只需要追加 -u 选项。

 

招数2:(网络诊断)判断防火墙是否“允许 or 禁止”某个端口

情景说明

前一个章节(招数1)的场景是——已经有某个网络软件开启了监听端口,然后用 nc 测试端口是否可达。
现在换另一个场景:
假设你正在配置防火墙规则,禁止 TCP 的 8080 端口对外监听。那么,你如何【验证】自己的配置是 OK 滴?
更进一步说:如果当前【没有】任何软件开启 8080 这个监听端口,你如何判断:该端口号是否会被防火墙阻拦?
为了叙述方便,设想如下场景:
有两台主机——“主机C”充当客户端,“主机S”充当服务端。
然后要判断“主机S”上的防火墙是否会拦截其它主机对 8080 TCP 端口的连接。

方法

在“主机S”上运行 nc,让它在 8080 端口,命令如下:

nc -lv -p 8080
  • 选项 -l
    这个选项会让 nc 进入监听模式。
  • 选项 -p
    这个选项有“选项值”,也就是具体端口号。

然后在“主机C”上运行 nc,测试“主机S”上的 8080 端口是否可达

补充

  • 是否省略“-p”  某些 nc 的变种,在开启监听模式时,可以省略“-p
  • 如何让 nc 的监听端口【持续开启】在默认情况下,nc 开启 listen 模式充当服务端,在接受【第一次】客户端连接之后,就会把监听端口关闭。
    为啥会这样捏?因为当年设计 nc 更多的是作为某种网络诊断/配置工具,并【不是】真拿它当服务端软件来用的。
    如果你想要让 nc 始终监听模式,使之能【重复】接受客户端发起的连接,可以追加 -k 选项
  • UDP 上述举例是基于 TCP 协议。如果你要测试 UDP 协议,要记得【两边】的 nc 都要追加 -u 选项。

 

招数3:(渗透测试)用 nc 玩“端口扫描”

情景说明

在“招数1”里面介绍了:如何测试【单个】端口是否可达。
扩展一下:如果你要测试的不止一个端口,而是某个【范围】的端口。这种行为有个专门的术语叫【端口扫描】。
“端口扫描”是一把双刃剑——“黑帽子”用这招进行信息收集,为后续的入侵做铺垫;“白帽子”用这招来进行“渗透测试”,以排查自己系统中【尚未屏蔽】的对外监听端口。
作为一款牛逼的网络瑞士军刀,nc 当然可以用来干这事儿啦。
顺便说一下:
不论是 TCP 还是 UDP,协议规定的【有效】端口号范围都是:1 ~ 65535

方法

下面这个命令,用来扫描 IP 地址为 x.x.x.x 的主机,扫描的端口范围从 1 到 1024

nc -znv x.x.x.x 1-1024
  • 选项 -z
    意思是:开启“zero-I/O 模式”。该模式指的是:nc 只判断某个监听端口是否能连上,连上后【不】与对端进行数据通讯。
  • 选项 -n
    (前面已聊过,参见“招数1”)
  • 选项 -v
    -v 选项前面也聊过,这里要特地强调一下。
    对 nc 的其它用法,-v 选项是可加可不加滴;但对于“端口扫描”而言,一定要有这个选项——否则你【看不到】扫描结果

补充

  • 优化输出 玩“端口扫描”的时候,“-v 选项”会把“成功/失败”的结果统统打印出来。
    通常大伙儿关注的都是“扫描成功”的那些端口。因此,可以用如下命令过滤一下,只打印扫出来的端口。

    nc -znv x.x.x.x 1-1024  2>&1 | grep succeeded

    由于“-v 选项”产生的输出位于【stderr】,上述命令中的 2>&1 用来把【stderr】合并到【stdout】(注:这种写法只适用于 POSIX 系统上的 shell)
    grep 命令用来进行【过滤】。对于 Windows 系统,默认【没有】grep 命令,需改用 find 命令过滤

  • 超时设置 如果你要扫描的端口范围,跨度比较大,超时值要【恰到好处】——
    超时值太大,会浪费时间;超时值太小,可能会遗漏某些端口(端口本身开放,但 nc 还没来得及连上就超时了)
  • 【并发】扫描  如果你设置了较小的超时值,依然嫌慢,还可以用【并发】扫描的方式,进一步提升效率。简而言之就是:同时运行多个 nc,分别扫描不同的端口范围。

 

招数4:用 nc 走代理

情景说明

为了支持代理,nc 的“OpenBSD 变种”增加了两个选项:-X 与 -x

方法

  • 选项 -x
    该选项表示【代理的位置】,以 x.x.x.x:xxx 的形式表示(中间是【半角冒号】)。
  • 选项 -X
    该选项表示【代理的类型】,含义如下:

 

选项值 含义
5 SOCKS5 代理
4 SOCKS4 代理
connect CONNECT 型的 HTTP 代理

 

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!

 

补充

  • 延时退出 在上述举例中,用到了一个新的 -q 选项。主要考虑到:本博客的 Web Server 位于【公网】。
    当你用 nc 连接【公网】上的服务器,考虑到网络环境的诸多因素,最好加 -q 选项,让 nc【延时】退出。
    示例中,延时3秒。实际操作时,要根据你的网络环境调整。
  • 设置别名(alias) 如果你比较懒,觉得每次都输入上述两个代理选项太麻烦,可以为 nc 设置一个【别名】
    alias nc-tor='nc -X 5 -x 127.0.0.1:9050'

 

招数5:(信息收集)用 nc 探测“服务器类型”和“软件版本”(以 SSH 为例)

使用场景

如今要【远程管理】服务器,最常用的大概就是 SSH 这种方式了。

方法

如果某个服务器运行了 SSH 服务端(默认监听端口是 22),那么用如下命令可以看出:该服务器的操作系统类型,以及 SSH server 的版本。

echo "EXIT" | nc -v -n 服务器IP 22
echo "EXIT" | nc -v 服务器域名 22

 

补充

  • 批处理 & 自动化 某些“有心人”甚至可以搞一个脚本,批量探测某个 IP 地址段的 22 端口,然后把找到的服务器信息保存在某个文件中。
    另外,
    有的系统管理员会把 sshd 的监听端口从 22 改为其它数值,想要迷惑攻击者。但这么干,【效果不大】。
    攻击者可以先进行端口扫描,拿到所有已开启的 TCP 监听端口;然后利用上述方法,对这些 TCP 端口进行【自动化】探测,从而判断出哪个端口是 SSH Server。

 

招数6:用 nc 爬取网页

使用场景

nc 再度派上用场——你可以用 nc 直接抓取页面,保存到本机。
这种玩法相当于——让 nc 在【裸 TCP】层面执行 HTTP 协议的命令。在整个过程中,浏览器完全【不】参与其中。既【不会】暴露浏览器的信息,也【不会】暴露操作系统的信息。

方法

先执行下列两个命令的其中一个(具体看你想用“IP”还是“域名”)

echo -e "GET / HTTP/1.0\r\n\r\n" | nc-tor -vq 5 服务器域名 端口
echo -e "GET / HTTP/1.0\r\n\r\n" | nc-tor -vq 5 -n 服务器IP 端口

然后 nc 就会把这个页面抓下来,打印到命令行终端。这时候你看到的是【HTML 源代码】。

上述命令访问的是 Web Server 的【根路径】。如果你想要看其它路径的页面(比如说:/index.html),稍微修改成如下:

echo -e "GET /index.html HTTP/1.0\r\n\r\n" | nc-tor -vq 5 服务器域名 端口
echo -e "GET /index.html HTTP/1.0\r\n\r\n" | nc-tor -vq 5 -n 服务器IP 端口

由于正常人类是无法直接阅读【HTML 源代码】滴。为了更加人性化,你可以把 nc 抓下来的 HTML 源代码,(在命令行中用“大于号”)重定向到某个 HTML 文件,然后就可以用你本机的浏览器阅读之。

补充

  • 协议版本 有些同学会奇怪——为啥上述的示例用的是 1.0 而不是 1.1?
    主要是为了偷懒——按照 RFC 的规范,HTTP 1.1 的 Request 中,Host 是【必须】的字段;而在 HTTP 1.0 中,这个字段是【可选】滴。另外,nc 的“OpenBSD 变种”还不支持 HTTPS(SSL/TLS)。
  • 局限性  
    • 关于“页面的【外部】元素”
      用这招,nc 只抓取页面本身,不包括页面中的外部元素(JS、CSS …)。
      这种方式拿到的页面,阅读的时候会显得比较丑陋(你就凑合着看吧)
    • 关于“JS 引擎”
      由于这招只是在 TCP 层面模拟了简单的 HTTP 协议。所以只能得到【静态 HTML】。
      如果某个页面的内容是依靠【前端 JS】动态生成(所谓的 AJAX 风格),那这招就不灵啦(因为 nc【没有】JS 引擎)。

 

招数7:(网络配置)基于 nc 的端口转发(Port Forward)

使用场景

所谓的“端口转发”,通俗地说就是让 A 监听端口的数据转发到 B 监听端口。

 

原理

用 nc 进行端口转发,需要运行【两个】nc 进程,一个充当“服务端”,另一个是“客户端”,然后用【管道】让把两个进程的“标准输入输出”交叉配对。所谓的“交叉配对”就是——每一个 nc 进程的“标准输出”都【对接】到另一个 nc 进程的“标准输入”。如此一来,就可以完美地建立【双向通讯】。
玩过命令行的同学,应该都知道:大部分 shell 都支持【管道符】(就是那个竖线符号 |),可以把某个进程的标准输出,重定向给另一个进程的标准输入。但是 shell 的“管道符”只能做到“单向配对”,【无法】做到“交叉配对”。所以还需要再借助另一个管道——也就是“命名管道”。
“命名管道”洋文叫做“named pipe”,是一种进程间通讯(IPC)的机制。顾名思义,“命名管道”就是有名号滴,而 shell 中使用的那个【管道符】,其本质上是“匿名管道”(无名管道)。
主流的操作系统(Windows、Linux、UNIX)都支持“命名管道”这种机制。

方法

       步骤1:创建命名管道
用下面这个简单的命令创建一个“命名管道”,其名称叫做 nc_pipe。(这个名称只是为了举例,你也可以用别的名称)

mkfifo nc_pipe

步骤2:同时启动两个 nc

nc -l -p 1234 < nc_pipe | nc 127.0.0.1 5678 > nc_pipe

运行上述命令之后,就可以把本机的 1235 端口重定向到本机的 5678 端口。

这个命令有点复杂。技术菜鸟如果看不懂,就算了(没关系滴,不影响你看后续的章节)。
如果你比较喜欢刨根问底,稍微解释一下:
上述命令行中,前一个 nc 充当【服务端】,后一个 nc 充当【客户端】。命令行中的“管道符”使得“服务端 nc”的输出绑定到“客户端 nc”的输入。然后再用 nc_pipe 这个命名管道做中转,使得“客户端 nc”的输出绑定到“服务端 nc”的输入。从而完成了【交叉配对】。

补充

  • 监听端口持续开启  -k

 

招数8:(系统管理)用 nc 传输文件

使用场景

有时候,你需要在两台电脑之间传输文件。也可以用 nc 搞定。

某些技术小白会问:为啥不用 Windows 的共享目录?
反驳的理由很多——
反驳1:这个玩意儿只能在 Windows 上用。
反驳2:为了使用“共享目录”,需要启用(Enable)系统中的好几个 service,这会增加你系统的【攻击面】。
反驳3:启用的 service 越多,占用的内容也越多,影响性能。
……
还有些同学会问:为啥不用 FTP、SSH(或诸如此类的东东)?
1、如果只是临时传一个文件,还要额外再去装某某软件的客户端/服务端,岂不是很蛋疼?
2、任何服务端软件,(从某种意义上说)都是在【增加攻击面】。

方法

为了叙述方便,假设你有两台主机 A 与 B,你要把 A 主机上的文件 file1 传输到 B 主机上,保存为 file2

你先在【接收端】(B 主机)运行如下命令(其中的 xxx 是端口号)

记得把开启监听端的防火墙放通端口,Linux关闭防火墙:systemctl  stop   firewalld.service

nc -l -p xxx > file2

然后在【发送端】(A 主机)运行如下命令。

nc x.x.x.x xxx < file1

第二条命令中的 xxx 是端口号,要与第一条命令中的端口号相同;第二条命令中的 x.x.x.x 是【主机 B】的 IP 地址。

 

补充

  • 性能优势 用 nc 传输文件,相当于是:直接在【裸 TCP】层面传输。你可以通俗理解为:【没有】应用层。如果你传输的文件【超级大】或者文件数量【超级多】,用 nc 传输文件的性能优势会很明显(相比“FTP、SSH、共享目录…”而言)

 

 

 

 


暂时先记录这些了

 

 

 

 

 

 

发表评论