
很多做安全的人第一次接触“开源情报”这四个字第一反应是去找各种高深莫测的暗网工具结果折腾一圈下来真正能用上的没几样。我在做外部攻击面管理和授权渗透测试时也是一样早期全靠一条命令一条命令地敲在网页和终端之间来回切。直到某一天我发现手里那几个固定的查询和账号已经远远追不上目标的变化才开始正儿八经琢磨怎么把OSINT这套东西工程化。后来我搭了一套半自动的情报采集分析流水线才真正感受到什么叫“系统干活人负责判断”。这篇东西就是我搭建这套系统过程中的完整复盘包括数据源怎么挑、脚本怎么组织、数据怎么存、任务怎么调度、以及我踩过的那些坑。适合正在做蓝队、攻击面管理、安全运营或者尝试给自己团队搭情报收集能力的朋友参考。1. 我为什么从“手工查域名”转向自建OSINT流水线先说触发点。一次授权项目中客户给了两个主域名要求快速梳理对外暴露的资产。我当时按老思路操作跑一遍子域枚举、查证书、翻DNS记录、再逐个访问确认存活。看着不复杂但实际执行起来全是零碎活。等到汇总阶段光是把几百条子域和IP对应关系整理到表格里就花了我将近一天时间。1.1 最初的需求一次授权测试暴露的收集短板这次经历让我意识到问题不在单个工具而在“流程”。每次项目都从零开始收集意味着大量重复劳动而且人的注意力会被机械操作消耗掉。更麻烦的是手工模式下不同轮次的数据标准不统一同一组数据今天用的是Python脚本明天可能换成了另一个在线工具导出的CSV字段名对不上后面做关联分析时全是麻烦。另一个痛点来自持续监测需求。攻击面不是静态的证书会新增、域名会失效、子域会冒出来。手工方式做一个快照还行要做到每星期甚至每24小时自动刷新一轮根本不现实。所以那阵子我下决心搭一套可持续运转的开源情报系统核心目的就一个把收集、处理、查询这些脏活累活交给自动化把时间留给分析。1.2 明确边界OSINT系统不等于爬虫而是信息调度中枢这里必须说清楚一个容易混淆的点。很多人以为OSINT系统就是个更强大的爬虫能把目标相关的网页全抓下来。其实不然。抓取只是整个链路的一部分系统真正的核心价值在于“调度的有序性”。我理解的OSINT系统包含四个环节采集、清洗、关联、输出。采集负责从公开渠道获取原始数据清洗负责去掉重复和无效信息统一数据格式关联负责把看似分散的数据拼成有意义的线索输出负责以人可读、机器可读的方式呈现结果。爬虫只是其中最前端的执行器后面的每一步才是拉开差距的地方。1.3 系统的输入输出定义在动手写第一行代码前先把边界定清楚避免后续失控。输入组织名称、主域名、网段或已知IP。过程中的数据证书记录、DNS记录、子域名、同源主体注册信息、代码托管平台的公开内容匹配结果、屏幕快照。最终产物资产清单、新发现资产列表、疑似仿冒域名列表、风险提示事件。这个输入输出设计贯穿了后面所有章节每次遇到新需求我都会先问一句它是该被采集的输入还是该被生成的输出这个约束让我没有把系统做成一个什么都装的怪兽也让我后续的每一个模块都足够克制。2. 数据源选型先把“在哪里找情报”钉死在地图上很多人做OSINT一上来就写采集代码结果写了一半发现不知道该去哪个公开源拉数据或者拉回来的数据根本缺乏时间线索。数据源选型这一步我认为是整个系统成败最关键的地方。数据源不是越多越好而是要看每个源在你的场景里能不能持续产出有效信息、有没有明确的时间戳、以及是否允许合法查询。2.1 我实际在用的公开数据源清单下面这份清单是在我的场景里经过验证的覆盖了域名、IP、代码平台、公开记录等维度。每个源都有明确的用途和局限性。数据源类型具体来源主要用途局限性证书透明日志crt.sh、Google CT、Censys发现新域名、子域名发现时间相对实时噪音较多需要大量清洗被动DNS在线PDNS服务、域名历史记录接口找回已经不在当前解析记录里的曾经IP/域名很多接口有配额限制Whois记录RDAP公开接口、WHOIS服务注册人、注册机构、时间信息用于同源扩展隐私保护导致很多字段脱敏公网资产测绘Shodan、Censys、FOFA等暴露服务、开放端口、横幅信息数据量大免费额度有限代码搜索GitHub公开代码搜索API查找硬编码密钥、内部域名、配置信息依赖目标的公开习惯搜索引擎Google与必应的高级查询语法收录页、历史快照、隐藏入口链接结果不稳定语法变化要注意泄露情报平台Have I Been Pwned、类似通报服务关联邮箱泄露情况辅助身份线索不能用于未授权的攻击性操作选择标准也很简单是否有明确的API或导出方式、数据的更新频率、历史记录是否可回溯。如果一个数据源只能看当前状态对系统性建设来说价值就大打折扣。2.2 证书透明日志是被低估的黄金入口单独把证书透明日志拿出来说是因为它在我这套系统里贡献了最多的高质量线索而且很多做OSINT的人没有把它用到极致。证书透明日志是公开的、只能追加的记录系统。每个公开的SSL/TLS证书一旦签发就会被记录进去。只要某个组织为它的域名申领了证书你基本就能在日志里看到域名组织名称等信息。这意味着每当目标上线新服务、新子域证书日志几乎会第一时间暴露。我做过一轮测试用证书透明日志识别出的新增子域比用字典爆破方式发现的要提前大约三到五天覆盖范围也更全。原因很简单你不可能猜到一个完全随机的三级域名但证书日志里它就在那里躺着。有了这个机制后我把它作为新增资产监测的第一信源每天固定拉取增量数据然后与已有资产库比对瞬间就能知道目标长出了什么新东西。另外一个被忽略的用法是利用证书的签发时间来辅助排序。同一个主域名下的子域如果是刚刚签发的证书往往意味着目标最近新增的服务和可能存在的薄弱点。排序这块在后续分析环节会多次用到。2.3 数据源对应的获取手段与合规前提数据源选好之后接下来就是怎么安全地获取。这里说两个必须坚持的原则。第一个原则是只走公开合法通道。涉及需要登录才能访问的数据尽量走官方提供的API不要用自动程序无限拉取网页。部分平台有使用条款明确禁止未授权的批量采集这种就需要放弃或者寻找替代源。OSINT精神本身是建立在公开、可合法访问基础上的一旦越界就和影子IT没有区别了风险完全不可控。第二个原则是数据使用时要有依据。同一份数据是否可以被公开查询和它是否可以被你用于某个特定目的是两回事。我在系统里做了一个简单的标记字段记录每条数据的来源、抓取时间、以及对应API的条款约束。这样万一某条数据的使用方式受到质疑我可以完整回溯来源。这条合规习惯在后面和外部同事协作时帮了不少忙。有一次我拉来的数据里面包含了某个平台明确禁止再分发的记录我直接在系统里把这批数据标记为“仅内部参考”避免了无意识扩散。看起来是个小细节但对长期运营这类系统的团队来说非常重要。3. 技术栈与落地方案从采集脚本到半自动情报台选定数据源之后接下来是技术选型。我的经验是不要一上来就引一堆重型平台先把一根最小的完整链路跑通再逐步加组件。下面是我最终采用的方案以及每个选择背后的理由。3.1 采集层Python httpx APScheduler采集层主要承担数据获取任务。为什么选Python因为它生态里跟OSINT相关的库和文档最多团队协作时上手门槛也低。HTTP客户端我后来统一用httpx因为它在异步并发和HTTP/2支持上比老牌requests更顺手。目标数量多的情况下并发采集证书和DNS记录能明显缩短时间。任务调度我用的是APScheduler轻量而且靠谱。每日证书日志增量拉取、每周Whois核对、每季度全量资产比对都用Cron触发器来设置频率。如果你的收集逻辑比较复杂比如任务之间有依赖关系再考虑把调度换成Airflow或者Prefect但我个人建议很多中小规模系统根本不需要走到那一步。每个采集器我坚持独立成模块。比如ct_log_collector只负责拉证书列表dns_collector只负责做解析。模块间通过统一的JSON输出对接后续调整任一层都不会炸掉整条流水线。3.2 存储层PostgreSQL打底Elasticsearch做检索Neo4j做关联存储选型这部分我纠结了很久。最初想全塞进Elasticsearch后来发现关联查询写起来很绕数据分析也不方便。最后定下来的方案是三件套配合。主数据库用PostgreSQL存资产、来源、任务状态。它支持JSONB字段意味着半结构化的原始日志也能塞进去查询性能足够日常用。Elasticsearch只存需要全文检索的日志和卡片式数据比如网页正文、证书字段、历史快照内容。Neo4j用来存实体和实体之间的关系域名属于哪个组织、证书关联哪几个域名、IP在某个时间段解析到哪个域名这些关系在图里一查一个准。这套组合看起来繁琐但实际跑起来很顺。日常用PostgreSQL就够了只有做关联分析时才需要Neo4j出手。3.3 分析层规则引擎优先机器学习靠后分析层的核心目标是减少人的重复判断。我优先用的是一组规则引擎比如新发现的域名如果在证书信息里与主域名同属一个组织就自动打上“高关联”标签Whois注册人或邮箱与已知主体重复则标记为“同源候选”。机器学习这块我没有一开始就上。原因很简单这类系统的样本量往往不够大而且攻击者的行为模式变化快规则引擎的可解释性更好。真正用到机器学习的地方是相似域名检测和钓鱼页面识别。这里用字符串编辑距离计算域名相似度再用简单的二分类器判断页面内容和已知品牌页面的接近程度。这个组合在实测里的表现比较稳定。你可能会问为什么不直接上大模型来做实体抽取我用过的感受是效果好但资源开销大而且输出不稳定很难直接引入自动化流程。更稳妥的做法是把大模型定位成辅助研判工具让它在高优先级告警出现时帮分析人员快速整理上下文而不是让它决策。3.4 前台展示Grafana可视化 自研Web控制台展示层一开始用的Grafana监控数据走势很方便比如新增域名数量、证书出现速率、采集任务成功率。后来我发现资产查询、线索管理这类交互需求Grafana做起来不够顺手所以又补了一个轻量Web控制台。控制台的几个核心页面我印象比较深资产全景以目标组织为单位展示域名、IP、证书、历史记录。时间线某个域名的证书变更记录某段时间内新增了多少资产。告警列表已聚合的疑似风险事件支持一键标记误报。搜索框输入任何关键词可跨库检索这个功能在应急场景特别好用。这个控制台没有做什么花哨功能就是让团队里每一个人都能用同一个入口查看全量情报不再各自维护Excel了。4. 管线打通后的运营细节任务调度、去重与数据保鲜系统跑通只是开始。真正让系统活起来的是运营层面的细节包括任务调度节奏、数据去重、以及怎么让数据一直保持新鲜。4.1 增量采集与全量采集的节奏控制采集节奏设计不好很容易让系统每天重复做无用功既浪费配额又增加噪声。我的经验是区分增量任务和全量任务。以证书日志为例每天定时拉取最近24小时新增的证书记录这是增量。但增量可以查漏补缺却无法发现历史遗漏比如某个证书签发后因为种种原因没被记录到。所以每到一个季度我会触发一次全量重扫把目标主域名下的所有已知子域再全部跑一遍证书和对解析记录。DNS记录也是类似逻辑日常增量更新解析结果同时每周做一次针对活跃资产的全量解析确认。因为A记录的TTL通常不长一周时间足够发现大多数变化了。4.2 去重的核心不是删除而是保留“首次发现时间”去重只写一次判断条件很危险。有一次我天真地按主键读到一个就更新结果把一批资产历史时间戳污染了——本来去年就出现的子域直接因为重复采集把首次发现时间改成了昨天。这个看似微小的改动直接导致我误判了目标的“最近新增”排名在报告里把老资产当成了新发现。之后我把去重逻辑改了。对于每个资产至少有四个固定字段资产标识、首次发现时间、最后确认时间、来源列表。重复出现时只更新最后确认时间和来源列表首次发现时间是绝对写入的不允许后续更新。这样新资产的冒头机制才算真正建立起来。4.3 监控报警与数据保鲜策略采集系统也会生病。API突然改版、超时、返回空数组、磁盘写满这些平凡但致命的问题都会让管线静默失败。我给系统加了心跳监控每个采集任务完成后会推一条记录如果某个关键任务连续两次没产生正常输出控制台直接亮红。数据保鲜这件事很多人会忽略。OSINT数据有强烈的时效性一个IP对应的服务可能三个月就变了。我给不同数据源设置了不同的握手周期证书数据1天、Active DNS 3天、Whois 14天、公开页面快照30天。到期没有更新的数据会在搜索结果里降权防止老信息误导新判断。还有一条是存储策略。原始响应不删不管清洗后有多冗余我都保留一份压缩存储。因为你永远不知道下一条线索会需要回溯哪个字段而且随时可以在保留原始数据的基础上重新清洗一遍极大提高容错率。5. 实测中踩过的坑与对应修补再完美的设计也敌不过真实世界的各种意外。这一节把我踩过的坑里比较有代表性的几个复盘一下每一条都是真金白银买来的教训。5.1 证书日志的噪音清洗证书透明日志的噪音问题比预想中严重得多。同一个域名可能会因为不同证书供应商的交叉签名出现多次记录泛域名证书和通配符证书又会引入一大堆无意义的子域名变体。一开始我的资产列表直接被刷爆很多根本不存在的域名也被当成资产。后来的方案是加白名单和黑名单机制已知主域名列表作为白名单只有与白名单存在关联的记录才保留黑名单则过滤掉比如“内部测试”“临时开发环境”等常见词。另外只用证书里的DNS names字段还不够我还会看证书申请者是否和组织名称匹配明显不匹配的记录会进入低优先级的“待研判”队列。5.2 反爬策略和API限速在线数据源通常不太喜欢高频采集。早期的脚本因为并发开得太猛很快把某个证件查询接口的额度用完了之后直接把网络请求给拦了。那段时间整个证书模块基本停摆。解决方案有三层。第一层是所有对外请求统一带User-Agent和项目标识遵守robots.txt。第二层做一个简单的令牌桶限速器全局控制每秒请求数不允许某个模块独占到影响其他模块。第三层是每个数据源都有独立的抓取配额账户单独监控用量接近阈值时提前告警。这里我学到的最重要一件事限速不是用来阻碍你的而是保护数据源可用性的。过于激进的结果就是大家一起用不了这是双输。5.3 数据格式变化与断裂的API响应数据源改版是家常便饭。有一次一个PDNS服务把返回JSON里字段从ip改成了ip_address我的解析模块直接报错任务全部失败。更麻烦的是批量任务的日志没有保留请求响应原始内容我想排查都没法排查只能重新拉一遍。从那以后我执行了两项规定。第一项是采集模块的日志里必须保留原始响应头和响应体切片哪怕只保留最近几条。第二项是每个数据源适配层都加“字段映射模板”模板文件单独存放源变了只改模板不改核心代码。这两项规定在后续多次数据源升级中帮我省了大量时间。另外数据源临时不可用是常态。我的重试机制现在采用指数退避策略第一次失败等30秒第二次90秒第三次直接放弃并把未入库请求写入一个待补拉队列。下次调度启动时会先处理这个队列而不是简单地把今天的任务跳过。6. 从“能跑”到“好用”关联分析与告警实战最后一节说说系统从“能跑”到“好用”的距离差在哪里。这一步最核心的是关联可视化、告警降噪以及和应急流程的联动。6.1 实体识别与关系图谱域名不再是孤立的字符串早期系统查询一个域名输出就是一串历史记录没有任何结构。后来我把数据导入Neo4j才发现实体之间的关系网远比想象中复杂。比如一个新注册的域名表面看和目标毫无关系但如果它的Whois电话和目标的某个历史域名注册信息一致或者它的证书申请邮箱跟目标泄露数据库里的邮箱相同那么关联度立刻上升。这就是纯靠列表排列看不出来的线索。图数据库帮我实现的这种关系挖掘让系统在仿冒域名监测场景里直接上升了一个档次。6.2 告警降噪用时间线折叠和风险评分过滤无效事件告警系统的头号敌人是误报。最初系统每天给我发几十封邮件里面一半是无关紧要的普通新证书这样的后果就是慢慢变得没有人看了。后来采用了两个降噪手段。第一个是时间线折叠同一资产在一个小时内因为数据源重复上报触发的多条告警自动合并成一条。第二个是风险评分制。评分包含多个维度域名相似度高于0.85加分证书签发时间距今少于30天加分页面标题与品牌主页相似加分Whois为最近注册加分。只有总分超过阈值的实体才会进入告警池。这个评分制用了几个月后告警数量从每天几十条降到了每周真正相关的几条人的效率提升非常可观。6.3 与应急响应联动直接输出可处理的工单系统最终的价值要体现在工作流里。我的做法是给控制台加了一个“生成工单”按钮。点一下系统会把这起事件的背景、资产清单、证据截图、关联记录打包成一个结构化的工单自动推送到应急响应用的协作工具里。有一个案例印象很深。系统发现一个与主品牌域名相似度很高的钓鱼站点再一查证书信息发现它和某次泄露事件里邮箱关联的是同一个注册人。我把这个线索打包成工单后上报给客户当场就确认了是近期活跃的钓鱼行动。整个流程从发现到上报用了不到十分钟而这在手工时代通常需要小半天。到这里这套OSINT系统已经从最初的一堆脚本变成了一个有采集、有存储、有关联、有告警、有输出的完整工作平台。如果需要继续往前扩展下一个方向我觉得是把更多公开威胁情报源接进来比如公开的恶意URL信誉库和已知威胁指标让系统能从“监测新资产”进化到“监测未知威胁”。但我始终提醒自己一点任何工具都会衰老只有持续维护数据质量和更新节奏系统才能持续创造价值。