- 网络安全
- 渗透测试
- CLI
【免费下载链接】masscan
TCP port scanner, spews SYN packets asynchronously, scanning entire Internet in under 5 minutes.
导读
本文以 doc/masscan.8.markdown(masscan 的 man 手册)为骨架,系统讲解 masscan —— 一款面向"互联网规模"(Internet-scale)大范围资产普查的异步端口扫描器:从目标与端口语法、发包速率控制、Banner 抓取、输出格式,到配置文件、断点续扫、分片并行,再到与操作系统自带协议栈冲突时的规避方案。读完本文,你将能够独立完成"扫描整个内网/全网、抓取服务 Banner、持久化输出结果、断点续扫与多机分片"的完整实战链路,并理解其底层基于 BlackRock 加密置换的随机化扫描原理。
一、masscan 是什么
根据 man 手册的定义,masscan是一个互联网规模的端口扫描器,适用于对整个互联网或内网的大规模普查(large scale surveys)。它的默认发包速率只有 100 包/秒,但最高可以加速到2500 万包/秒(25 million packets/second)——按这一速率,理论上 3 分钟即可针对单个端口扫完整个 IPv4 互联网(README 中则描述为"5 分钟内以 1000 万包/秒从单机扫完整个互联网")。
关键定位(来自 README.md):
- 使用与
nmap相似的用法、参数与输出风格,但内部采用异步传输架构,与scanrand、unicornscan、ZMap同类,并且比它们更灵活——支持任意的端口范围和地址范围组合; - masscan 拥有自己的ad-hoc TCP/IP 协议栈(用户态协议栈),与操作系统内核协议栈共存;
- 它面向"广范围、多主机"扫描而设计,
nmap则面向"单机/小范围深扫",两者定位互补。
注意:本文所有速率、兼容性等表述均以本项目仓库中 doc/masscan.8.markdown 与 README.md 的原始声明为准,实际吞吐取决于网卡、驱动、CPU 与操作系统。
二、构建与安装
masscan 除 C 编译器(gcc/clang)外几乎没有其他依赖。在 Debian/Ubuntu 上:
sudo apt-get --assume-yes install git make gcc git clone https://github.com/robertdavidgraham/masscan cd masscan make构建产物位于masscan/bin子目录(本仓库根目录为bin/masscan)。安装到系统:
make install源码由大量小文件组成,多线程构建会显著提速(Raspberry Pi 上内存不足 2G 可能失败,建议用-j4而非全部线程):
make -j其他平台构建方式(README 原文):
- Windows + Visual Studio:使用
vs10/下的 VS10 工程(masscan.vcxproj); - Windows + MinGW:直接
make; - macOS + Xcode:使用 xcode4/masscan.xcodeproj;
- macOS 命令行:直接
make; - FreeBSD:
gmake; - 其他平台:尝试一次性编译全部源文件
cc src/*.c -o bin/masscan。
构建完成后建议先跑一遍内置自检(README 中的回归测试小节):
make test bin/masscan --selftest selftest: success!也可以直接运行 man 手册中提到的--regress选项进行回归测试:成功返回 0,失败返回 1。
三、命令行语法与目标指定
man 手册给出的 SYNOPSIS:
masscan [options] [<IP|ranges>... -p PORT[,PORT...]]3.1 目标(Target)的三种写法
命令行上任何不以-开头的参数都会被当作 IP 地址或地址范围,支持以下三种格式:
| 格式 | 示例 | 说明 |
|---|---|---|
| 单个 IP | 192.168.0.1、2001:db8::1 | IPv4 / IPv6 均可 |
| 连续范围 | 10.0.0.1-10.0.0.100 | 起止地址用-连接 |
| CIDR | 0.0.0.0/0、2001:db8::/90 | 标准的无类域间路由写法 |
约束与技巧:
- 至少必须指定一个目标;多个目标可用空格分隔(作为多个参数),也可用逗号合并为单个参数,如:
masscan 10.0.0.0/8,192.168.0.1,2001:db8::1 --range <IP|RANGE>与上述"匿名目标"写法等价,只是显式命名。
3.2 端口指定
-p PORT[,PORT...]/--ports PORT[,PORT...]用于指定待扫描端口:
- 单端口:
-p80 - 端口范围:
-p 20-25 - 端口列表(端口与范围混用):
-p80,20-25 - UDP 端口:使用
U:前缀,如--ports U:161,U:1024-1100
在 src/main-conf.c 的参数解析中,ports/port关键字会被统一处理(代码中的EQUALS("ports", name)分支),并将U:前缀解析为 UDP 端口段;--echo输出时也会以U:前缀形式还原(fprintf(fp,"U:"))。
3.3 从文件读取目标与排除
| 选项 | 作用 |
|---|---|
-iL FILE/--includefile FILE | 从文件读取待扫描范围列表,格式与命令行目标相同,文件可包含数百万条地址/范围 |
--exclude <IP|RANGE> | 黑名单一个地址/范围,覆盖任何目标设置,保证该段绝不会被扫描 |
--excludefile FILE | 从文件读取排除范围列表,同样优先于目标 |
仓库的 data/exclude.conf 就是一个真实的排除列表样例:开头按 IANA/RFC 5735 列出保留段(0.0.0.0/8、10.0.0.0/8、127.0.0.0/8、192.168.0.0/16、240.0.0.0/4等),随后是历史扫描中对方投诉要求拉黑的真实网段(如153.11.0.0/16、165.160.0.0/16),最后还有"建议不要扫描的 DOD / 美国军方网段"以及英国 JANET 教育网段。这正体现了 man 手册的建议:把排除项放进默认配置文件,避免误扫危险地址。
3.4 其他目标相关选项
--ping:在 TCP/UDP 扫描的同时附带 ICMP Echo 请求探测。--source-ip/--adapter-ip:见下文"网络接口"一节。
四、扫描控制:速率、重试与扫描范围
4.1 发包速率--rate RATE
--rate指定期望的发包速率:
- 支持极小值,如
0.1(每 10 秒发 1 包); - 支持极大值,如
10000000(1000 万包/秒)。 - 经验参考(man 手册原文):Windows 约 25 万包/秒,新版 Linux 约 250 万包/秒,要达到 2500 万包/秒需要 PF_RING 驱动。
README 补充:默认速率仅 100 包/秒;--rate 1000000可提升到 100 万包/秒。注意:高速率下对 IPv6 大段扫描会淹没目标网络(IPv6 常聚焦单一子网内的数十亿地址,不像 IPv4 均匀分布到大量子网),导致对方网络崩溃。
4.2 重试--retries <num>
指定重试次数,每次重试间隔 1 秒。由于 masscan 是无状态(stateless)扫描器,即使已经收到回应,重试仍会照发不误——这是与有状态扫描器的本质区别。
4.3 随机种子--seed INT
为随机数生成器提供种子。不同种子 → 不同的随机扫描顺序。也可以传字符串time,用本地时间戳作为种子,每次都生成不同顺序;未指定时默认即time。--seed在 src/main-conf.c 中以SET_seed保存,最终传给blackrock_init()作为置换密钥(见 src/main.c 第 261 行)。
4.4 TTL 与退出等待
--ttl NUM:出站报文 TTL,默认 255。--wait SECONDS:发送完毕后等待收包多少秒再退出,默认 10 秒;传字符串forever则永不终止。
4.5 离线模式--offline
不真正发包。两种典型用途:
- 配合低速率和
--packet-trace,观察"本应发出的报文"长什么样; - 配合
--rate 100000000做性能基准——衡量假设零开销驱动(如 PF_RING)时的极限吞吐,实测 PF_RING 实际值比离线基准慢约 20%。
4.6 仅列出地址-sL
不做扫描,只生成一串随机地址列表,便于导入其他工具。可与--shard、--resume-index、--resume-count组合使用。
4.7 回归测试--regress
运行回归测试,成功返回 0,失败返回 1。README 中还提到--selftest自检(bin/masscan --selftest),二者共同构成项目的质量保障手段;此外 VULNINFO.md 记载了漏洞赏金计划,项目代码大量使用safe_strcpy()等安全函数替代strcpy()。
五、网络接口与源地址控制
| 选项 | 作用与默认值 |
|---|---|
-e IFNAME/--adapter IFNAME | 指定原始网络接口(如eth0、dna1);不指定时使用第一个带默认网关的接口 |
--adapter-ip IP/--source-ip IP | 指定出站报文的源 IP;不指定时使用接口上第一个 IP。也可给一个范围——注意范围大小必须是 2 的整数次幂(1、2、4、8、16、1024……) |
--adapter-port PORT | 指定源端口;默认在 40000–60000 之间随机选取。建议用主机防火墙(如 iptables)过滤该端口,防止内核协议栈干扰回包。也可给范围(如40000-40003),大小同样必须是 2 的幂 |
--adapter-mac MAC | 指定源 MAC;默认使用接口绑定的第一个 MAC |
--adapter-vlan VLANID | 使用指定的 802.1q VLAN ID 发包 |
--router-mac MAC | 指定目的 MAC(网关);不指定时对接口网关做 ARP 解析 |
--iflist | 列出所有可用网络接口后退出,随后可用-e IFNAME选用其一 |
关于多网卡:当配置了多块网卡时,--echo输出与 resume 文件中会以adapter[0]、adapter[1]这类带索引后缀的参数区分(见 src/main-conf.c 的idx_str处理逻辑),因此多网卡场景的断点续扫也能完整还原适配器配置。
六、Banner 抓取与协议识别
6.1--banners
建立 TCP 连接后抓取 Banner。支持的协议包括:HTTP、FTP、IMAP4、memcached、POP3、SMTP、SSH、SSL、SMB、Telnet、RDP、VNC。
两个注意事项:
- Banner 默认只在服务的标准端口上抓取;
- 可以通过
--hello-string或--hello-file改变这一行为。
6.2 连接超时--connection-timeout SECS
Banner 检查中单条 TCP 连接可保持的最长时间,默认 30 秒。抓取不完整时可调大——例如下载全互联网 SSL 证书链时,有些站点需要较长时间才能发完整条链。警告:该值调大后,快速扫描会消耗大量内存——代码虽可支撑数百万条并发 TCP 连接,但你的内存不一定够。
6.3 自定义问候--hello-file/--hello-string
--hello-file[PORT] FILE:TCP 连接建立后向该端口发送文件内容;需同时开启--banners。程序会对响应做启发式协议识别(HTTP 响应与其他协议的解析方式不同)。--hello-string[PORT] BASE64:与--hello-file相同,但内容是 BASE64 编码字符串,解码后作为问候语发出。
6.4 抓取内容控制--capture/--nocapture
Banner 模式下控制抓取哪些内容:
- 默认只抓 HTML 文档的
TITLE字段;要抓完整文档用--capture html; - SSL 证书默认整条抓取;要关闭用
--nocapture cert; - 当前仅支持
html和cert两个取值,未来会增加更多。
6.5 自定义 HTTP 头
Banner 抓取 HTTP 服务时,可深度定制请求头:
| 选项 | 作用 |
|---|---|
--http-method | 替换请求行中的方法 |
--http-url | 替换请求行中的 URL |
--http-version | 替换请求行中的 HTTP 版本 |
--http-host | 替换Host:头 |
--http-user-agent | 替换User-Agent:头,例如--http-user-agent "Keurig K575 Coffee Maker" |
--http-field NAME:VALUE | 替换已有头部字段,字段不存在则插入(不能改请求行三要素),例如--http-field Accept:image/gif |
--http-field-remove NAME | 删除第一个匹配的字段(Cookie这类可多次出现的字段可能需要重复删除多次) |
--http-cookie VALUE | 追加一个Cookie:字段——其他--http-*都是"替换",这个专用于"追加" |
--http-payload STR | 在头部之后追加负载字符串;会自动补上匹配长度的--http-field Content-Length:LEN,但Content-Type需要你自己加(常用值:application/x-www-form-urlencoded、application/json、text/xml),通常还要配合--http-method POST使用 |
6.6 UDP 负载注入
--pcap-payloads FILE:从 libpcap 抓包文件读取 UDP 报文,提取其负载并按目的端口关联记忆(每端口只记一条),后续向该端口发送 UDP 报文时自动携带该负载;--nmap-payloads FILE:读取与 nmap 的nmap-payloads同格式的文件,得到各端口的 UDP 负载,避免发出空负载的 UDP 报文。
两者功能相似,可互为替代。仓库中 data/afl-http.pcap 与 data/flush_all.pcap 即为可用于载荷分析的抓包样例。
七、输出:格式、文件与实时展示
7.1 状态筛选
--show [open|closed]:指定要显示哪种端口状态——TCP 回 SYN-ACK 的记为open,回 RST 的记为closed。默认只显示open。--noshow [open|closed]:关闭某类状态的显示(如不再显示open)。
7.2 五种输出格式
--output-format FMT支持xml、binary、grepable、list、JSON五种(注意--output-filename必须同时指定);也可以直接用快捷键:
| 快捷键 | 等价写法 | 说明 |
|---|---|---|
-oB FILE | --output-format binary+--output-filename | 二进制格式,文件远小于 XML,需用--readscan事后转回可读格式 |
-oX FILE | --output-format xml+--output-filename | XML,便于导入数据库 |
-oG FILE | --output-format grepable+--output-filename | nmap-oG风格的 grepable 格式,便于命令行工具解析 |
-oJ FILE | --output-format json+--output-filename | JSON |
-oL FILE | --output-format list+--output-filename | 每行一个"主机:端口"对 |
list格式的行结构为:
<port state> <protocol> <port number> <IP address> <POSIX timestamp> open tcp 80 XXX.XXX.XXX.XXX 13903800647.3 二进制结果回放--readscan FILE
读取-oB生成的二进制结果文件,再按命令行参数转成其他格式——例如把二进制转成 XML 或 JSON。注意:使用该选项时,/etc/masscan/masscan.conf的默认配置将不会被读取。
7.4 输出文件管理
--append-output:结果追加到文件而非覆盖,配合--resume续扫时很有用;--rotate TIME:按时间轮转输出文件,用时间戳重命名并移入独立目录。时间可用秒数(3600)或单位(hourly、6hours、10min)。轮转对齐到整数边界——daily会在每天午夜轮转;--rotate-offset TIME:轮转的时间偏移,用于适配时区;--rotate-size SIZE:文件超过指定大小即轮转,支持k/m/g/t后缀;--rotate-dir DIR:轮转时文件移入的目录,推荐/var/log/masscan。
7.5 收包与追踪
--pcap FILE:把收到的报文(不含发出的报文)保存为 libpcap 格式文件;--packet-trace:逐包打印收发摘要——低速率(每秒几包)时很有用,高速率下会刷爆终端;--interactive:在控制台实时显示结果;与--output-format/--output-filename同时使用时无效。
八、配置文件:格式、默认路径与 echo
8.1 加载方式
-c FILE/--conf FILE:读取配置文件;未指定时默认读取/etc/masscan/masscan.conf;--resume FILE:与--conf相同,但会自动设置--append-output等少数选项,用于恢复被 Ctrl-C 中断的扫描(见下文);--echo:不执行扫描,而是把当前配置整体 dump 成配置文件,之后可用-c加载回用。
README 中给出了一个典型工作流:
# masscan -p80,8000-8100 10.0.0.0/8 2603:3001:2d00:da00::/112 --echo > xxx.conf # masscan -c xxx.conf --rate 10008.2 文件格式
配置文件使用与命令行相同的参数名,但去掉--前缀,并用=连接名称与值。man 手册给出的完整示例:
# targets range = 10.0.0.0/8,192.168.0.0/16 range = 172.16.0.0/12 ports = 20-25,80,U:53 ping = true # adapter adapter = eth0 adapter-ip = 192.168.0.1 router-mac = 66-55-44-33-22-11 # other exclude-file = /etc/masscan/exludes.txt要点:
range可写多行,等价于多个目标;ports同样支持U:UDP 前缀;- 默认配置
/etc/masscan/masscan.conf适合存放系统相关设置(如adapter-xxx系列)和排除地址——这样即使扫描全网,也会自动跳过危险网段(如美军/DoD 网段),避免误操作。
README 中的全网扫描配置示例(可直接存为myscan.conf):
# My Scan rate = 100000.00 output-format = xml output-status = all output-filename = scan.xml ports = 0-65535 range = 0.0.0.0-255.255.255.255 excludefile = exclude.txt使用:# masscan -c myscan.conf。README 特别强调:masscan 启动时先加载/etc/masscan/masscan.conf,之后出现的配置参数会覆盖默认配置——因此把excludefile放进默认配置文件里,就能"永远自动生效、永不忘记"。
从源码看(src/main-conf.c),masscan_echo()会完整还原各项参数(rate = %f、resume-index、seed等),参数表同时登记了别名:rate的别名是max-rate,shard的别名是shards。这解释了为什么 README 示例中--max-rate与 man 手册的--rate都能使用。
九、Ctrl-C 行为与断点续扫
9.1 中断与恢复
按下<ctrl-c>后:
- 扫描停止,当前扫描状态保存到
paused.conf; - 程序不会立即退出,而是默认再等 10 秒接收互联网上的回报并保存结果,之后才完全退出——等待时间可用
--wait调整。
恢复扫描:
# masscan --resume paused.conf从源码验证:发送线程检测到min_index < count_ips * count_ports(扫描未完成)时,会记录masscan->resume.index = min_index并调用masscan_save_state()(见 src/main.c 第 1447-1451 行);而masscan_save_state()在 src/main-conf.c 中把状态写入paused.conf并打印saving resume file to: paused.conf。也就是说,paused.conf本质上是当前完整配置 + 断点索引的 echo 快照。
9.2 分段参数
--resume-index INDEX:扫描暂停时的位置点;--resume-count NUM:退出前最多发送的探测包数量。
两者配合可以把一次扫描切成任意小块交给不同实例执行(分片方式见下文)。
十、多机并行:shards 与 resume 切分
man 手册给出了把全网扫描分摊到三台机器的经典做法:
# masscan 0.0.0.0/0 -p0-65535 --shard 1/3 # masscan 0.0.0.0/0 -p0-65535 --shard 2/3 # masscan 0.0.0.0/0 -p0-65535 --shard 3/3--shards X/Y(注意别名为--shard)的含义:x是当前实例编号,y是实例总数。例如--shards 1/2表示"从索引 0 开始每隔一个包发一个";--shards 2/2表示"从索引 1 开始每隔一个包发一个",与前者不重叠。
源码佐证(src/main.c):发送线程的起点为start = masscan->resume.index + (masscan->shard.one-1) * masscan->nic_count + parms->nic_index,循环中i += increment,其中increment = masscan->shard.of * masscan->nic_count——可见 shards 与多网卡(nic_count)在索引空间上是统一的,既可以多机分片,也可以同一台机器多网卡分片。
另一种切分方式利用内部索引:一次扫描的内部索引从 0 到"端口数 × IP 数",配合--resume-index与--resume-count可切成任意大小的块:
# masscan 0.0.0.0/0 -p0-65535 --resume-index 0 --resume-count 1000 # masscan 0.0.0.0/0 -p0-65535 --resume-index 1000 --resume-count 1000 # masscan 0.0.0.0/0 -p0-65535 --resume-index 2000 --resume-count 1000 # masscan 0.0.0.0/0 -p0-65535 --resume-index 3000 --resume-count 1000脚本可以借此把大批量小任务分发到多台机器(如 EC2 实例)上:每完成一个任务块,就向中央协调服务器申请下一块工作。
十一、用户态协议栈与"虚假 RST"问题
11.1 问题根源
masscan 内置了与操作系统协议栈并存的用户态 TCP/IP 协议栈。多数场景下相安无事,但使用--banners建立真实 TCP 连接时容易出问题:如果 masscan 的源 IP 与操作系统相同,内核收到被探测方回应的 SYN-ACK 后会认为"这是别人的连接",随即发出RST 包,把连接掐断在 Banner 抓取之前。最坏情况下,可能要求把协议栈的全部参数都单独指定:
--adapter-port PORT --adapter-ip IP --adapter-mac MAC --adapter-vlan VLANID --router-mac MAC11.2 解法一:防火墙过滤源端口(Linux iptables 示例)
# iptables -A INPUT -i eth0 -p tcp --dport 44444 -j DROP这条规则让 Linux 内核不再处理发往 44444 端口的入站报文,但 masscan 绕过内核协议栈仍然能收到。随后用--adapter-port 44444强制 masscan 使用该端口作为源端口:
# masscan 10.0.0.0/8 -p80 --banners --adapter-port 61234man 手册"SPURIOUS RESETS"一节给出的等价示例:
# iptables -A INPUT -p tcp -i eth0 --dport 61234 -j DROP # masscan 10.0.0.0/8 -p80 --banners --adapter-port 6123411.3 解法二:伪造(spoof)一个空闲源 IP
源 IP 必须落在本网段内、且没有被本机或其他机器占用:
# masscan 10.0.0.0/8 -p80 --banners --adapter-ip 192.168.1.101man 手册明确表示:这样设置源 IP 是运行本扫描器的首选方式(preferred way)。
README 补充了选端口的实操细节:
- Linux 的临时端口范围可查/可改:
/proc/sys/net/ipv4/ip_local_port_range(Kali 2018-08 上为 32768–60999),应选择低于 32768 或高于 60999 的端口; iptables规则重启后失效,需按发行版用iptables-save/iptables-persistent持久化;- macOS/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;新版 macOS/OpenBSD 用pf,在/etc/pf.conf加block in proto tcp from any to any port 40000:40015,再用pfctl -E开启或pfctl -f /etc/pf.conf重载; - Windows 内核不会回 RST,两种技巧都不需要,但仍建议尽可能使用独立 IP;
--heartbleed这类检查本质上是 Banner 检查的一种,同样需要上述处理。
十二、简单示例与实战命令
man 手册的入门示例(可直接复现):
1. 扫描全部私网段找 Web 服务器,只显示 open 端口:
# masscan 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 -p80 --open-only2. 扫描整个互联网的 DNS 服务器(UDP 53),抓取版本并保存 XML:
# masscan 0.0.0.0/0 --excludefile no-dod.txt -pU:53 --banners --output-filename dns.xmlXML 结果可直接导入数据库。
3. 回放二进制结果到控制台:
# masscan --readscan bin-test.scan4. 二进制结果转 XML:
# masscan --readscan bin-test.scan -oX bin-test.xmlREADME 中的组合示例(同时扫 IPv4 与 IPv6 网段):
# 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 可重定向到文件。README 强调:IPv4/IPv6 没有独立模式,可同时混扫,输出位置与格式一致(没有-6选项)。
全网扫描的完整姿势(README):
# masscan 0.0.0.0/0 -p0-65535 --excludefile exclude.txt --max-rate 100000 -oX scan.xml注意:masscan 默认启用了一组与 nmap 兼容的"隐形选项":-sS -Pn -n --randomize-hosts --send-eth。与 nmap 的两点关键差异:没有默认端口(必须显式-p);目标只能是 IP/简单范围,不接受 DNS 名或 nmap 的10.0.0-255.0-255式写法。想查看全部 nmap 兼容选项,运行:
# masscan --nmap十三、性能基准与 IPv6 注意事项
13.1 基准测试
README 的性能测试小节给出了两个避免打爆本地路由器的基准方法:
# 方法一:伪造 router-mac,让报文留在本地网段 $ bin/masscan 0.0.0.0/4 -p80 --rate 100000000 --router-mac 66-55-44-33-22-11 # 方法二:离线模式,衡量去掉发包开销后的纯程序吞吐 $ bin/masscan 0.0.0.0/4 -p80 --rate 100000000 --offline第二个基准近似 PF_RING(近零开销)下的运行速度。README 还提到:随机化算法重度依赖整数运算,现代 CPU 将整数除法速度翻倍,直接让 masscan 变得更快。
13.2 速率警告
README 的"Transmit rate (IMPORTANT!!)"一节:Windows/虚拟机约 30 万包/秒,Linux(非虚拟化)约 160 万包/秒——足以"融化"多数网络。它只可能淹没你自己的网络(目标 IP 已随机化,不会冲垮远端网络)。IPv4 扫描因为遍布大量子网,每个子网收到的流量很小;而 IPv6 常聚焦单一子网,默认行为会压垮目标网络。
13.3 IPv6 建议
- 不要在 IPv6 上扫大段地址;如确需扫描,只扫一个子网内前 64k 个(如 DHCPv6 分配的)地址;
- 更推荐把大量 IPv6 地址写入文件,用
--include-file filename.txt扫描(该文件可同时混含 IPv4/IPv6,README 的测试文件有 800 万条地址,启动时需要多花几秒排序去重); - 运行 masscan 的本机不需要启用 IPv6——只需本地网络能路由 IPv6 报文。
13.4 PF_RING 高速驱动
要突破约 200 万包/秒,需要 Intel 10Gbps 网卡和 ntop 的 "PF_RING ZC" 驱动。masscan无需重新编译即可使用 PF_RING,但需要装齐:
libpfring.so(安装到/usr/lib/libpfring.so)pf_ring.ko(内核驱动)ixgbe.ko(其 Intel 10G 网卡驱动版本)
无需构建他们的libpcap.so。当网卡名是zc:enp1s0这类前缀而非普通enp1s0时,masscan 会自动切换 PF_RING ZC 模式。--pfring选项可强制使用 PF_RING 驱动,驱动不可用则直接退出。
十四、源码级原理:异步架构与 BlackRock 随机化
14.1 异步收发线程
README.md 的 Design 章节与 src/main.c 一致表明:main()中扁平化、注释详尽的transmit_thread()与receive_thread()相互独立,构成异步架构(对 nmap 而言如同 nginx 之于 Apache)。因为无状态、异步,扫描速度完全取决于底层发包能力。
14.2 单索引 + 加密置换
扫描的核心是一个从 0 递增到range = ip_count * port_count的索引变量:
range = ip_count * port_count; for (i = 0; i < range; i++) { x = encrypt(i); // BlackRock 置换 ip = pick(addresses, x / port_count); port = pick(ports, x % port_count); scan(ip, port); }其中pick()负责把索引翻译成 IP(用二分搜索在内存中查找,注意缓存效率);除法和取模约 90 个时钟周期(30ns),而 1000 万包/秒下每包只有 100ns 预算——两个除法可并行执行,所以做两个不比做一个贵。
随机化的方式是对索引做加密:加密天然是"随机且 1:1"的,线性递增的索引经加密后输出完全随机,从而把流量均匀铺开,避免集中轰炸某个目标网络。这一置换正是由 src/crypto-blackrock.c 实现的BlackRock 密码(Feistel 网络,基于 Black & Rogaway 的《Ciphers with Arbitrary Finite Domains》论文):给定[0..N]内任意大小的域,它产出同域内不重复的随机映射。因为只关心速度不关心密码学强度,内部READ()函数刻意做得极简(并带一个 256 字节 S-box)。源码注释明确给出了它在扫描中的用途——"randomize the sequence"。
这一架构带来的能力(README Design 章节):
- shards:多机/多网卡/多源 IP 分摊扫描,各做
range / shard_count; - seed:作为加密密钥改变扫描顺序(
x = encrypt(seed, i)); - 断点续扫:记住当前
i即可(开发者在修 bug 时反复 Ctrl-C/重启); - 重传:以
i + rate作为重传索引,天然实现"约 1 秒后重发"。
14.3 C10M 扩展性
masscan 面向 C10M(千万级并发连接)设计,三大内核绕过手段:
- 自定义网络驱动(PF_RING DNA 直接 DMA,绕过内核,8 块 10Gbps 网卡可支撑每秒上亿包);
- 用户态 TCP 协议栈(轻松支撑 1000 万并发 TCP 连接,前提是内存足够);
- 用户态同步:不使用互斥锁(mutex),改用 ring 队列同步收发线程,避免缓存行颠簸与内核 syscall。
14.4 可移植性
代码以标准 C90 编写,可运行于 Linux、Windows、macOS(Visual Studio / Clang / GCC 均可编译)。Windows/macOS 未针对发包调优,约 30 万包/秒,Linux 约 150 万包/秒。
十五、合规与滥用投诉
man 手册的 ABUSE COMPLAINTS 一节值得全文重视:
- 本工具面向大规模普查,扫描行为一定会被对方日志记录并引发投诉;
- 扫描自己所在组织可能导致被解雇;未经老板书面同意,永远不要扫描本地子网之外的范围;
- 用雇主网络扫描互联网同样容易被解雇;
- 在家用/ISP 网络上扫描,可能因投诉被取消账户;
- 可行的做法:与 ISP 沟通清楚研究意图(研究互联网,而非"入侵"),让 ISP 把投诉直接转给你;对任何提出异议的对象,将其加入
--excludefile永久黑名单不再扫描(有人也会反过来把你加入白名单,让防火墙不再记录你的扫描日志——当然仍会拦截); - 作者的结论:互联网虽是公开端到端网络,但扫描者总是"有罪推定",这一问题无法彻底解决。
data/exclude.conf 中保留的投诉邮件原文(General Dynamics、EGI Hosting、Utah State University 等)就是这一现实的真实注脚,也解释了为何排除列表是全网扫描的第一道安全阀。
十六、快速参考:选项总览
| 类别 | 选项 |
|---|---|
| 目标 | <IP|RANGE>、--range、-iL/--includefile、--exclude、--excludefile、--ping |
| 端口 | -p/--ports(支持U:UDP 前缀) |
| 速率/行为 | --rate、--retries、--seed、--ttl、--wait、--offline、-sL、--regress、--pfring |
| 适配器 | -e/--adapter、--adapter-ip/--source-ip、--adapter-port、--adapter-mac、--adapter-vlan、--router-mac、--iflist |
| Banner | --banners、--connection-timeout、--hello-file[PORT]、--hello-string[PORT]、--capture/--nocapture |
| HTTP 定制 | --http-method/url/version/host/user-agent、--http-field、--http-field-remove、--http-cookie、--http-payload |
| 载荷 | --pcap-payloads、--nmap-payloads |
| 输出 | --show/--noshow、--interactive、--output-format、--output-filename、-oB/-oX/-oG/-oJ/-oL、--readscan、--append-output、--rotate*、--pcap、--packet-trace |
| 配置/续扫 | -c/--conf、--echo、--resume、--resume-index、--resume-count、--shards X/Y |
| 其他 | --nmap |
十七、延伸阅读
- 手册正文:doc/masscan.8.markdown(本文骨架)与 doc/masscan.8(roff 格式)
- 项目总览与设计:README.md
- 配置解析与 echo/resume 实现:src/main-conf.c
- 收发线程与 shards/resume 逻辑:src/main.c
- 随机化置换算法:src/crypto-blackrock.c
- 真实排除列表样例:data/exclude.conf
- 常见问题(速率、丢包、排除列表、服务端日志):doc/faq/README.md
- 安全漏洞信息与赏金计划:VULNINFO.md
免责声明:masscan 是高速扫描工具,仅应在获得明确授权的前提下用于自己的网络或合规的资产普查场景。高速率、大范围的扫描可能违反服务条款、触发安全告警并带来法律风险,请务必参照上文"合规与滥用投诉"一节谨慎使用。
- 网络安全
- 渗透测试
- CLI
【免费下载链接】masscan
TCP port scanner, spews SYN packets asynchronously, scanning entire Internet in under 5 minutes.
相关推荐
Masscan:5分钟扫描整个互联网的终极端口扫描器
Masscan:5分钟扫描整个互联网的终极端口扫描器 Masscan 是一款高性能的互联网级 TCP 端口扫描器,能够在短短5分钟内完成对整个互联网的扫描。作为
网络安全渗透测试CLIMasscan项目推荐:互联网级端口扫描的终极利器
Masscan项目推荐:互联网级端口扫描的终极利器 Masscan 是一款互联网级别的端口扫描工具,能够异步发送SYN数据包,在短短5分钟内完成对整个互联网的扫
网络安全渗透测试CLI如何使用Masscan:5分钟扫描整个互联网的终极端口扫描工具教程
如何使用Masscan:5分钟扫描整个互联网的终极端口扫描工具教程 Masscan是一款高性能的TCP端口扫描工具,能够异步发送SYN数据包,在短短5分钟内完成
网络安全渗透测试CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考