基于微步在线威胁情报的公网 IP 攻击迹象监测:threatbook_query 脚本全解析与 BruceSec 平台整合实践

基于微步在线威胁情报的公网 IP 攻击迹象监测:threatbook_query 脚本全解析与 BruceSec 平台整合实践

摘要

在公网资产安全监测中,仅靠主动端口扫描往往难以穿透严格的边界防火墙;此时,借助第三方威胁情报(Threat Intelligence)对公网 IP 的历史行为进行被动研判,是一种高效、低噪的补充手段。本文以实际落地的 threatbook_query.py 脚本为线索,完整介绍其设计背景、方案选型、脚本架构、逐函数代码解析、部署使用方法,以及如何将其注册进 BruceSec 安全平台(tools yaml + ApplyConfig 热重载 + MCP 管理页)实现一键调用。文中所涉 IP 判定、接口返回、平台热重载结果均来自本机实测输出,未做任何虚构。


脱敏声明:本文所有涉及真实资产的公网 IP 已按 RFC 5737 替换为测试保留地址(203.0.113.x),地理位置、运营商、ASN 已泛化脱敏;文中不包含任何 API Key 明文;相关数据仅用于技术示例。

一、项目背景:公网 IP 攻击迹象监测与 nmap 的"严防火墙"困境

单位公网出口长期暴露在互联网上,安全运维团队需要持续监测公网 IP 是否存在被攻击、被利用的迹象。传统做法是使用 nmap 等工具对目标 IP 做端口扫描与服务识别,但在实际执行中遇到了明显的瓶颈:

text 复制代码
=== 扫描时间: 2026-08-14 18:19:10 ===

