从代码角度看各类子域名收集工具
字数 3334 2025-08-15 21:31:44
子域名收集工具技术分析与使用指南
目录
子域名收集工具概述
子域名收集是渗透测试和信息收集的重要环节,本文从代码角度分析各类开源子域名收集工具的技术特点、优缺点及适用场景。主要分析工具包括:subDomainBrute、Sublist3r、ESD、OneForAll、dnsprobe、subfinder、shuffledns和massdns。
主流子域名收集工具详解
subDomainBrute
基本信息:
- GitHub: https://github.com/lijiejie/subDomainsBrute
- 首次发布:2015年
- 语言:Python(支持Python3)
技术特点:
- 纯DNS爆破:通过字典爆破方式发现子域名
- 高性能设计:
- Python3使用asyncio+aiodns进行异步DNS查询
- Python2使用dnspython+gevent
- DNS服务器测试:
- 启动时自动测试DNS服务器可用性
- 测试逻辑:
- 测试public-dns-a.baidu.com返回180.76.76.76为正确DNS
- 测试test.bad.dns.lijiejie.com应抛出异常
- 局限性:
- 无泛域名处理功能,遇到泛解析直接退出
使用建议:
- 适合需要稳定、简单DNS爆破的场景
- 依赖较少,安装简单
Sublist3r
基本信息:
- GitHub: https://github.com/aboul3la/Sublist3r
- 首次发布:2015年
- 语言:Python
技术特点:
- 混合收集方式:
- 暴力破解(使用subbrute模块)
- 搜索引擎和API枚举
- 支持的搜索引擎:
supported_engines = { 'baidu': BaiduEnum, 'yahoo': YahooEnum, 'google': GoogleEnum, 'bing': BingEnum, 'ask': AskEnum, 'netcraft': NetcraftEnum, 'dnsdumpster': DNSdumpster, 'virustotal': Virustotal, 'threatcrowd': ThreatCrowd, 'ssl': CrtSearch, 'passivedns': PassiveDNS } - 爆破模块特点:
- 使用开放式解析器作为代理规避DNS速率限制
- Windows下仅使用线程,效率较低
- 泛解析检测:
- 使用随机UUID字符串作为测试子域名
- 优势:
- 可通过pip安装,便于集成
使用建议:
- 适合需要快速安装使用的场景
- 作为Python包集成到其他工具中
ESD
基本信息:
- GitHub: https://github.com/FeeiCN/ESD
- 语言:Python
技术特点:
- 创新技术:
- RSC(响应相似度对比)技术处理泛解析
- 基于aioHTTP获取不存在子域名的响应内容
- 与字典子域名响应进行相似度比对(阈值0.8)
- 高性能:
- 基于AsyncIO异步协程技术
- 比传统多进程/多线程快50%以上
- 示例:扫描qq.com(170083条规则)耗时约163秒
- 全面字典:
- 融合各类字典,去重后170083条
- 包括通用字典、DNS提供商公布常用子域名等
- 多种收集渠道:
- DNSPod接口泄露
- 页面响应内容
- 跳转过程
- HTTPS证书透明度
- DNS域传送
- 搜索引擎
- ZoomEye、Censys、FOFA、Shodan接口
- DNS服务器优化:
- 解决DNS服务商网络线路出口判定不一致问题
- 解决缓存时间不一致问题
- 解决随机DNS问题
- 自动剔除无效DNS
关键技术实现:
-
DNS域传送漏洞检测:
class DNSTransfer(object): def __init__(self, domain): self.domain = domain def transfer_info(self): ret_zones = list() try: nss = dns.resolver.query(self.domain, 'NS') nameservers = [str(ns) for ns in nss] ns_addr = dns.resolver.query(nameservers[0], 'A') zones = dns.zone.from_xfr(dns.query.xfr(ns_addr, self.domain, relativize=False, timeout=2, lifetime=2), check_origin=False) # ...处理返回结果... except BaseException: return [] -
HTTPS证书透明度获取子域名:
class CAInfo(object): def __init__(self, domain): self.domain = domain def get_ca_domain_info(self): domain_list = list() try: ip = self.dns_resolve() cert_data = self.get_cert_info_by_ip(ip) for domain_info in cert_data: hostname = domain_info[1] if not hostname.startswith('*') and hostname.endswith(self.domain): domain_list.append(hostname) except Exception as e: return domain_list -
纯socket实现的DNS服务器检测:
def check(self, dns): msg = b'\x5c\x6d\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x05baidu\x03com\x00\x00\x01\x00\x01' sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(3) for i in range(3): sock.sendto(msg, (dns, 53)) try: sock.recv(4096) break except socket.timeout as e: if i == 2: return False return True -
基于文本相似度过滤泛解析域名:
from difflib import SequenceMatcher # RSC ratio self.rsc_ratio = 0.8 self.wildcard_html # 获取一个随机子域名的html ratio = SequenceMatcher(None, html, self.wildcard_html).real_quick_ratio() ratio = round(ratio, 3) if ratio > self.rsc_ratio: # passed logger.debug('{r} RSC ratio: {ratio} (passed) {sub}'.format( r=self.remainder, sub=sub_domain, ratio=ratio)) else: # added pass
局限性:
- RSC技术消耗大量内存和CPU资源
- Windows兼容性问题(路径硬编码为/tmp/esd)
使用建议:
- 适合集成到扫描器中
- 机器性能要求较高
OneForAll
基本信息:
- GitHub: https://github.com/shmilylty/OneForAll
- 语言:Python3(要求3.8+)
功能特点:
- 多功能集成:
- 被动搜索域名
- 子域爆破
- 子域接管检测
- 端口探测
- 指纹识别
- 结果导出
- 被动搜索:
- 集成大量Web接口
- 通用域名匹配函数:
def match_subdomains(domain, html, distinct=True, fuzzy=True): if fuzzy: regexp = r'(?:[a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])?\.){0,}' + domain.replace('.', r'\.') result = re.findall(regexp, html, re.I) deal = map(lambda s: s.lower(), result) return set(deal) if distinct else list(deal)
- 泛解析处理:
- 基于DNS泛解析返回的TTL相同特性
- 参考技术:http://sh3ll.me/archives/201704041222.txt
- 爆破流程:
wildcard_ips = list() # 泛解析IP列表 wildcard_ttl = int() # 泛解析TTL整型值 ns_list = query_domain_ns(self.domain) # 查询域名NS记录 ns_ip_list = query_domain_ns_a(ns_list) # DNS权威名称服务器对应A记录列表 self.enable_wildcard = detect_wildcard(domain, ns_ip_list) # 检测泛解析 if self.enable_wildcard: wildcard_ips, wildcard_ttl = collect_wildcard_record(domain, ns_ip_list) ns_path = get_nameservers_path(self.enable_wildcard, ns_ip_list) # 生成字典并调用massdns扫描 - 域名接管检测:
- 针对公共服务商的域名接管
- 指纹识别规则示例:
[ { "name":"github", "cname":["github.io", "github.map.fastly.net"], "response":["There isn't a GitHub Pages site here."] }, { "name":"heroku", "cname":["herokudns.com", "herokussl.com", "herokuapp.com"], "response":["There's nothing here, yet."] } ]
- 指纹识别:
- 使用https://github.com/webanalyzer/rules
- 集成fofa、wappalyzer、whatweb的指纹
- 仅使用多进程(未用协程)
局限性:
- 依赖较多(requirements.txt有38行)
- Python版本要求高(3.8+)
- 部分功能效率不高
使用建议:
- 适合对新域名进行全面收集
- 结果较为全面
dnsprobe
基本信息:
- GitHub: https://github.com/projectdiscovery/dnsprobe
- 语言:Go
技术特点:
- 高效设计:
- Go语言协程实现高并发
- 边读字典边爆破,减少IO等待
- 跨平台:
- 静态编译,各平台兼容性好
- 使用示例:
subfinder -d hackerone.com -silent | dnsprobe -f domain.txt
优势:
- 性能优异
- 使用简单
subfinder
基本信息:
- GitHub: https://github.com/projectdiscovery/subfinder
- 语言:Go
技术特点:
- 专注被动枚举:
- 通过各类接口发现子域名
- 支持的接口:
var DefaultSources = []string{ "alienvault", "archiveis", "binaryedge", "bufferover", "censys", "certspotter", "certspotterold", "commoncrawl", "crtsh", "digicert", "dnsdumpster", "dnsdb", "entrust", "hackertarget", "ipv4info", "intelx", "passivetotal", "rapiddns", "securitytrails", "shodan", "sitedossier", "spyse", "sublist3r", "threatcrowd", "threatminer", "urlscan", "virustotal", "waybackarchive", "zoomeye", } - 插件架构:
- 每个接口实现Source接口
- 统一调用Run方法执行
优势:
- 被动收集,隐蔽性好
- 适合与其他工具配合使用
shuffledns
基本信息:
- GitHub: https://github.com/projectdiscovery/shuffledns
- 语言:Go
技术特点:
- 基于massdns封装
- 主要处理massdns的返回结果
massdns
基本信息:
- GitHub: https://github.com/blechschmidt/massdns
- 语言:C
技术特点:
- 高性能DNS解析:
- 每秒可解析超过350,000个名称
- 底层技术:
- socket发包
- epoll/pcap/busy-wait polling接收
- 无状态扫描技术:
- 理论速度可达70w/s
优势:
- 性能极致
- 适合大规模爆破
技术要点解析
泛域名解析处理
-
常见解决方案:
- RSC(响应相似度对比)技术
- TTL相同特性检测
- 黑名单IP过滤
-
TTL检测原理:
- 权威DNS中泛解析记录的TTL相同
- 如果子域名记录相同但TTL不同,则不是泛解析记录
- 示例判断逻辑:
func IsPanDNSRecord(record string, ttl uint32) bool { _ttl, ok := panDNSRecords[TrimSuffixPoint(record)] if !ok || (_ttl != ttl && _ttl%60 == 0 && ttl%60 == 0) { return false } return true }
DNS服务器选择
-
关键因素:
- 数量:推荐1w字典对应1个DNS服务器
- 质量:响应速度、稳定性
- 分布:不同网络线路的DNS
-
测试方法:
- 验证DNS是否能正确解析已知域名
- 验证DNS是否会错误解析不存在的域名
性能优化技术
-
并发模型:
- Python: asyncio/gevent协程+多进程
- Go: 原生协程
- C: epoll/pcap
-
IO优化:
- 边读字典边扫描(减少IO等待)
- 异步文件读取(aiofiles)
-
网络优化:
- 使用开放式解析器规避速率限制
- 自动剔除无效DNS服务器
工具组合推荐
-
推荐组合:
subfinder -d hackerone.com -silent | dnsprobe -f domain.txt- subfinder:被动收集
- dnsprobe:验证和爆破
-
适用场景:
- 快速收集:subfinder + dnsprobe
- 全面收集:OneForAll
- 集成开发:ESD
- 高性能爆破:massdns/shuffledns
最佳实践建议
-
DNS服务器配置:
- 准备足够数量的优质DNS服务器
- 定期测试DNS服务器有效性
-
字典选择:
- 根据目标特点选择合适字典
- 合并多源字典并去重
-
性能调优:
- 根据机器性能调整并发数
- 监控资源使用情况,避免过度消耗
-
结果验证:
- 对收集结果进行去重和验证
- 注意过滤泛解析导致的误报
-
法律合规:
- 仅在授权范围内使用
- 控制扫描频率,避免对目标造成影响
通过合理选择和组合这些工具,可以高效完成子域名收集任务,为后续安全测试奠定基础。