手写一个 OpenClaw 插件:让 AI 自动扫描端口(安全测试+龙虾结合)
上篇文章我们聊了 OpenClaw 这只“AI龙虾”到底有多 Hackable,评论区炸出一堆安全圈的老铁。有人问:能不能让龙虾自己干渗透测试的活?
能。
这周我花了几个晚上,手写了一个 network-scan 插件——让 OpenClaw 能调用 nmap 自动扫描端口、识别开放服务,然后把结果整理成报告发给我。
这篇文章不讲虚的,全是能直接复制粘贴的代码和踩坑实录。跟着做,你也能让龙虾替你干活。
🔍 一、为什么是端口扫描?
端口扫描是渗透测试的“敲门砖”。扫到开放端口,才能知道目标跑了什么服务、有没有漏洞。
让 AI 来做这件事,价值在于:
-
自动化:不用一条条敲命令,一句话搞定
-
可编排:扫完端口 → 识别服务 → 查漏洞库 → 生成报告,全流程自动跑
-
省手:晚上挂上任务,早上收报告
OpenClaw 官方的技能市场已经有一个现成的 network-scan 技能,但它需要手动配置 nmap 路径。我们干脆从头写一个,顺便搞懂插件的底层逻辑。
🛠️ 二、开发前准备
2.1 环境要求
-
OpenClaw 已安装并运行(参考上篇文章)
-
nmap 已安装:
sudo apt install nmap -y(Linux/WSL) -
Node.js 18+(OpenClaw 插件用 JS/TS 开发)
2.2 搞清楚:Skill vs Plugin
OpenClaw 的扩展体系分三层:Skill(策略层)→ Hook(拦截层)→ Plugin(系统层)。
我们要做的是 Plugin——因为需要注册一个全新的工具(nmap扫描),这属于“加新功能”,必须走 Plugin 路线。
极简判断口诀:
-
只教 Agent 怎么做事 → 用 Skill
-
只改运行时流程 → 用 Hook
-
要加新功能/新服务 → 用 Plugin ✅
📁 三、动手写插件
3.1 目录结构
text
network-scanner/
├── openclaw.plugin.json # 插件配置(必选)
├── index.js # 插件入口(必选)
└── README.md # 说明文档(可选)
3.2 创建配置文件 openclaw.plugin.json
json
{"id":"network-scanner","version":"1.0.0","main":"./index.js","description":"让AI调用nmap进行端口扫描,支持IP范围、CIDR、端口过滤","configSchema":{"type":"object","properties":{"nmap_path":{"type":"string","default":"nmap","description":"nmap可执行文件路径"},"default_ports":{"type":"string","default":"22,80,443,3306,8080","description":"默认扫描端口"},"timeout":{"type":"integer","default":30,"description":"扫描超时时间(秒)"}}}}
3.3 编写核心代码 index.js
这是插件的灵魂,核心逻辑是:接收 AI 传来的目标参数 → 调用 nmap 执行扫描 → 解析结果返回。
javascript
import{ exec }from'child_process';import{ promisify }from'util';import{ Type }from'@sinclair/typebox';const execAsync =promisify(exec);exportdefaultfunction(api){// 注册一个名为 port_scan 的工具 api.registerTool({name:'port_scan',description:'使用nmap扫描目标主机的开放端口。支持单个IP、IP范围(192.168.1.1-254)、CIDR(192.168.1.0/24)。返回JSON格式的扫描结果。',parameters: Type.Object({target: Type.String({description:'扫描目标,如 192.168.1.1 或 192.168.1.0/24'}),ports: Type.Optional(Type.String({description:'指定端口,如 22,80,443 或 1-1000,默认使用配置的default_ports'})),fast: Type.Optional(Type.Boolean({description:'快速模式,使用 -T4 加速扫描',default:false}))}),asyncexecute(toolCallId, params){const{ target, ports, fast }= params;const config = api.getConfig();const nmapPath = config.nmap_path ||'nmap';const defaultPorts = config.default_ports ||'22,80,443,3306,8080';const timeout = config.timeout ||30;// 确定扫描端口const scanPorts = ports || defaultPorts;// 构建 nmap 命令let cmd =`${nmapPath} -p ${scanPorts} -oG -`;if(fast) cmd +=' -T4'; cmd +=`${target}`;try{ api.logger.info(`执行扫描: ${cmd}`);// 执行扫描,带超时控制const timeoutPromise =newPromise((_, reject)=>setTimeout(()=>reject(newError('扫描超时')), timeout *1000));const scanPromise =execAsync(cmd,{timeout: timeout *1000});const{ stdout, stderr }=await Promise.race([scanPromise, timeoutPromise]);if(stderr &&!stderr.includes('Warning')){return{content:[{type:'text',text:`扫描出错: ${stderr}`}]};}// 解析 nmap grepable 输出const results =parseNmapOutput(stdout);return{content:[{type:'text',text:JSON.stringify(results,null,2)}]};}catch(error){ api.logger.error(`扫描失败: ${error.message}`);return{content:[{type:'text',text:`扫描失败: ${error.message}`}]};}}}); api.logger.info('network-scanner 插件已加载');}/** * 解析 nmap -oG 格式输出 * 输入格式: Host: 192.168.1.1 () Ports: 22/open/tcp//ssh//, 80/open/tcp//http// * 输出 JSON 数组 */functionparseNmapOutput(output){const results =[];const lines = output.split('\n');for(const line of lines){if(!line.startsWith('Host:'))continue;// 提取 IPconst ipMatch = line.match(/Host:\s+([^\s]+)/);if(!ipMatch)continue;const host ={ip: ipMatch[1],ports:[]};// 提取端口信息const portsMatch = line.match(/Ports:\s+(.+)/);if(portsMatch){const portsStr = portsMatch[1];const portPattern =/(\d+)\/(\w+)\/tcp\/\/([^\/]+)/g;let match;while((match = portPattern.exec(portsStr))!==null){ host.ports.push({port:parseInt(match[1]),state: match[2],service: match[3]||'unknown'});}} results.push(host);}return results;}
3.4 安装插件
将 network-scanner 文件夹放到 OpenClaw 的插件目录:
bash
# 插件目录位置(根据你的安装方式可能不同)cp-r network-scanner ~/.openclaw/plugins/# 或者用官方命令安装openclaw plugin install--path ./network-scanner
重启 OpenClaw 使插件生效:
bash
openclaw gateway restart
查看插件是否加载成功:
bash
openclaw plugin list# 应该能看到 network-scanner 出现在列表中
🧪 四、实战测试:让 AI 自己扫端口
4.1 基础测试
插件装好后,在 OpenClaw 对话中输入:
帮我扫描一下 127.0.0.1 的端口,看看开了哪些服务
AI 会调用 port_scan 工具,返回类似这样的结果:
json
[{"ip":"127.0.0.1","ports":[{"port":22,"state":"open","service":"ssh"},{"port":80,"state":"open","service":"http"},{"port":3306,"state":"open","service":"mysql"}]}]
4.2 高级用法:批量扫描内网
扫描 192.168.1.0/24 网段,只扫 22,80,443 端口,用快速模式
AI 会自动带上 fast=true 和 ports=22,80,443 参数,并发执行扫描。
4.3 结合渗透测试流程
这才是真正好玩的地方——你可以让 AI 串联多个工具:
先扫描 example.com 的开放端口,然后针对 80 和 443 端口,用浏览器访问看看有什么信息泄露
OpenClaw 会:
-
调用
port_scan扫端口 -
拿到结果后,自动调用
browser工具访问对应端口 -
汇总两份结果给你
⚠️ 五、安全提醒:龙虾不是刀,是拿刀的手
插件写完了,但有些话必须说在前面。
5.1 权限控制:别让龙虾裸奔
在插件配置里,我把 port_scan 设为了 可选工具(optional: true)。这意味着:
-
用户必须手动在白名单中启用它
-
AI 不能擅自调用高权限工具
启用方式:
bash
# 在 config.json 中配置{"tools":{"allow":["port_scan"]}}
5.2 扫描前先问一句
建议在 AGENTS.md 或系统提示词中加一条约束:
在执行 port_scan 之前,必须先询问用户确认目标是否授权。禁止扫描未经授权的IP地址。
5.3 扫描目标的法律边界
重要:用这个插件扫描别人的服务器,必须获得授权。私自扫描他人系统可能触犯法律(如《网络安全法》)。
本文仅用于学习研究和授权测试。
📦 六、进阶:从插件到完整的渗透测试 Skill
如果你想让龙虾成为一个真正的“AI渗透测试助手”,可以继续叠加能力:
|
|
|
|---|---|
|
|
subdomain_bruteforce 工具 |
|
|
dirbuster 工具,调用 ffuf |
|
|
sql_injection_test 工具 |
|
|
cve_search 工具,对接 NVD API |
把这些工具串起来,加上 任务模板 和 结果自动传递,就能实现:
一句话:帮我测一下 example.com,挖个洞出来。
AI 会自动:子域名枚举 → 端口扫描 → 目录探测 → SQL注入测试 → 生成报告。
我在 GitHub 上看到有研究团队用类似思路,1 小时 40 分钟就挖出了一个 OpenClaw 自身的 0day(CVE-2026-22708)。这说明 AI 辅助渗透测试的能力已经被验证了。
🎯 七、总结
这篇文章,我们从 0 到 1 写了一个 OpenClaw 端口扫描插件,核心代码不到 100 行。
你学会了:
-
OpenClaw Plugin 的标准目录结构
-
如何注册一个带参数校验的 Tool
-
如何调用系统命令并解析返回结果
-
插件的安全配置方法
你可以继续做的:
-
添加更多扫描参数(如
-sV版本探测、-sC默认脚本) -
对接 CVE 漏洞库,自动识别高危端口
-
写一个 Skill 来串联多个工具,实现自动化渗透流程
-
官方文档:OpenClaw Plugin 开发指南
-
现有技能市场:
npx clawhub@latest install network-scan -
本文完整代码:自己写啊!等着我喂饭啊
让 AI 帮你干活是件很爽的事,但别把安全丢在脑后。龙虾是工具,你才是主人。用好它,别被它用。
截图不贴因为误删了
下篇预告:我用 OpenClaw 挖到了一个真实漏洞,全过程复盘。欢迎关注。
夜雨聆风