跳转至

资产端口状态与历史

数据语义

scan_observation 保存每次执行产生的端口和服务观察,是扫描结果的事实来源。 ips、ports 继续用于资产分页、地理信息和端口索引。服务端不再写入 scaninfo,该表仅 可能作为升级后尚未由用户手动删除的遗留数据存在,不再作为业务查询来源。

扫描器当前只上传开放端口,因此系统不会根据“某次没有发现”推断端口已经关闭:

  • open:最近 30 天内至少有一次成功 execution 观察到该端口;
  • stale:曾观察到开放,但超过配置的展示阈值没有再次观察到;
  • 系统暂不产生 closed,直到 execution 能记录并证明完整扫描覆盖范围。

服务信息取该端口最新的 service observation。若端口在服务观察之后又被发现,接口会返回 service_stale: true,页面仍展示旧服务,同时明确标记信息可能过期。

API

当前端口

GET /api/assets/ports?ip=192.0.2.1&stale_after_days=30

普通用户只能查看自己任务产生的 observation;管理员可以查看全部任务。接口只使用状态为 succeeded 的 execution 计算当前状态。

端口历史

GET /api/assets/port-history?ip=192.0.2.1&port=443&limit=50&offset=0

返回 observation 类型、协议、服务、banner、来源、批次、execution、任务和观察时间。 superseded execution 不参与历史查询。

历史回填

当 scaninfo 仍存在时,启动时的 source/database/init.sql 为还没有 observation 的旧 execution 创建协议版本 1 合成批次,并从 scaninfo -> ports -> ips 回填事实记录。回填键使用 legacy:<scan_info_id>,可以安全重复执行;已有 v2 observation 的 execution 不会再次导入 旧双写时期的兼容镜像。若表不存在,初始化会直接跳过这一步,且不会重新创建它。

下线核验与手动删除

代码不会自动删除或清空 scaninfo。完成升级并确保所有服务端实例均已使用停止双写的版本后:

  1. 在 scaninfo 仍存在时执行只读脚本 source/database/verify_scaninfo_migration.sql;
  2. 确认结果中的 missing_backfill_rows 和 mismatched_backfill_rows 都为 0;
  3. 经过业务观察期,核对任务详情、搜索、导出、资产当前端口及端口历史均正常;
  4. 由用户或 DBA 按自身变更流程手动删除 scaninfo,应用不会代为执行;
  5. 删除后重启一次服务,确认初始化和数据库容量监控正常。

若核验值不为 0,应保留该表并排查对应旧 execution,不要进入手动删除步骤。

后续覆盖模型

如需可靠显示 closed,需要增加 execution 覆盖记录,至少包含目标 IP/CIDR、端口范围、阶段、 完成状态和覆盖完整性。只有成功且完整覆盖指定 IP、端口的扫描未发现开放时,才能把旧的开放 状态转为关闭。