scan4all 中的子网运算利器:mapcidr 全功能解析与实战指南
【免费下载链接】scan4allOfficial repository vuls Scan: 15000+PoCs; 23 kinds of application password crack; 7000+Web fingerprints; 146 protocols and 90000+ rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all
导读
mapcidr 是 ProjectDiscovery 团队开发的一款针对子网 / CIDR 段执行多类运算的实用工具,既可独立作为 CLI 使用,也可作为 Go 库集成到扫描引擎中。在 scan4all 中,mapcidr(依赖版本为v1.1.2,见 go.mod)被用于 httpx、naabu 等子模块的 CIDR 展开、地址计数、子网合并与 IP 流式生成。读完本文,你将掌握 mapcidr 的 CIDR 展开、切片、聚合、匹配/过滤、IP 格式转换、乱序打乱等全部能力,并了解它在 scan4all 内部的实际调用方式与底层原理。
功能总览
mapcidr 的核心定位是为大规模扫描操作分担负载:把一段段 CIDR 精确地展开成目标 IP、再按需切片分发给不同扫描节点。其支持的功能包括:
- CIDR 展开(默认行为):把 CIDR 展开为逐个 IP
- CIDR 切片(
sbh、sbc):按 CIDR 数量或主机数量切分 - CIDR/IP 聚合(
a、aa):合并为最小子网 - CIDR/IP 匹配(
match-ip):从 CIDR 中匹配指定 IP - CIDR/IP 过滤(
filter-ip):从 CIDR 中剔除指定 IP - CIDR/IP 排序(
s、sr):升序 / 降序排列 - CIDR 主机计数(
count):统计地址数量 - 多种 IP 格式(
ip-format):十进制、八进制、十六进制等 - IP/PORT 乱序(
si、sp):随机打乱 - IPv4 / IPv6 互转(
t4、t6) - STDIN 管道输入:支持
echo ... | mapcidr方式
安装方式
mapcidr 是标准的 Go 工具,直接使用go install即可:
go install -v github.com/projectdiscovery/mapcidr/cmd/mapcidr@latest在 scan4all 项目中它作为依赖被打入 vendor 目录(vendor/github.com/projectdiscovery/mapcidr/README.md),因此无需单独安装即可随 scan4all 一起编译使用。
命令行参数全解析
运行mapcidr -h可以查看全部参数。以下按功能分组整理:
INPUT: -cl, -cidr string[] CIDR/IP/File containing list of CIDR/IP to process PROCESS: -sbc int Slice CIDRs by given CIDR count -sbh int Slice CIDRs by given HOST count -a, -aggregate Aggregate IPs/CIDRs into minimum subnet -aa, -aggregate-approx Aggregate sparse IPs/CIDRs into minimum approximated subnet -c, -count Count number of IPs in given CIDR -t4, -to-ipv4 Convert IPs to IPv4 format -t6, -to-ipv6 Convert IPs to IPv6 format -ip-format, -if string[] IP formats (0,1,2,3,4,5,6,7,8,9,10,11) -zpn, -zero-pad-n int number of padded zero to use (default 3) -zpp, -zero-pad-permute enable permutations from 0 to zero-pad-n for each octets FILTER: -f4, -filter-ipv4 Filter IPv4 IPs from input -f6, -filter-ipv6 Filter IPv6 IPs from input -skip-base Skip base IPs (ending in .0) in output -skip-broadcast Skip broadcast IPs (ending in .255) in output -mi, -match-ip string[] IP/CIDR/FILE containing list of IP/CIDR to match (comma-separated, file input) -fi, -filter-ip string[] IP/CIDR/FILE containing list of IP/CIDR to filter (comma-separated, file input) MISCELLANEOUS: -s, -sort Sort input IPs/CIDRs in ascending order -sr, -sort-reverse Sort input IPs/CIDRs in descending order -si, -shuffle-ip Shuffle Input IPs in random order -sp, -shuffle-port string Shuffle Input IP:Port in random order UPDATE: -up, -update update mapcidr to latest version -duc, -disable-update-check disable automatic mapcidr update check OUTPUT: -verbose Verbose mode -o, -output string File to write output to -silent Silent mode -version Show version of the project几点使用注意:
-cl的输入可以是 CIDR、单个 IP 或包含二者的文件路径;-mi/-fi支持逗号分隔的 IP/CIDR 列表,也支持文件输入;-ip-format用0表示展示全部支持格式,其余数字(1~11)表示展示指定格式;- 默认启动时会显示 banner 与免责声明,
-silent可关闭多余输出,便于脚本化处理。
核心功能实战
CIDR 展开(默认行为)
将单个 CIDR 展开为 IP 列表:
mapcidr -cidr 173.0.84.0/24输出示例(默认带 banner):
173.0.84.0 173.0.84.1 173.0.84.2 173.0.84.3 173.0.84.4 173.0.84.5 173.0.84.13 173.0.84.14 173.0.84.15 173.0.84.16也支持 IP 区间输入,通过管道喂给 mapcidr:
$ echo "192.168.0.0-192.168.0.5" | mapcidr输出:
192.168.0.0 192.168.0.1 192.168.0.2 192.168.0.3 192.168.0.4 192.168.0.5从源码层面看,CIDR 展开的核心实现在 vendor/github.com/projectdiscovery/mapcidr/cidr.go:IPAddresses将 CIDR 解析为net.IPNet后,通过IpAddresses返回一个流式 channel,逐 IP 通过GetNextIP递增产出。这种流式设计保证即使是超大网段也不会一次性吃满内存——scan4all 的 naabu 模块正是利用这一特性进行内存友好的端口扫描。
按 CIDR 数量切片(-sbc)
将给定的 CIDR 切成指定数量的等分子网:
mapcidr -cidr 173.0.84.0/24 -sbc 10 -silent输出:
173.0.84.0/27 173.0.84.32/27 173.0.84.64/27 173.0.84.96/27 173.0.84.128/27 173.0.84.160/27 173.0.84.208/28 173.0.84.192/28 173.0.84.240/28 173.0.84.224/28底层对应SplitN/SplitIPNetIntoN(见 cidr.go):当切片数 n 是 2 的幂时直接按位划分;否则会先取小于 n 的最大 2 次幂划分,再通过divideIPNet逐级对最后一个子网做二分,直到凑够 n 个子网。
按主机数量切片(-sbh)
将 CIDR 按每段包含指定数量主机的方式切分:
mapcidr -cidr 173.0.84.0/16 -sbh 20000 -silent输出:
173.0.0.0/18 173.0.64.0/18 173.0.128.0/18 173.0.192.0/18注意:只有当期望的切片数量或每子网主机数为 2 的幂时,才能得到完美切分;否则工具会自动寻找最优切分策略逼近目标值。对应实现为SplitByNumber/SplitIPNetByNumber(cidr.go):先算总地址数,用总地址数 / 每段主机数得到目标子网数,再委托给SplitIPNetIntoN完成二分切分。
CIDR/IP 聚合
将多个 CIDR 合并为更小的子网块:
$ mapcidr -cl cidrs.txt -aggregate将 IP 列表转换为 CIDR 块:
$ mapcidr -il ips.txt -aggregate对于稀疏 IP 组,还可以使用近似聚合(仅支持 IPv4)。最终区间会包含不属于输入的连续 IP:
$ cat ips.txt 1.1.1.1 1.1.1.16 1.1.1.31$ cat ips.txt | mapcidr -aggregate-approx 1.1.1.0/27IP 区间也可以直接聚合(同时支持 IPv4 与 IPv6):
$ mapcidr -cl 192.168.0.1-192.168.0.255 -aggregate OR $ echo 192.168.0.1-192.168.0.255 | mapcidr -aggregate输出:
192.168.0.1/32 192.168.0.2/31 192.168.0.4/30 192.168.0.8/29 192.168.0.16/28 192.168.0.32/27 192.168.0.64/26 192.168.0.128/25聚合的底层实现集中在 vendor/github.com/projectdiscovery/mapcidr/ip.go:
CoalesceCIDRs先把每个 CIDR 转成[First, Last]区间,按区间排序后用mergeAdjacentCIDRs合并相邻段,最后经rangeToCIDRs/createSpanningCIDR把区间还原为 CIDR 列表,并分别输出 IPv4、IPv6 两组结果;AggregateApproxIPV4s(ip.go)则把同一 /24 段内的 IP 按位异或归并,用最小的前缀长度覆盖输入 IP,这正是-aggregate-approx的实现。
从 CIDR 中匹配 / 过滤 IP
匹配出指定 CIDR 列表范围内的 IP:
$ mapcidr -cidr 192.168.1.0/24 -mi 192.168.1.253,192.168.1.252 $ mapcidr -cidr 192.168.1.0/24 -mi ip_list_to_match.txt从 CIDR 中剔除指定 IP:
$ mapcidr -cidr 192.168.1.224/28 -fi 192.168.1.233,192.168.1.234 $ mapcidr -cidr 192.168.1.224/28 -fi ip_list_to_filter.txtIP 多格式输出
-if 0可以一次性展示某个 IP 支持的全部格式,具体索引值可通过-if <索引>单独输出。当前共支持 10 余种格式:
$ echo 127.0.1.0 | mapcidr -if 0 -silent输出:
127.0.1.0 127.1 0177.0.01.0 0x7f.0x0.0x1.0x0 0x7f000100 0xabfa659dfa7f000100 281472812450048 111111111111111101111111000000000000000100000000 0x7f.0.01.0x0 ::ffff:7f00:0100 %31%32%37%2E%30%2E%31%2E%30 127.000.001.000这些格式在源码中由AlterIP函数实现(见 ip.go),涵盖:
- 标准点分十进制(格式 1)
- 零值省略表示(格式 2,如
127.0.1.0→127.1) - 八进制表示(格式 3)
- 十六进制点分 / 单值 / 带随机前缀(格式 4)
- DWORD 十进制(格式 5)
- 二进制(格式 6)
- 混合进制(格式 7)
- IPv6 表示(格式 8)
- URL 编码(格式 9)
多格式输出对 WAF 绕过、IP 混淆类测试(如 fuzz、SSRF 探测)非常实用。
IP 转换(IPv4 ↔ IPv6)
-t4/-t6分别在 IPv4 与 IPv6 表示之间转换:
$ cat ips.txt 1.1.1.1 2.2.2.2$ mapcidr -cl ips.txt -t6 00:00:00:00:00:ffff:0101:0101 00:00:00:00:00:ffff:0202:0202注意:并非所有 IPv6 地址都能转换为 IPv4,只有合法的 IPv4 映射(IPv4-mapped)形式的 IPv6 地址才能转换。对应实现为
ToIP4/ToIP6(ip.go),内部基于net.ParseIP判断地址族后调用To16()/To4()完成转换。
CIDR 主机计数
统计一个或多个 CIDR 内的主机数:
$ echo 173.0.84.0/16 | mapcidr -count -silent 65536计数底层对应AddressCount/AddressCountIpnet(cidr.go),计算公式为1 << (总位数 - 前缀长度),即2^(32-prefix)。
ASN 输入
直接输入 ASN 号即可展开为其所属的全部 IPv4 地址:
echo AS15133 | mapcidr -silent输出示例:
5.104.64.0 5.104.64.1 5.104.64.2 5.104.64.3 5.104.64.4该功能由 vendor/github.com/projectdiscovery/mapcidr/asn/asn.go 实现:IsASN负责识别AS前缀加数字的输入,GetCIDRsForASNNum通过 asnmap 客户端拉取该 ASN 的 CIDR 列表并过滤出 IPv4 段,最终经GetIPAddressesAsStream以流式 channel 产出所有 IP。
将 mapcidr 作为 Go 库使用
mapcidr 可以直接集成进 Go 程序。以下示例演示如何把 CIDR 切成子网、按主机数切分,以及展开全部 IP:
package main import ( "fmt" "github.com/projectdiscovery/mapcidr" ) func main() { // Divide the CIDR into two subnets subnets1 := mapcidr.SplitN("192.168.1.0/24", 2) for _, subnet := range subnets1 { fmt.Println(subnet) } // Divide the CIDR into two subnets containing 128 hosts each subnets2 := mapcidr.SplitByNumber("192.168.1.0/24", 128) for _, subnet := range subnets2 { fmt.Println(subnet) } // List all ips in the CIDR ips, _ := mapcidr.IPAddresses("192.168.1.0/24") for _, ip := range ips { fmt.Println(ip) } }除了 README 中的这几个 API,库内还提供了大量可直接复用的函数:
- 区间与计数:
AddressRange返回网段首尾 IP;TotalIPSInCidrs统计多网段总 IP 数(utils.go) - 集合运算:
RemoveCIDRs从一组 CIDR 中扣减另一组 CIDR;CoalesceCIDRs合并最小化 CIDR;KeepUniqueIPs去重并排序(ip.go) - 网络号 / 广播地址判断:
IsBaseIP(以.0结尾)与IsBroadcastIP(以.255结尾),对应 CLI 的-skip-base/-skip-broadcast(utils.go) - 整数互转:
Inet_aton/Inet_ntoa在 IP 与 int64 之间转换,naabu 模块正是借助它们实现按索引取子网内 IP(ip.go) - 乱序打乱:
ShuffleCidrsWithSeed/ShuffleCidrsWithPortsAndSeed基于 blackrock 加密算法,在不生成完整 IP 列表的前提下,以随机顺序访问所有 IP(以及 IP:端口组合)(shuffle.go)
mapcidr 在 scan4all 中的实际应用
mapcidr 并非孤立存在,它在 scan4all 的多个核心扫描子模块中被深度使用,以下是可验证的源码调用点:
httpx 子模块:CIDR 计数与展开
在 pkg/httpx/runner/runner.go 中,httpx 读取目标列表时会对 CIDR 类目标调用mapcidr.AddressCount计算其包含的 IP 数量,用于精确统计待探测目标总量:
if iputil.IsCIDR(target) { // so we need to count the ips if ipsCount, err := mapcidr.AddressCount(target); err == nil && ipsCount > 0 { expandedTarget = int(ipsCount) } }在 pkg/httpx/runner/runner.go 附近,httpx 通过mapcidr.IPAddresses(target)将 CIDR 展开为 IP 列表后逐一发起 HTTP 探测。
naabu 子模块:流式展开、合并与索引取 IP
naabu(端口扫描器)对 mapcidr 的利用更深入:
- pkg/naabu/v2/pkg/runner/runner.go 与 同文件 L291 调用
mapcidr.IPAddressesAsStream以流式 channel 方式逐 IP 产出,保证大网段扫描时内存可控; - L344 调用
mapcidr.CoalesceCIDRs对目标 CIDR 做最小化合并,减少重复扫描; - L347 与 L474 使用
mapcidr.AddressCountIpnet统计每个子网的地址数; - L485 使用
mapcidr.Inet_ntoa(mapcidr.Inet_aton(network.IP) + index)实现按索引在子网内取特定 IP,这是分片扫描任务分配的关键一环。
这种"先聚合去重、再按索引分片、最后流式取 IP"的组合,正是 mapcidr 为大规模分布式扫描提供负载均衡能力的典型应用模式。
小结
mapcidr 把 CIDR 运算中最常用也最易出错的细节——二进制边界对齐、2 的幂切分、区间与 CIDR 互转、流式展开、随机乱序——全部封装成简单直观的 CLI 参数与库 API。在 scan4all 中,无论是 httpx 的目标计数与展开,还是 naabu 的分片扫描,都依赖它的底层能力。掌握 mapcidr,也就掌握了子网级目标治理的通用方法论,可以直接复用到任何需要批量 IP 处理、负载均衡扫描或 IP 混淆测试的场景中。
【免费下载链接】scan4allOfficial repository vuls Scan: 15000+PoCs; 23 kinds of application password crack; 7000+Web fingerprints; 146 protocols and 90000+ rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考