########## 目标 1: 203.0.113.11 ##########
Starting Nmap 7.95 ( https://nmap.org ) at 2026-08-14 18:18 CST
Nmap scan report for 203.0.113.11
Host is up.
All 100 scanned ports on 203.0.113.11 are in ignored states.
Not shown: 100 filtered tcp ports (no-response)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 34.26 seconds

########## 目标 2: 203.0.113.12 ##########
Starting Nmap 7.95 ( https://nmap.org ) at 2026-08-14 18:18 CST
Nmap scan report for 203.0.113.12
Host is up (0.040s latency).
Not shown: 90 closed tcp ports (conn-refused)
PORT     STATE    SERVICE      VERSION
53/tcp   filtered domain
80/tcp   filtered http
135/tcp  filtered msrpc
139/tcp  filtered netbios-ssn
443/tcp  filtered https
445/tcp  filtered microsoft-ds
3128/tcp filtered squid-http
5800/tcp filtered vnc-http
5900/tcp filtered vnc
8080/tcp filtered http-proxy
Nmap done: 1 IP address (1 host up) scanned in 16.56 seconds

从扫描结果可以清晰看到两个问题:

  1. 端口大面积 filtered :目标 1(203.0.113.11)全部 100 个扫描端口均处于 filtered(无响应)状态,说明边界防火墙对探测流量做了严格过滤,nmap 几乎拿不到任何服务信息;目标 2(203.0.113.12)虽然有 10 个端口被列出,但全部为 filtered,无法确认其真实服务。
  2. 主动扫描的先天局限:防火墙过滤后,主动探测既得不到服务指纹,也观察不到目标 IP 的"历史行为"。攻击迹象往往体现在历史威胁标签(如僵尸网络、扫描器、C2、被攻陷等),而这些信息只有威胁情报平台才有积累。

因此,团队决定引入微步在线(ThreatBook)威胁情报 API,通过 IP 情报查询对监测名单中的公网 IP 做被动研判,形成"情报判定 + nmap 对照"的双通道监测模式。


二、方案选型:为什么选择微步 v3/ip/query

2.1 选型背景

威胁情报服务商众多,本项目选型时主要关注四点:威胁标签的丰富度、接口返回字段的完整度、是否支持国内 IP 的深度覆盖、以及接入成本(Key 申请与绑定流程)。微步在线在国内威胁情报领域积累较深,对国内运营商 IP(ISP 已脱敏ISP 已脱敏等)的标签覆盖较好,且提供免费额度便于验证,因此进入候选。

2.2 v3/ip/query 与 ip_reputation 的对比考量

在微步在线 API 体系中,IP 情报查询存在不同的接口形态,本项目最终选定 /v3/ip/query,主要对比考量如下:

对比维度 v3/ip/query(本项目采用) 场景化信誉查询(ip_reputation 类接口)
返回内容 全维度情报:judgments 恶意判定、basic 基础信息(位置/运营商)、asnintelligences 情报标签及置信度 面向特定场景的信誉评分与结论,字段相对聚焦
与监测需求的匹配度 字段与研判流程一一对应,可直接支撑"标签 + 置信度 + 发现时间"的完整证据链 更偏单值评分,历史标签细节较少
实现复杂度 GET 请求 + apikey 即可,纯标准库可完成 具体参数与返回结构以官方文档为准

说明:具体接口的请求参数与返回字段差异请以微步在线官方 API 文档为准;本文只陈述本项目脚本实际使用 v3/ip/query 的事实与收益。

2.3 Key 绑定出口 IP(关键约束)

微步在线对 API Key 有出口 IP 绑定 机制:在微步控制台申请 Key 后,需要在控制台将该 Key 绑定到实际发起请求的服务器出口 IP。若请求源 IP 与控制台绑定的 IP 不一致,接口会返回 Invalid Access IP 错误。这是接入过程中最易踩坑的一步,也是本脚本部署文档中的首要注意事项(详见 yaml 注册文件中的说明:"需在微步控制台绑定请求出口 IP,否则报 Invalid Access IP")。


三、脚本架构与数据流

threatbook_query.py 是一个无第三方依赖的纯 Python 标准库脚本(仅使用 json / os / sys / urllib.request / urllib.parse),整体架构清晰,共四个函数:

  • load_key():读取 API Key(从同目录的 threatbook_api_key 文件,权限 chmod 600)
  • query(key, ip):调用微步 v3/ip/query 接口,返回 JSON
  • summarize(ip, data):将原始返回压缩为研判所需的摘要结构
  • main():命令行入口,支持批量 IP,输出汇总 JSON

数据流如下(Mermaid 图):

平台侧调用链路(BruceSec 整合后):


四、逐函数代码解析

4.1 脚本完整代码

以下为脚本全文(共 70 行,与部署于本机 ~/.config/threatbook/threatbook_query.py 的版本一致):

python 复制代码
#!/usr/bin/env python3
"""微步在线 IP 情报查询(BruceSec 公网IP攻击迹象监测用)
用法: python3 threatbook_query.py [ip1 ip2 ...]
默认查询: 203.0.113.11 203.0.113.12 203.0.113.13
Key 读取自同目录 threatbook_api_key(chmod 600)
"""
import json, os, sys, urllib.request, urllib.parse

KEY_FILE = os.path.expanduser("~/.config/threatbook/api_key")
API = "https://api.threatbook.cn/v3/ip/query"
DEFAULT_IPS = ["203.0.113.11", "203.0.113.12", "203.0.113.13"]


def load_key():
    with open(KEY_FILE) as f:
        return f.read().strip()


def query(key, ip):
    q = urllib.parse.urlencode({"apikey": key, "resource": ip})
    req = urllib.request.Request(f"{API}?{q}", headers={"User-Agent": "BruceSec-ip-monitor/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.loads(r.read().decode())


def summarize(ip, data):
    judgments = data.get("judgments") or []
    basic = data.get("basic") or {}
    loc = basic.get("location") or {}
    asn = data.get("asn") or {}
    intels = []
    for src, items in (data.get("intelligences") or {}).items():
        for it in items:
            if not it.get("expired", True):
                intels.append({
                    "source": src,
                    "types": it.get("intel_types", []),
                    "confidence": it.get("confidence"),
                    "find_time": it.get("find_time"),
                })
    return {
        "ip": ip,
        "judgments": judgments,
        "location": f"{loc.get('country','')} {loc.get('province','')} {loc.get('city','')}".strip(),
        "carrier": basic.get("carrier", ""),
        "asn": f"AS{asn.get('number','')} {asn.get('info','')}".strip(),
        "active_intels": intels[:10],
        "update_time": data.get("update_time", ""),
    }


def main():
    ips = sys.argv[1:] or DEFAULT_IPS
    key = load_key()
    out = []
    for ip in ips:
        try:
            d = query(key, ip)
            if d.get("response_code") != 0 or ip not in (d.get("data") or {}):
                out.append({"ip": ip, "error": d.get("verbose_msg", "查询失败")})
                continue
            out.append(summarize(ip, d["data"][ip]))
        except Exception as e:
            out.append({"ip": ip, "error": str(e)})
    print(json.dumps(out, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()

4.2 load_key():密钥安全加载

python 复制代码
def load_key():
    with open(KEY_FILE) as f:
        return f.read().strip()
  • KEY_FILE 使用 os.path.expanduser 展开 ~,指向 ~/.config/threatbook/api_key,避免硬编码绝对路径带来的可移植性问题。
  • 文件按行读取并 strip() 去除首尾空白,确保 Key 不带多余换行符。
  • 安全要点:Key 不写在代码中,而是独立存放于 chmod 600 的密钥文件,实现"代码与密钥分离"。

4.3 query(key, ip):HTTP 调用与 JSON 解析

python 复制代码
def query(key, ip):
    q = urllib.parse.urlencode({"apikey": key, "resource": ip})
    req = urllib.request.Request(f"{API}?{q}", headers={"User-Agent": "BruceSec-ip-monitor/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.loads(r.read().decode())
  • 使用 urllib.parse.urlencode 构造查询串,参数为 apikeyresource(目标 IP),避免手动拼接导致的 URL 编码问题。
  • 通过 urllib.request.Request 显式设置 User-Agent: BruceSec-ip-monitor/1.0,标识请求来源,便于在微步侧做调用审计。
  • urlopen(..., timeout=30) 设置 30 秒超时,防止网络异常导致脚本长时间挂起。
  • 返回结果用 json.loads 解码为 Python 字典。

4.4 summarize(ip, data):情报摘要提炼

python 复制代码
def summarize(ip, data):
    judgments = data.get("judgments") or []
    basic = data.get("basic") or {}
    loc = basic.get("location") or {}
    asn = data.get("asn") or {}
    intels = []
    for src, items in (data.get("intelligences") or {}).items():
        for it in items:
            if not it.get("expired", True):
                intels.append({
                    "source": src,
                    "types": it.get("intel_types", []),
                    "confidence": it.get("confidence"),
                    "find_time": it.get("find_time"),
                })
    return {
        "ip": ip,
        "judgments": judgments,
        "location": f"{loc.get('country','')} {loc.get('province','')} {loc.get('city','')}".strip(),
        "carrier": basic.get("carrier", ""),
        "asn": f"AS{asn.get('number','')} {asn.get('info','')}".strip(),
        "active_intels": intels[:10],
        "update_time": data.get("update_time", ""),
    }

该函数是本脚本的"信息压缩器",做了四件事:

  1. 恶意判定 :直接取出 judgments 列表(如 ZombieGatewayWhitelistCDN 等),作为首要研判依据。
  2. 基础信息 :从 basic.location 拼接 国家 省份 城市,取 basic.carrier 运营商;从 asn 拼出 AS号 名称
  3. 活跃情报过滤 :遍历 intelligences(按情报源分组),仅保留未过期(expired 为 False)的情报条目,并记录来源、威胁类型、置信度、发现时间------这是"证据链"的核心。
  4. 数量裁剪intels[:10] 最多保留 10 条活跃情报,控制输出体积,避免超长 JSON 影响下游解析。

4.5 main():命令行编排与容错

python 复制代码
def main():
    ips = sys.argv[1:] or DEFAULT_IPS
    key = load_key()
    out = []
    for ip in ips:
        try:
            d = query(key, ip)
            if d.get("response_code") != 0 or ip not in (d.get("data") or {}):
                out.append({"ip": ip, "error": d.get("verbose_msg", "查询失败")})
                continue
            out.append(summarize(ip, d["data"][ip]))
        except Exception as e:
            out.append({"ip": ip, "error": str(e)})
    print(json.dumps(out, ensure_ascii=False, indent=2))
  • 参数兜底sys.argv[1:] or DEFAULT_IPS ------ 支持命令行传入任意数量 IP;不传参数时自动查询默认监测名单(三个单位公网 IP)。
  • 业务级容错 :微步返回 response_code 非 0(如 Key 失效、IP 无效)或 data 中不含该 IP 时,记录 verbose_msg 错误信息,不中断整体流程。
  • 异常级容错 :网络异常、超时、JSON 解码失败等统一 except Exception 捕获,单 IP 失败不影响其他 IP 的查询。
  • 输出契约 :最终 json.dumps(out, ensure_ascii=False, indent=2) 输出格式化 JSON(保留中文),该 JSON 是平台 / AI 解析的统一契约格式。

五、部署与使用

5.1 部署清单

项目 位置 说明
脚本 ~/.config/threatbook/threatbook_query.py 纯标准库,无第三方依赖
API Key ~/.config/threatbook/api_key 微步控制台申请,chmod 600
授权 chmod 600 threatbook_api_key 仅当前用户可读写

部署命令:

bash 复制代码
# 1. 放置脚本与密钥
mkdir -p ~/.config/threatbook
# ... 将 threatbook_query.py 与 threatbook_api_key 放入该目录 ...

# 2. 收紧密钥权限
chmod 600 ~/.config/threatbook/api_key

# 3. 校验脚本语法
python3 -m py_compile ~/.config/threatbook/threatbook_query.py

5.2 命令行用法

bash 复制代码
# 查询单个 IP
python3 ~/.config/threatbook/threatbook_query.py 1.1.1.1

# 查询多个 IP(空格分隔)
python3 ~/.config/threatbook/threatbook_query.py 1.1.1.1 8.8.8.8

# 不传参数:查询默认监测名单
python3 ~/.config/threatbook/threatbook_query.py

5.3 真实输出示例(8.8.8.8,实测于本机)

以 Google 公共 DNS 8.8.8.8 为例,验证脚本功能正常:

json 复制代码
[
  {
    "ip": "8.8.8.8",
    "judgments": [
      "Gateway",
      "Whitelist",
      "CDN"
    ],
    "location": "United States",
    "carrier": "Google LLC",
    "asn": "AS15169 GOOGLE",
    "active_intels": [
      {
        "source": "threatbook_lab",
        "types": [
          "Gateway"
        ],
        "confidence": 75,
        "find_time": "2025-12-09 06:17:42"
      },
      {
        "source": "threatbook_lab",
        "types": [
          "CDN"
        ],
        "confidence": 85,
        "find_time": "2023-10-19 23:30:02"
      },
      {
        "source": "threatbook_lab",
        "types": [
          "Whitelist"
        ],
        "confidence": 100,
        "find_time": "2020-11-29 03:23:39"
      },
      {
        "source": "threatbook_lab",
        "types": [
          "Whitelist"
        ],
        "confidence": 100,
        "find_time": "2016-01-13 20:34:26"
      },
      {
        "source": "open_source",
        "types": [
          "Phishing"
        ],
        "confidence": 55,
        "find_time": "2023-03-17 02:06:22"
      },
      {
        "source": "open_source",
        "types": [
          "Suspicious"
        ],
        "confidence": 65,
        "find_time": "2018-09-21 09:00:31"
      },
      {
        "source": "open_source",
        "types": [
          "Suspicious"
        ],
        "confidence": 65,
        "find_time": "2018-03-01 06:04:34"
      },
      {
        "source": "open_source",
        "types": [
          "Suspicious"
        ],
        "confidence": 65,
        "find_time": "2017-09-20 13:52:07"
      },
      {
        "source": "open_source",
        "types": [
          "Spam"
        ],
        "confidence": 65,
        "find_time": "2017-09-12 02:31:14"
      },
      {
        "source": "open_source",
        "types": [
          "Suspicious"
        ],
        "confidence": 65,
        "find_time": "2017-07-07 08:25:37"
      }
    ],
    "update_time": "2026-08-11 06:01:47"
  }
]

结果解读 :8.8.8.8 的 judgmentsGateway / Whitelist / CDN,均为良性标签;threatbook_lab 高置信度(75-100)情报指向 Gateway、CDN、Whitelist,符合 Google 公共 DNS 的定位;open_source 来源存在少量历史 Phishing / Suspicious / Spam 标签(置信度 55-65),属于开源情报的宽泛收录,不影响整体良性判定。脚本输出质量符合预期。


六、平台整合:注册进 BruceSec 安全平台

6.1 tools/threatbook_query.yaml 注册文件

将脚本以 MCP 工具形式注册进 BruceSec 平台,配置文件为 tools/threatbook_query.yaml

yaml 复制代码
name: "threatbook_query"
command: "/usr/bin/python3"
# 固定参数:微步 IP 情报查询脚本(绝对路径,避免 PATH 依赖)
args: ["~/.config/threatbook/threatbook_query.py"]
enabled: true
short_description: "微步在线 IP 威胁情报查询:威胁标签/恶意判定/位置/ASN(需 API Key,已绑定出口IP)"
description: |
  微步在线 IP 威胁情报查询(v3/ip/query,全维度标签)。

  **能力:**
  - 查询单个或多个 IP 的威胁情报
  - 返回 `judgments` 恶意判定、威胁标签(Zombie/Scanner/Compromised/C2 等)、情报置信度
  - 返回位置、运营商、ASN 信息

  **用法:**
  - 只传 `ip` 即可,例如 `1.1.1.1`;多个 IP 用空格分隔(如 `1.1.1.1 8.8.8.8`)
  - 不传 `ip` 时默认查询监测名单:`203.0.113.11 203.0.113.12 203.0.113.13`

  **注意:**
  - API Key 存于 `~/.config/threatbook/api_key`(chmod 600),需在微步控制台绑定请求出口 IP,否则报 Invalid Access IP
  - 输出为 JSON,`judgments` 为空数组通常表示情报未知/无恶意标签
parameters:
  - name: "ip"
    type: "string"
    description: |
      目标 IP(可多个,空格分隔)。示例:`203.0.113.11`、`1.1.1.1 8.8.8.8`。
      留空默认查询监测名单三个 IP。
    required: false
    position: 1
    format: "positional"

设计要点:

  • command + args 分离command 固定为 /usr/bin/python3,脚本路径放入 args 绝对路径,避免 PATH 依赖,保证平台侧稳定执行。
  • enabled: true:工具注册后立即生效,可被 AI 会话调用。
  • description 分层short_description 精简摘要供工具列表展示;description 详述能力、用法、注意事项(Key 绑定、默认名单、JSON 语义),供 AI 深度理解及 resources/read 查询。
  • 参数契约 :定义 ippositional 位置参数,支持多 IP 空格分隔,留空走默认监测名单。

6.2 ApplyConfig 热重载验证

BruceSec 平台支持配置热重载,无需重启进程即可应用新增工具。实测验证过程(由平台浏览器 Agent 执行):

  1. 登录状态 :平台已登录(用户为管理员 admin,拥有 config:write 等完整权限)。
  2. 触发热重载 :调用后端 POST /api/config/apply 接口(携带 Bearer token)。
  3. 返回结果 :HTTP 200,响应体为:
json 复制代码
{"message":"配置已应用","tools_count":93}
  1. 工具列表验证 :通过 /api/config/tools 接口分页检索(平台共 141 个工具),确认 threatbook_query 存在且 enabled: true

6.3 MCP 管理页确认(含截图)

平台 MCP 管理页(#mcp-management)搜索过滤后显示:

  • 名称:threatbook_query
  • 状态:常驻(已启用),复选框已勾选
  • 描述:"微步在线 IP 威胁情报查询:威胁标签/恶意判定/位置/ASN(需 API Key,已绑定出口IP)"
  • 页面统计:当前页已启用 1/1,总计已启用 1/1

截图说明:图中为 BruceSecAI 安全管理平台" MCP 管理"页面(暗色主题,左侧功能导航栏,顶部有 API 文档、GitHub、语言切换等元素),threatbook_query 工具显示为已启用(勾选 + "常驻"),确认平台整合成功。

至此,threatbook_query 已可在平台对话中直接调用,例如:"查询 1.1.1.1 的微步情报"。


七、实际应用:三个监测 IP 的微步判定与 nmap 对照

7.1 微步情报查询结果(实测于本机)

对默认监测名单中的三个公网 IP 执行脚本查询,真实结果如下:

IP judgments 判定 位置 运营商 ASN 活跃情报(未过期) 情报更新时间
203.0.113.11 Zombie、Gateway 中国(省市已脱敏) ISP 已脱敏 ASN 已脱敏 Gateway(75)、Zombie(75)、Mobile(50) 2026-08-10 16:39:39
203.0.113.12 Gateway 中国(省市已脱敏) ISP 已脱敏 ASN 已脱敏 Gateway(75)、Mobile(50) 2026-08-10 17:18:04
203.0.113.13 Gateway 中国(省市已脱敏) ISP 已脱敏 ASN 已脱敏 Gateway(75)、Mobile(50) 2026-08-10 17:52:36

原始 JSON(203.0.113.11,截取关键字段):

json 复制代码
{
  "ip": "203.0.113.11",
  "judgments": ["Zombie", "Gateway"],
  "location": "China (region redacted)",
  "carrier": "[ISP 已脱敏]",
  "asn": "[ASN 已脱敏]",
  "active_intels": [
    {"source": "threatbook_lab", "types": ["Gateway"], "confidence": 75, "find_time": "2025-12-08 23:21:29"},
    {"source": "threatbook_lab", "types": ["Zombie"], "confidence": 75, "find_time": "2017-02-23 19:36:24"},
    {"source": "open_source", "types": ["Mobile"], "confidence": 50, "find_time": "2021-08-03 02:34:26"}
  ],
  "update_time": "2026-08-10 16:39:39"
}

7.2 判定结论解读

  1. 203.0.113.11 :出现 Zombie(僵尸网络)判定标签,threatbook_lab 来源置信度 75,发现时间 2017-02-23------属于历史情报(早期被标记为僵尸网络节点),同时具备 Gateway 标签(ISP 已脱敏骨干网网关特征)。结论:存在历史僵尸网络关联记录,需持续关注,但非近期活跃威胁(最新活跃情报为 2025-12-08 的 Gateway 标签)。
  2. 203.0.113.12 :仅 Gateway 判定,无恶意标签,运营商为中国ISP 已脱敏,(省市已脱敏)(省市已脱敏),ASN 已脱敏结论:当前情报面无恶意标记。
  3. 203.0.113.13 :仅 Gateway 判定,中国ISP 已脱敏,(省市已脱敏)(省市已脱敏),ASN 已脱敏结论:当前情报面无恶意标记。

三个 IP 的 judgments 均包含 Gateway,与其作为运营商骨干网/出口网关的属性一致;唯一需要重点关注的是 203.0.113.11 的 Zombie 历史标签。

7.3 与 nmap 主动扫描对照

将微步被动情报与 nmap 主动扫描结果对照(nmap 扫描文件记录了前两个目标,实测于 2026-08-14):

IP nmap 主动扫描结论 微步情报结论 对照分析
203.0.113.11 100 端口全部 filtered(34.26s),无服务信息 Zombie + Gateway,ISP 已脱敏ASN 已脱敏 主动探测被防火墙完全屏蔽,但情报仍给出"僵尸网络历史标签"这一主动扫描无法获得的关键信息
203.0.113.12 10 个端口(53/80/135/139/443/445/3128/5800/5900/8080)全部 filtered Gateway,ISP 已脱敏ASN 已脱敏 防火墙过滤了全部常见服务端口,情报侧同样无恶意标签,两者结论一致(未发现攻击迹象)
203.0.113.13 本次扫描文件中未包含该目标结果 Gateway,ISP 已脱敏ASN 已脱敏 情报侧无恶意标记;nmap 未执行/未记录,建议补充主动扫描对照

对照结论 :在边界防火墙严格过滤(filtered)导致主动扫描近乎失效的场景下,微步威胁情报提供了补充视角------尤其是 203.0.113.11 的 Zombie 历史标签,仅靠 nmap 无法获得。两者结合,构成了"主动 + 被动"双通道的公网 IP 攻击迹象监测方案。


八、安全与合规

  1. 仅限授权资产:本脚本仅用于本单位/已获授权的公网 IP 监测,严禁对未授权目标进行批量查询与研判。微步情报查询虽属被动行为,但将查询行为与具体业务场景绑定,避免被滥用为"踩点工具"。
  2. API Key 保护
    • Key 独立存放于 threatbook_api_key 文件,并 chmod 600 限制为仅当前用户可读写;
    • 代码与密钥分离,脚本中不出现任何硬编码 Key;
    • 平台侧 yaml 只引用密钥文件路径,不记录 Key 明文。
  3. 出口 IP 绑定 :Key 在微步控制台绑定请求出口 IP,既是访问控制,也是 Key 泄露时的第一道止损防线(泄露后在其他 IP 上无法使用,并报 Invalid Access IP)。
  4. 配额管理 :脚本单次调用设置 30 秒超时、单 IP 失败不重试(except Exception 直接记录错误),避免异常循环消耗配额;建议结合微步控制台配额额度按需调用(本项目为按需查询场景,未做高频轮询),并关注控制台配额与速率限制告警。
  5. 数据最小化summarize 只保留研判所需字段(判定、位置、运营商、ASN、未过期情报 top10),不落盘原始全量响应,减少敏感数据暴露面。

九、总结

threatbook_query.py 以不足百行的纯标准库代码,打通了"公网 IP 攻击迹象监测"的威胁情报链路:

  • 解决痛点 :在 nmap 等主动扫描被边界防火墙大面积 filtered 限制的场景下,通过微步 v3/ip/query 被动情报补充主动扫描无法获取的"历史行为视角",成功识别出 203.0.113.11 的 Zombie 历史标签。
  • 工程实践:密钥分离 + chmod 600、接口调用超时与双层容错、JSON 摘要契约,保证了脚本在批量监测中的健壮性。
  • 平台整合 :通过 tools/threatbook_query.yaml(enabled: true)+ POST /api/config/apply 热重载(实测返回 HTTP 200、tools_count: 93)一键注册为 MCP 工具,并在 MCP 管理页确认"常驻(已启用)",使 AI 会话可直接调用。
  • 可扩展方向 :可将情报查询结果与告警平台联动(如对含 Zombie/C2 等恶意判定且置信度较高的 IP 触发告警),并定期与 nmap 主动扫描做周期性对照,形成常态化的公网资产威胁监测报表。

本文所有 IP 判定、接口返回、平台热重载数据均来自本机实测(2026-08-14),截图来自 BruceSec 平台 MCP 管理页实拍。

相关推荐
码农颜1 小时前
5.6.2 ⾏级锁死锁
数据库·sql·oracle
ZJU_统一阿萨姆1 小时前
【DSH】如何将 DeepSeek Harness 嵌入生产环境?万字解构 DeepSeek Agent Harness 的运行机制与安全边界
前端·javascript·安全
明航咨询_贾老师1 小时前
CISP-AISE知识体系大纲深度解读:6大模块,国内首个AI安全应用官方认证
人工智能·安全
ChaHae-In2 小时前
MyBatis动态SQL与MyBatis-Plus高效开发指南
数据库·oracle·mybatis
冰暮流星2 小时前
mysql之分组查询
数据库·mysql
80s7772 小时前
独享住宅IP、长效代理ip是什么?有哪些作用?
网络·网络协议·tcp/ip
IPdodo_2 小时前
静态 IP、住宅 IP 和固定出口有什么区别?开发场景选型指南
服务器·网络·网络协议·tcp/ip·代理ip
倒流时光三十年2 小时前
PostgreSQL Semi-Join(半连接)通俗讲解
数据库·postgresql