做资产测绘或者授权攻防评估的时候,子域名收集永远是最先动手的一步。很多人来问过我,Amass和Subfinder到底应该选哪个。我的答案很直接:别选,两个都装。Amass擅长把攻击面完整铺开,内置数据源多,能做主动枚举和字典爆破;Subfinder赢在速度快、被动收集干净,配置文件也简单。两个工具搭在一起,既能明显缩短一轮收集的耗时,又能把单工具的遗漏率降下来。这篇文章主要给做资产梳理、SRC测试、攻防演练准备的人看,我会从分工逻辑、安装配置、集成模式、实战流程、脚本自动化到高频踩坑,完整讲一遍这两个工具怎么深度配合。
1. 两个工具的分工:Amass管面,Subfinder管快
1.1 为什么不是二选一,而是互补
先说结论:Amass和Subfinder在功能上有大量交集,但设计目标完全不同。Subfinder是ProjectDiscovery社区的作品,定位非常纯粹——通过被动数据源快速发现子域名,不主动向目标发送查询流量,跑起来轻盈、输出干净。Amass则是OWASP旗下的攻击面测绘工具,它的定位不是"子域发现"这一件事,而是把整个外部资产关系网铺开:DNS记录、TLS证书、历史关联域名、API数据源、主动爆破,全部揉在一起,输出结构化的测绘结果。
很多新手会陷入一个误区,觉得"只要Amass就够了"或者"Subfinder更快,没必要用大而全的工具"。实际跑过一轮就会明白:Subfinder分钟级出结果,Amass可能跑了十几分钟还在扫;但Subfinder漏掉的子域,Amass往往能通过更多数据源和主动探测补回来。反过来,如果每次只跑Amass,节奏会慢到拖垮整个项目。
还有一层容易被忽略:两个工具的API数据源并不完全重叠。同一个域名,Subfinder可能从某个被动源拿到一条记录,而Amass从另一个数据源拿到完全不同的记录。所以"叠加使用"不是重复劳动,而是互相查漏补缺。
1.2 数据源与输出粒度的差异
具体拆开看,两者的差异主要体现在三块:
数据源接入方式不同。Subfinder通过YAML配置文件(provider-config.yaml)接入VirusTotal、Shodan、Censys、Fofa等几十个数据源,每个源只需要填入API密钥;Amass则通过INI格式的config.ini管理数据源,同样可以填VirusTotal、Shodan这些,但它还会结合主动采集能力,比如从DNS服务器差异、证书透明度日志、搜索引擎快照等维度做关联分析。
输出格式不一样。Subfinder默认只输出纯域名列表,适合直接进入下一步工具做存活校验;Amass默认支持CSV、JSON输出,除了域名还会附带发现来源、关联记录、首次发现时间等字段。做攻击面测绘时,Amass的CSV很有用,能追溯某条子域是从哪个数据源挖出来的;做快速筛选时,Subfinder的纯文本更友好。
主动与被动模式的分工。Subfinder基本只做被动收集,不主动向目标基础设施发包,所以不容易触发告警。Amass的
-active模式会主动解析域名、尝试区域传送、抓取TLS证书信息,信息更全,但也意味着会产生真实流量。两者配合的典型策略就是:先用Subfinder做快速被动摸底,再让Amass针对已发现的子域做更重的主动测绘。
这里顺便强调一句:所有枚举、爆破、主动探测,都必须在目标所有方授权的范围内进行。资产测绘和渗透测试一样,边界不清的操作本身就有风险。
2. 环境准备和配置文件:最容易卡住人的地方
2.1 安装方式与版本陷阱
Amass和Subfinder的安装都不复杂,但版本坑不少。Subfinder是Go语言写的,老教程喜欢让你go get,现在更推荐直接去GitHub Releases页面下载对应平台的二进制,或者用包管理器:macOS上可以用Homebrew,Linux发行版如果有官方仓库也可以直接装。Amass同理,建议直接用release二进制,免去GOPATH、依赖版本等一堆环境问题。
如果用go install方式装,有个经典坑:安装完成后shell找不到命令。原因基本是GOPATH/bin不在PATH环境变量里。我一般在~/.bashrc里加上:
export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin装完先跑一下版本号确认:
amass -version subfinder -version注意Amass v4.x的早期版本和v3.x参数差异很大,网上很多旧教程还在写-whois、-brute这类老参数的位置,并不完全通用。我的建议是:装完先看amass -h和subfinder -h,以帮助文档为准,别照着两三年前的博客盲操作。
2.2 Amass数据源配置:config.ini的格式与常见错误
Amass默认读取~/.config/amass/config.ini,也可以随时用-config参数指定自定义路径。配置文件是INI格式,结构大概这样:
[data_sources] [data_sources.VirusTotal] apikey="你的密钥" [data_sources.Shodan] apikey="你的密钥" [data_sources.Censys] id="你的ID" secret="你的Secret"这个文件本身不难,但我在帮人排查时发现几个高频错误:
- 复制粘贴密钥时带上了多余空格或引号,导致API认证失败。
- 把多个密钥写在同一行,改成分行后忘了调整语法。
- 更新了密钥但没重启终端,或者没指定
-config路径,实际还是走了默认空配置。
验证配置是否生效有个笨办法:跑一次被动枚举,打开verbose日志,看数据源有没有被加载。比如:
amass enum -passive -d example.com -config config.ini -v日志里会显示当前启用了多少个数据源。如果数字少得可怜,基本就是配置解析出了问题。
2.3 Subfinder数据源配置:YAML缩进本身就是坑
Subfinder的配置文件默认路径是~/.config/subfinder/provider-config.yaml,内容大概是:
shodan: - 你的密钥 virustotal: - 你的密钥 censys: - 你的ID - 你的SecretYAML对缩进极度敏感,必须用两个空格作为层级缩进,不能用Tab。很多人在这一步卡住,最后发现是-列表项前面多了一个空格,或者某个key和后面的值没对齐。
我建议最稳妥的做法是:不要手动从零写,先运行一次subfinder -provider-config生成默认模板,然后在模板基础上改。改完再跑:
subfinder -d example.com -pc provider-config.yaml -v确认日志里没有红色报错,并且有"x active sources"这样的加载提示,就说明配置生效了。
2.4 两套配置放在一个工作目录里管理
因为两个工具的配置格式完全不同,我在实际项目中习惯建一个subdomain_toolkit工作目录,里面单独放一套配置,避免污染全局:
subdomain_toolkit/ ├── configs/ │ ├── amass_config.ini │ └── provider_config.yaml ├── wordlists/ ├── outputs/ └── scripts/每次工作就固定用一套命令参数指定到工作目录下的文件。这样换机器、换项目、交给同事接手都很方便,不会出现"跑起来用的还是系统旧配置"这种问题。
3. 三种可落地的集成模式
3.1 快速预筛加深度测绘:先Subfinder后Amass
这是我最常用的模式,也是逻辑最顺的一种。第一轮:Subfinder做被动预筛,把子域列表在几十秒内拉出来。
subfinder -d example.com -all -silent -o outputs/round1_subfinder.txt-all表示使用所有已配置的数据源,-silent让输出干净到只有域名列表。这一步得到的是基础资产面。
第二轮:把第一轮的结果作为Amass的根域列表,做深度枚举。注意这里不是让Amass去爆破第一轮的每个子域,而是把发现的子域交给Amass做关联分析,Amass会基于这些子域继续挖关联域名、证书信息和历史记录。
amass enum -passive -active -df outputs/round1_subfinder.txt -config configs/amass_config.ini -timeout 20 -o outputs/round2_amass.txt-df指定根域名文件,一个域名一行;-timeout是分钟级的超时控制。为什么要把Subfinder的结果喂给Amass而不是让Amass从头跑?核心原因是:Amass通过子域之间的关联关系(比如相同证书、相同解析记录、相同所有者信息)能挖出更多同源资产,只给根域名的话,它会错过不少隐藏在已知子域背后的线索。
3.2 直接合并去重:最粗暴但最有效的模式
如果不想搞那么重的二级联动,直接把两个工具的输出合并去重,也能立刻提升覆盖度。
cat outputs/round1_subfinder.txt outputs/round2_amass.txt | sort -u > outputs/all_subdomains.txtsort -u能顺便处理大小写问题(严格来说大小写敏感,但DNS域名通常会被降级处理)。如果还想更严谨一点,可以做一次小写统一:
cat outputs/round1_subfinder.txt outputs/round2_amass.txt | tr 'A-Z' 'a-z' | sort -u > outputs/all_subdomains.txt这一步看似简单,但效果立竿见影。我之前在一个授权资产项目里,单独跑Subfinder得到约900条子域,单独跑Amass得到约1100条,合并去重后是1500多条,说明两个工具的交集只有一半左右。不合并,等于丢掉三成资产。
3.3 用Amass子命令做长期追踪:intel/track的补充价值
Amass不只是enum一个命令,intel和track在集成工作流里也有位置。intel负责查关联数据,比如用whois、反向DNS等做前期侦察:
amass intel -d example.comtrack则适合做周期性对比,记录同一域名在某个时间段内新增或移除的子域,前提是Amass的数据库开启状态。平时做项目报告时,track能给出"这个月新增了哪些子域、下线了哪些资产"的直观差异,配合Subfinder的快速摸底,整个资产变化链路就很清晰。
当然,日常快速场景里用到intel和track的频率不高,但它们和Subfinder之间并不冲突,属于"锦上添花"的进阶能力。集成方案不必做得很复杂,先把最基本的先跑通,后面再按需加。
4. 从零开始的一轮实战:example.com全流程记录
4.1 第一轮:Subfinder被动收集
我用example.com做演示,实际项目中替换成你的授权目标即可。进入工作目录,先跑Subfinder:
cd subdomain_toolkit subfinder -d example.com -all -silent -pc configs/provider_config.yaml -o outputs/example_subfinder.txt命令跑完后看下结果数量:
wc -l outputs/example_subfinder.txt我实测下来,一个中等规模的站点,Subfinder大概能给出几百到上千条结果,耗时通常在一分钟以内。如果数据量太大,可以再加-recursive做递归查询,但要注意API配额消耗会明显增加。
4.2 第二轮:Amass主动枚举与爆破
接着用Amass做主动模式和爆破。爆破不可避免要一个好的词表,如果你没有现成的,可以先用Amass自带字典跑一遍,后续再换大字典补漏。
amass enum -active -brute -d example.com -w wordlists/dns_subdomains.txt -config configs/amass_config.ini -dns-qps 50 -timeout 30 -o outputs/example_amass.txt这里-brute会基于字典生成可能的子域名并尝试解析;-dns-qps限制每秒DNS查询数,默认值有时候太激进,容易触发解析商的限流;-timeout是最大运行分钟数,防止任务卡死在某个数据源上。
跑Amass时不要干等,我一般会同时把上一轮Subfinder的结果拿去做基础存活探测,把时间利用起来。
4.3 合并去重与基础校验
两轮都跑完后,统一合并:
cat outputs/example_subfinder.txt outputs/example_amass.txt | tr 'A-Z' 'a-z' | sort -u > outputs/example_all.txt合并后我习惯再和已知资产表做一次比对。比如你手头有一份官方资产清单official_assets.txt,用-Fx按整行精确匹配就能找出不在这份清单里的"未知资产":
grep -Fxf official_assets.txt outputs/example_all.txt | wc -l也可以反过来,找出不在白名单里的:
grep -vFxf official_assets.txt outputs/example_all.txt这一步能快速帮你定位哪些子域需要优先人工确认。
4.4 从域名列表到资产指纹:接上httpx桥接
Amass和Subfinder做完后,如果这是一次完整的web资产测绘,下一步通常是做存活探测和指纹识别。ProjectDiscovery生态里httpx正好和Subfinder无缝衔接:
cat outputs/example_all.txt | httpx -silent -status-code -title -tech-detect -follow-redirects这条命令会对每个子域发起HTTP请求,输出状态码、页面标题和技术栈指纹。走到这一步,子域枚举的"收集"阶段才算真正闭环,后面就可以继续接nuclei漏洞扫描或者手工测试。
一次跑完后的结果大概长这样(示意):
| 子域 | 状态码 | 标题 | 技术栈 | 来源 |
|---|---|---|---|---|
| www.example.com | 200 | Example Home | Cloudflare, React | Subfinder |
| api.example.com | 403 | - | Nginx, Node.js | Amass |
| staging.example.com | 200 | Staging App | Nginx, PHP | Amass+Subfinder |
来源列可以帮你分析哪个工具发现了哪些资产,后续优化配置时很有用。
5. 把流程脚本化:批量域名的自动化方案
5.1 一个最小可用的工作流脚本
跑了几次全流程后,手动敲命令就有点烦了。我写了个简单的bash脚本,参数传入域名,自动完成Subfinder收集、Amass枚举、合并去重,顺便把关键结果打日志:
#!/bin/bash # usage: ./run_recon.sh example.com DOMAIN=$1 TS=$(date +%Y%m%d_%H%M%S) OUT="outputs/${DOMAIN}_${TS}" mkdir -p "$OUT" echo "[*] Running Subfinder" subfinder -d "$DOMAIN" -all -silent -pc configs/provider_config.yaml -o "$OUT/subfinder.txt" echo "[*] Running Amass" amass enum -passive -active -d "$DOMAIN" -config configs/amass_config.ini -timeout 20 -o "$OUT/amass.txt" echo "[*] Merging results" cat "$OUT/subfinder.txt" "$OUT/amass.txt" | tr 'A-Z' 'a-z' | sort -u > "$OUT/final.txt" wc -l "$OUT/final.txt"这个脚本没什么高深技术,但它把"命令重复执行"变成了"固定流程执行",降低了每天切换多个工具的认知负担。如果还想更省事,可以再套一层循环,批量处理多个域名。
5.2 批量域名的输入与任务分批
批量场景下,Subfinder用-dL指定域名列表文件,Amass用-df指定根域名文件:
subfinder -dL domains.txt -all -silent -o outputs/batch_subfinder.txt amass enum -passive -active -df domains.txt -config configs/amass_config.ini -timeout 60 -o outputs/batch_amass.txt我个人的经验是:批量任务不要一次丢上百个域名给Amass,尤其开启了-active和-brute之后,整个任务可能几个小时跑不完。更稳妥的方式是先按优先级给域名分组,每个批次控制在10到20个,逐个检查进度。同时在脚本里记录每个域名的开始和结束时间,方便估算整个资产测绘项目的排期。
5.3 定时任务的注意事项
如果你要做周期性资产监控,可以用crontab定时拉取:
0 2 * * * /path/to/run_recon.sh example.com >> logs/recon.log 2>&1但我强烈建议定时任务里优先用被动模式,把-active和-brute关掉。原因很简单:被动模式对目标产生的影响极小,适合高频执行;主动模式会产生大量DNS查询,属于实质性的流量行为,每周甚至每月跑一次就够了。API配额也要提前规划,VirusTotal这类免费额度有每日调用上限,高频定时任务很容易把配额刷爆,第二天直接报错。
6. 实测中容易翻车的几个细节
6.1 API限速与调用配额
这是我最先要提醒的坑。Amass和Subfinder的价值很大一部分来自商业数据源API,但API都有配额和速率限制。Amass跑的时候,有时日志里会刷出一堆"rate limit exceeded",这时候结果会明显变少,甚至某些源直接失效。
我的处理方式是:
- 在Amass命令里显式设置
-dns-qps,别用默认的激进值,一般30到50比较稳。 - Subfinder的
-all参数会把所有源全部启用,某些慢的源会拖长整个任务,如果只是日常快速排查,不加-all反而更快。 - 免费配额用完时,适当错峰执行,把大任务放到凌晨批次。
6.2 字典选择与爆破时间
Amass的-brute一旦开启,任务时长会从分钟级跳到小时级。默认字典很小,覆盖有限;但如果直接上超大字典,比如几万条前缀,对一个有很多CNAME的站点来说,可能会产生大量无效请求。
我的建议是:第一次探测先用中小型字典,跑完看命中率;如果命中率比较高,再换大字典补一轮。爆破不用追求"一次全中",资产测绘是个持续优化的过程。
所谓泛解析问题,就是某些DNS服务器会对任意不存在的子域返回一个默认IP,导致爆破结果里出现大量假资产。遇到这种情况,必须对爆破结果做二次确认,比如把解析到同一IP且标题都是默认页的子域单独拉出来审一遍。Amass的CSV输出里可以看来源标签,我会直接筛选出brute来源的条目做重点核查。
6.3 主动、被动结果的差异要心里有数
被动收集和主动枚举的结果特性完全不同。被动收集干净、误报少,因为每条记录都来自真实存在过的数据源;主动枚举信息更全,但噪音也更多,尤其是在泛解析的域名上。
所以合并结果时,不要觉得"数量越多越好"。我见过有人拿Amass主动模式下扫出来的几千条结果直接进漏洞扫描,结果一半都是泛解析假资产,白白浪费时间和扫描流量。正确的姿势是:合并后先做一轮存活和去伪,再进入下一步。
6.4 配置文件泄露风险
最后提一个容易被忽略的安全习惯:amass_config.ini和provider_config.yaml里都是明文API密钥,千万不能提交到Git仓库。我见过不止一次,开发者把配置目录整个推到GitHub,导致密钥被别人拿走刷爆配额、产生账单。
建议在所有相关目录下加.gitignore,或者至少把configs目录忽略掉。本地文件权限也顺手改一下:
chmod 600 configs/amass_config.ini configs/provider_config.yaml这串操作十秒钟,但能省掉后面一大堆麻烦。
跑过几轮完整的Amass+Subfinder流程后,我最深的体会是:这两个工具本身都不难学,真正的价值在于把它们放进一条清晰的资产测绘流水线里,让每一步的输出自然成为下一步的输入。你不需要在刚开始就把所有参数吃透,只需要先跑通我上面写的快速预筛加深度测绘这套流程,然后根据实际结果不断调整字典、数据源和任务节奏。等配好了,后续每次拿到域名,半小时内就能产出一份像样的资产清单,这份效率提升才是最值得投入时间的地方。