这是一个端口扫描仪。理论上可以在5分钟内扫描整个互联网,单机每秒传输1000万个数据包。它的用法(参数,输出)类似于nmap端口扫描器。支持对多台计算机进行广泛扫描,但不支持对
这是一个端口扫描仪。理论上可以在5分钟内扫描整个互联网,单机每秒传输1000万个数据包。
它的用法(参数,输出)类似于nmap端口扫描器。支持对多台计算机进行广泛扫描,但不支持对单台计算机进行深入扫描。
内部采用异步传输,如端口扫描器Scanland、unicornscan、ZMap等。它更加灵活,允许任何端口和地址范围。
注意:masscan使用自己的专用TCP/IP堆栈。除简单端口扫描之外的任何操作都可能导致与本地TCP/IP堆栈的冲突。也就是说,你需要使用–src-ip从不同的ip地址运行的选项,或者–Src-port配置masscan使用的源端口,然后还配置内部防火墙(如pf或iptables ),将这些端口与操作系统的其余部分分开。
固定
它实际上除了C编译器(比如gcc或者clang)之外没有任何依赖。
sudo apt-get --assume-yes install git make gccgit clone https://github.com/robertdavidgraham/masscancd masscanmake
二进制文件位于masscan/bin子目录中。
make install
源代码是由很多小文件组成的,所以使用多线程构造可以加快构造速度。
make -j
使用
用法类似于nmap。要扫描某些端口的网段:
# masscan -p80,8000-8100 10.0.0.0/8 2603:3001:2d00:da00::/112
这将:
扫描10.x.x.x子网和2603:3001:2d00:da00::x子网扫描两个子网上的端口 80 和范围 8000 到 8100,或总共 102 个端口<stdout>可以重定向到文件的打印输出
要查看选项的完整列表,请使用此–。回声功能。这将转储当前配置并退出。此输出可用作程序的反馈输入:
# masscan -p80,8000-8100 10.0.0.0/8 2603:3001:2d00:da00::/112 --echo > xxx.conf# masscan -c xxx.conf --rate 1000
横幅信息Masscan不仅可以检测端口是否打开。它还可以在该端口完成与应用程序的TCP连接和交互,以获取简单的“横幅”信息。
Masscan支持以下协议的横幅检查:
FTPHTTPIMAP4memcachedPOP3SMTPSSHSSLSMBv1SMBv2TelnetRDPVNC
问题是masscan包含自己的TCP/IP堆栈,它独立于系统。当本地系统接收到来自探测目标的SYN-ACK时,它将对RST数据包做出响应,并在masscan获得横幅之前终止连接。
防止这种情况的最简单方法是为masscan分配一个单独的IP地址。这将类似于以下示例之一:
# masscan 10.0.0.0/8 -p80 --banners --source-ip 192.168.1.200 # masscan 2a00:1450:4007:810::/112 -p80 --banners --source-ip 2603:3001:2d00:da00:91d7:b54:b498:859d
选定的源地址必须在本地子网上,否则不能被其他系统使用。Masscan会警告你犯了一个错误,但你可能搞砸了另一台机器几分钟的通信,所以要小心。
在某些情况下,如WiFi,这是不可能的。在这些情况下,您可以在masscan使用的端口上设置防火墙。这将阻止本地TCP/IP堆栈看到数据包,但masscan仍然可以看到它,因为它绕过了本地堆栈。对于Linux,这看起来像:
# iptables -A INPUT -p tcp --dport 61000 -j DROP# masscan 10.0.0.0/8 -p80 --banners --source-port 61000
您可能希望选择一个不与Linux可能为源端口选择的端口冲突的端口。您可以查看Linux使用的范围,并通过查看以下文件重新配置该范围:
/proc/sys/net/ipv4/ip_local_port_range
在最新版本的Kali Linux(2018年8月)上,范围是32768到60999,所以应该选择32768以下或者61000及以上的端口。
将iptables规则设置为仅持续到下次重新启动。您需要了解如何根据您的发行版保存配置,比如使用iptables-save和/或iptables-persistent。
在Mac OS X和BSD上,也有类似的步骤。要找出要避免的范围,请使用以下命令:
# sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last
在FreeBSD和旧的MacOS上,使用ipfw命令:
# sudo ipfw add 1 deny tcp from any to any 40000 in# masscan 10.0.0.0/8 -p80 --banners --source-port 40000
在较新的MacOS和OpenBSD上,使用pf包过滤实用程序。编辑文件/etc/pf.conf以添加以下行:
block in proto tcp from any to any port 40000
然后,要启用防火墙,请运行以下命令:
# pfctrl -E
如果防火墙已经在运行,请使用以下命令重新启动或重新加载规则:
# pfctl -f /etc/pf.conf
Windows不响应RST数据包,因此这两种技术都不是必需的。然而,masscan仍然被设计为最好地使用其自己的IP地址,因此您应该尽可能以这种方式运行它,即使这不是绝对必要的。
其他检查也需要同样的东西,比如–心脏出血检查,这只是横幅检查的一种形式。
如何扫描整个互联网
虽然它对较小的内部网络很有用,但这个程序的设计确实考虑到了整个互联网。它可能看起来像这样:
# masscan 0.0.0.0/0 -p0-65535
扫描整个互联网是一种糟糕的体验。一方面,互联网的某些部分对被扫描的反应很差。另一方面,一些网站会跟踪扫描并将你添加到禁止列表中,这将保护你免受互联网有用部分的影响。所以,你要排除很多范围。要列入黑名单或排除某个范围,您需要使用以下语法:
# masscan 0.0.0.0/0 -p0-65535 --excludefile exclude.txt
这只是将结果打印到命令行。您可能希望将它们保存到文件中。因此,您需要类似的东西:
# masscan 0.0.0.0/0 -p0-65535 -oX scan.xml
这将结果保存在XML文件中,以便您可以轻松地将结果转储到数据库或其他内容中。
但是,这只是以每秒100个包的默认速率进行的,这将需要很长时间来扫描互联网。你需要加快速度:
# masscan 0.0.0.0/0 -p0-65535 --max-rate 100000
这将把速率提高到每秒100,000个数据包,这将在每个端口大约10小时内扫描整个互联网(不包括在内)(如果扫描所有端口,则需要655,360小时)。
与Nmap的比较
Masscan设计用于多台机器的大规模扫描,而nmap设计用于单机或小规模密集扫描。
两个重要的区别是:
没有要扫描的默认端口,必须指定 -p <ports>目标主机是 IP 地址或简单范围,而不是 DNS 名称,也不是nmap可以使用的时髦子网范围(如10.0.0-255.0-255)。
Masscan can可以将以下设置视为永久启用:
-sS: 这仅做 SYN 扫描(目前,将来会改变)-Pn: 不首先 ping 主机,这是异步操作的基础-n: 没有发生 DNS 解析–randomize-hosts:扫描完全随机,总是,你不能改变这个–send-eth: 使用 raw 发送 libpcap
如果您需要其他nmap兼容设置的列表,请使用以下命令:
# masscan --nmap
传输率(重要!!)这个程序发送数据包非常快。在Windows或VM上,每秒可以处理300,000个数据包。在Linux上(没有虚拟化),每秒将处理160万个包。这足以融化大多数网络。
默认情况下,该速率设置为每秒100个数据包。要将速率增加到一百万,使用类似–。利率1000000。
扫描IPv4 Internet时,您将扫描大量子网,因此即使数据包的传出速率很高,每个目的子网也将接收少量传入数据包。
然而,使用IPv6扫描,您将倾向于关注具有数十亿个地址的单个目标子网。因此,您的默认行为将会淹没目标网络。网络经常在masscan产生的负载下崩溃。
它是如何设计的?
代码布局main.c文件包含main()函数。它还包含transmit_thread()和receive_thread()函数。这些函数被有意地展平和注释,这样你可以通过逐行浏览每个函数来阅读程序的设计。
异步的这是一种异步设计。它有独立的发送和接收线程,这些线程在很大程度上是相互独立的。
因为它是异步的,所以它以底层数据包传输允许的最快速度运行。
使不规则化Masscan和其他扫描仪的主要区别在于它随机选择目标的方式。
基本原理是有一个从零开始的单一索引变量,每个探针递增1。在C代码中,这表示为:
for (i = 0; i < range; i++) { scan(i);}
我们必须将索引转换成IP地址。假设您想要扫描所有“私有”IP地址。这就是范围表,例如:
192.168.0.0/1610.0.0.0/8172.16.0.0/12
在这个例子中,第一个64k索引被附加到192.168.xx以形成目标地址。然后,将10.xxx范围内的剩余索引加上下一个1600万,并应用于172.16.xx
在这个例子中,我们只有三个范围。当扫描整个互联网时,我们实际上有100多个范围。那是因为你要黑名单或者排除很多子范围。将这个需要的范围切割成数百个更小的范围。
这是代码中最慢的部分之一。我们每秒传输1000万个包,并且我们必须为每个探测将索引变量转换成IP地址。我们通过少量内存中的“二分搜索法”来解决这个问题。在这种数据包速率下,缓存效率开始超过算法效率。理论上有很多更有效的技术,但都需要太大的内存,在实践中会变慢。
我们将把索引转换成IP地址的pick()函数。在使用中,它看起来像:
for (i = 0; i < range; i++) { ip = pick(addresses, i); scan(ip);}
Masscan不仅支持IP地址范围,还支持端口范围。这意味着我们需要从索引变量中选择IP地址和端口。这很简单:
range = ip_count * port_count;for (i = 0; i < range; i++) { ip = pick(addresses, i / port_count); port = pick(ports, i % port_count); scan(ip, port);}
这导致了代码的另一个昂贵部分。在x86 CPU上,除法/模数指令需要大约90个时钟周期或30纳秒。当以1000万包/秒的速度传输时,我们每个包只有100纳秒。我觉得没有什么办法可以更好的优化了。幸运的是,可以同时执行两个这样的操作,所以执行两个(如上所示)并不比执行一个更昂贵。
针对上述性能问题,其实也有一些简单的优化,但都依赖于i++索引变量的增加。实际上,我们需要随机化这个变量。我们需要随机扫描IP地址的顺序。我们需要在目标上平均分配流量。
随机化是通过简单地加密索引变量来完成的。根据定义,加密是随机的,并在原始索引变量和输出之间创建一对一的映射。这意味着当我们线性遍历该范围时,输出的IP地址是完全随机的。在代码中,这看起来像:
range = ip_count * port_count;for (i = 0; i < range; i++) { x = encrypt(i); ip = pick(addresses, x / port_count); port = pick(ports, x % port_count); scan(ip, port);}
这也有很大的成本。因为范围是不可预测的,不是2的好的偶次方,我们不能使用廉价的二进制技术,例如AND (&)和XOR (^).相反,我们不得不使用昂贵的运算,如模数(%)。在我目前的基准测试中,加密变量需要40纳秒。
这种架构允许许多很酷的功能。比如支持“切片”。可以设置5台机器,每台机器执行五分之一的扫描或range/shard_count。切片可以是多台机器、同一台机器上的多个网络适配器,甚至(如果需要)同一网络适配器上的多个IP源地址。
或者,您可以对加密函数使用“seed”或“key ”,以便为每次扫描获得不同的顺序,例如,x = encrypt(seed,I)。
我们也可以通过退出程序来暂停扫描,只需记住当前的I值,稍后再重新启动。我在开发过程中经常这样做。我发现互联网扫描有问题,所以我点击停止扫描,然后在修复错误后重新启动。
另一个功能是重传/重试。有时候在网上丢包,你可以背靠背发两个包。但是,丢弃一个数据包的可能会丢弃下一个数据包。因此,您希望发送副本的时间间隔大约为1秒。我们已经有一个“rate”变量,它是我们每秒传输的数据包数量,所以重传函数只是i+rate用作索引。
C10可扩展性
异步技术被称为“c10k问题”的解决方案。Masscan是为下一级可扩展性设计的,即“C10M问题”。
C10M的解决方案是绕过内核。Masscan中有三种主要的内核旁路:
自定义网络驱动程序用户模式 ?TCP 堆栈用户模式同步
Masscan可以使用PF_RING DNA驱动程序。这个驱动程序DMA直接从用户态内存发送数据包到网络驱动程序,没有内核的参与。这允许软件以硬件允许的最大速率传输数据包,即使CPU速度很慢。如果把8个10-gbps的网卡放进电脑,就意味着它能以每秒1亿包的速度传输。
Masscan有自己的内置TCP堆栈,用于从TCP连接中抓取横幅。这意味着它可以轻松支持1000万个并发TCP连接,前提是计算机有足够的内存。
Masscan没有“互斥锁”。现代互斥体(也称为futexes)大多是用户模式的,但是它们有两个问题。第一个问题是,它们会导致缓存线在CPU之间快速来回跳动。第二是当有争用时,它们会对内核进行系统调用,这会降低性能。程序快速路径上的互斥体严重限制了可伸缩性。相反,Masscan使用“环”来同步事物,例如当接收线程中的用户模式TCP堆栈需要在不干扰发送线程的情况下传输数据包时。
可运输性代码在Linux、Windows和Mac OS X上运行良好,所有重要部分都使用标准C (C90)。因此,它在Visual Studio上用微软的编译器编译,在Mac OS X上用Clang/LLVM编译器编译,在Linux上用GCC编译。
Windows和Mac没有针对包传输进行调整,每秒只能接收大约30万个包,而Linux每秒可以处理150万个包。反正可能比你想的要快。
安全的
这个项目使用安全函数strcpy_s()而不是strcpy()。
这个项目有自动单元回归测试(make regress)。
IPv6和IPv4共存。
Masscan支持IPv6,但没有特殊模式,两者都支持。
在任何使用masscan的示例中,只需将IPv6地址放在您看到IPv4地址的地方。您可以在同一次扫描中包括IPv4和IPv6地址。包括相同位置的适当地址,没有特殊标记。
IPv6地址空非常大。除了DHCPv6分配的子网的前64k个地址之外,您可能不想扫描大范围的地址。
您可能想要扫描存储在–Include-file filename.txt从其他来源获得的文件()中大量地址的列表。该文件可以包含IPv4和IPv6地址列表。使用的测试文件包含800万个地址。这种大小的文件在启动时需要额外的几秒钟来读取(masscan在扫描前会对地址进行排序并删除重复的地址)。
记住,masscan包含自己的网络堆栈。因此,运行masscan的本地机器不需要启用IPv6,但本地网络需要能够路由IPv6数据包。
PF_RING
为了超过每秒200万个数据包,你需要一个英特尔10-gbps以太网适配器和一个来自ntop的名为“PF_RING ZC”的特殊驱动程序。为了使用PF_RING,不需要重建Masscan。要使用PF_RING,您需要构建以下组件:
libpfring.so (安装在/usr/lib/libpfring.so)pf_ring.ko (他们的内核驱动程序)ixgbe.ko (他们的 Intel 10-gbps 以太网驱动程序版本)
当Masscan检测到适配器的名称类似zc:enp1s0而不是类似名称时,它将自动切换到PF_RING ZC模式。
回归测试
此项目包含一个内置单元测试:
$ make testbin/masscan --selftestselftest: success!
这测试了代码中许多棘手的部分。您应该在构建之后执行此操作。
特性试验
要测试性能,请在未使用的地址上运行以下类似操作,以避免本地路由器过载:
$ bin/masscan 0.0.0.0/4 -p80 --rate 100000000 --router-mac 66-55-44-33-22-11
伪造者–路由器-mac将数据包保存在本地网段,这样它们就不会被传输到互联网。
您也可以在“离线”模式下测试,这是程序在没有传输开销的情况下运行的速度:
$ bin/masscan 0.0.0.0/4 -p80 --rate 100000000 --offline
第二个基准测试大致展示了如果使用PF_RING的话程序的运行速度,其开销接近于零。
对了,随机化算法用了很多“整数算法”,这是CPU上长时间的慢运算。现代CPU将执行这种计算的速度提高了一倍,从而使masscan更快。