网络发现MCP-用户指南
一种模块化、容器化的网络发现服务,用于自动化网络映射和分析。网络发现MCP自动发现网络设备,收集配置,并从单个种子设备开始生成交互式拓扑可视化。
目录
______________________________________________________________________
概述
网络发现MCP提供自动化的网络基础设施发现和映射。该系统支持两种发现方法:
发现方法1:种子装置发现
- 连接到单个“种子”网络设备
- 通过以下方式自动发现网络拓扑:
- 接口信息(子网、VRF) - 路由表(已知网络) - ARP表(活动主机) - CDP/LDP邻居(直接连接的设备)
- 扫描所有发现的IP地址以获取可达性
- 确定设备供应商和型号
- 收集设备配置
- 生成交互式网络拓扑可视化
在以下情况下使用此方法:您可以通过网络访问设备,并希望自动发现拓扑结构。
发现方法2:直接IP/子网扫描
- 直接接受IP地址或子网列表
- 扫描提供的地址以查找可达性
- 确定设备供应商和型号
- 收集设备配置
- 生成网络拓扑可视化
在以下情况下使用此方法:您有设备IP的真实来源(如NetBox、电子表格或IPAM),并希望跳过拓扑发现。
操作模式
该服务可以在两种模式下运行:
- REST API模式:用于与脚本、工具和CI/CD管道集成的传统HTTP API
- MCP模式:用于直接AI代理集成的模型上下文协议接口
这两种模式都提供了相同的功能,但集成模式不同。
______________________________________________________________________
特性
核心发现功能
- 自动网络映射:从单个种子设备发现整个网络拓扑
- 智能多供应商支持:登录后自动检测设备操作系统(思科、瞻博网络、Arista、帕洛阿尔托、Fortinet、华为)
- 增强型设备指纹识别:通过支持Arista EOS、Juniper JUNOS和Palo Alto PAN-OS,改进了供应商识别
- 并行操作:高性能扫描和配置收集
- 配置管理:使用特定于供应商的命令安全地收集和存储设备配置
- 交互式可视化:生成带有颜色编码设备状态的交互式HTML网络拓扑图
- 蝙蝠鱼一体化:高级网络分析和验证
可靠性特征
- 凭证验证:在开始昂贵的操作之前测试凭据(在失败时节省30多分钟)
- 工作简历:恢复失败的作业,而不重新执行已完成的工作(对于大型网络至关重要)
- 重试逻辑:针对瞬态故障,采用指数回退自动重试
- 超时处理:可配置的超时可防止挂起操作
- 优雅地关闭:集装箱环境的清洁停机处理
监测和可观察性
- 系统健康检查:在开始扫描之前监视系统资源
- 作业统计:详细的进度跟踪和成功指标
- 失效分析:故障排除的智能建议
- 历史跟踪:跟踪一段时间内的工作历史和成功率
智能功能
- 自动操作系统检测:SSH登录后检测设备操作系统(无需平台参数)
- 供应商特定命令:自动为每个供应商选择正确的命令
- 指纹校正:通过验证操作系统身份验证后的错误识别
- 回退机制:如果操作系统检测失败,则使用指纹数据
安全功能
- 安全凭证处理:日志和表示中隐藏的密码
- 原子文件操作:防止写入过程中的数据损坏
- 集装箱隔离:在隔离的容器环境中运行
- 可选HTTPS:支持加密MCP通信
______________________________________________________________________
入门指南
先决条件
- 已安装Docker和Docker Compose
- 对要发现的设备的网络访问
- 至少一个“种子”设备的有效凭据
快速开始
- 克隆存储库:
git clone https://github.com/username/network-discovery-mcp.git
cd network-discovery-mcp- 选择部署模式:
对于REST API模式:
docker compose up -d对于MCP模式(AI代理):
docker compose -f docker-compose.mcp.yml up -d- 验证服务是否正在运行:
REST API:
curl http://localhost:8000/healthMCP:
curl http://localhost:8080/mcp- 启动发现(REST API示例):
curl -X POST http://localhost:8000/v1/seed \
-H "Content-Type: application/json" \
-d '{
"seed_host": "192.168.1.1",
"credentials": {
"username": "admin",
"password": "your_password"
},
"methods": ["interfaces", "routing", "arp", "cdp"]
}'备注:The platform 参数(如 cisco_ios)现在是可选的!登录后,系统会自动检测设备操作系统,并选择相应的命令。您仍然可以提供 platform 如有需要,作为备选方案。
响应中包含一个job_id,可用于跟踪进度和检索结果。
______________________________________________________________________
部署模式
REST API模式(默认)
REST API模式为编程访问提供了传统的HTTP端点。
在以下情况下使用此模式:
- 与现有工具和脚本集成
- 从CI/CD管道运行
- 构建自定义应用程序
- 您需要与语言无关的HTTP访问
正在启动REST API模式:
docker compose up -d访问API:
- API基本URL:
http://localhost:8000 - API文件:
http://localhost:8000/docs - 健康检查:
http://localhost:8000/health
配置文件: docker-compose.yml
______________________________________________________________________
MCP模式(AI代理集成)
MCP模式为AI代理集成提供了一个模型上下文协议接口。
在以下情况下使用此模式:
- 与AI代理(Claude、GPT等)集成
- 构建自主网络发现工作流
- 你想要人工智能驱动的网络运营
启动MCP模式:
docker compose -f docker-compose.mcp.yml up -d访问MCP服务器:
- MCP端点:
http://localhost:8080/mcp - 健康检查:
http://localhost:8080/health
配置文件: docker-compose.mcp.yml
带HTTPS的MCP
一些AI代理框架(如某些Claude实现或企业AI平台)需要HTTPS连接,并且不接受HTTP。如果您的AI代理需要HTTPS,则需要配置SSL证书。
何时使用HTTPS:
- 您的AI代理框架拒绝HTTP连接
- 您的AI代理正在另一个网络上运行,需要加密
- 公司安全政策要求加密通信
- 您正在将MCP服务器暴露在互联网上
先决条件:
- SSL证书文件(fullchain.pem或certificate.crt)
- SSL私钥文件(privkey.pem或private.key)
第一步:准备证书
选项A-使用Let's Encrypt证书:
# If using Let's Encrypt/Certbot, certificates are typically at:
# Certificate: /etc/letsencrypt/live/yourdomain.com/fullchain.pem
# Private key: /etc/letsencrypt/live/yourdomain.com/privkey.pem选项B-使用自签名证书(用于测试):
# Generate self-signed certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout privkey.pem \
-out fullchain.pem \
-subj "/CN=localhost"选项C-使用公司证书:
# Use certificates provided by your organization
# Ensure you have both the certificate and private key files步骤2:修改docker-compose.mcp.yml
编辑 docker-compose.mcp.yml 用于装载证书的文件:
services:
network-discovery-mcp:
build:
context: .
dockerfile: Dockerfile
container_name: network-discovery-mcp
environment:
- ENABLE_MCP=true
- TRANSPORT=https # Set transport to https
- PORT=8080
- HOST=0.0.0.0
- ARTIFACT_DIR=/artifacts
- BATFISH_HOST=batfish
- LOG_LEVEL=info
ports:
- "8080:8080" # HTTP port (optional, for health checks)
- "443:443" # HTTPS port (required)
volumes:
- ./artifacts:/artifacts
# Mount your SSL certificates (REQUIRED for HTTPS):
- /path/to/your/fullchain.pem:/certs/fullchain.pem:ro
- /path/to/your/privkey.pem:/certs/privkey.pem:ro
depends_on:
- batfish
networks:
- discovery-network
batfish:
image: batfish/batfish:latest
container_name: batfish
ports:
- "9996:9996"
- "9997:9997"
networks:
- discovery-network
networks:
discovery-network:
driver: bridge重要变更:
- 改变
TRANSPORT从http到https - 添加端口映射
443:443 - 取消注释并使用您的实际证书路径更新证书卷装载
- 替换
/path/to/your/带有证书的实际路径
步骤3:启动服务
# Start with HTTPS enabled
docker compose -f docker-compose.mcp.yml up -d
# Check logs to verify HTTPS is working
docker compose -f docker-compose.mcp.yml logs network-discovery-mcp
# You should see logs indicating nginx started with HTTPS on port 443步骤4:验证HTTPS是否正常工作
# Test HTTPS endpoint
curl https://localhost/mcp
# If using self-signed certificates, use -k to skip verification
curl -k https://localhost/mcp
# You should get a response from the MCP server步骤5:配置您的AI代理
更新您的AI代理配置以使用HTTPS端点:
# Example: Connecting AI agent to HTTPS MCP server
import mcp
# With valid certificates
client = mcp.Client("https://your-server.com/mcp")
# With self-signed certificates (development only)
import ssl
context = ssl._create_unverified_context()
client = mcp.Client("https://localhost/mcp", ssl_context=context)HTTPS故障排除
问题:“证书验证失败”
如果使用自签名证书,您的AI代理可能会拒绝它们。解决:
- 对于测试,请在代理中禁用证书验证(不建议用于生产)
- 将自签名证书添加到系统的受信任证书中
- 使用Let's Encrypt或CA的正确签名证书
问题:“端口443上的连接被拒绝”
检查:
# 1. Container is running
docker compose -f docker-compose.mcp.yml ps
# 2. Port 443 is mapped
docker compose -f docker-compose.mcp.yml port network-discovery-mcp 443
# 3. Nginx is running with HTTPS
docker compose -f docker-compose.mcp.yml logs network-discovery-mcp | grep nginx
# 4. Certificates are mounted correctly
docker exec network-discovery-mcp ls -la /certs/问题:“找不到证书”
容器在以下位置查找证书:
/certs/fullchain.pem/certs/privkey.pem
验证它们是否已安装:
docker exec network-discovery-mcp ls -la /certs/
# Should show both files示例:使用Let's Encrypt完成HTTPS设置
# 1. Obtain Let's Encrypt certificates (on host machine)
sudo certbot certonly --standalone -d your-domain.com
# 2. Update docker-compose.mcp.yml with certificate paths
# Edit the volumes section:
volumes:
- ./artifacts:/artifacts
- /etc/letsencrypt/live/your-domain.com/fullchain.pem:/certs/fullchain.pem:ro
- /etc/letsencrypt/live/your-domain.com/privkey.pem:/certs/privkey.pem:ro
# 3. Ensure TRANSPORT is set to https
# environment:
# - TRANSPORT=https
# 4. Start the service
docker compose -f docker-compose.mcp.yml up -d
# 5. Test HTTPS connection
curl https://your-domain.com/mcp
# 6. Configure AI agent to use HTTPS endpoint
# In your AI agent config:
# mcp_server_url: https://your-domain.com/mcpHTTP与HTTPS决策矩阵
| 场景 | 使用HTTP | 使用HTTPS |
|---|---|---|
| 在同一台机器上使用AI代理进行本地测试 | 是 | 否 |
| AI代理框架需要HTTPS | 否 | 是 |
| 通过网络暴露MCP服务器 | 否 | 是 |
| 公司安全政策 | 否 | 是 |
| 不同网络上的AI代理 | 否 | 是 |
| 开发/测试环境 | 是 | 可选 |
| 生产环境 | 否 | 是 |
摘要:
- HTTP(端口8080)更便于本地测试
- 不接受HTTP的AI代理框架需要HTTPS(端口443)
- 该服务会自动检测已装载的证书并启用HTTPS
- HTTP和HTTPS可以同时运行(对端口8080上的健康检查很有用)
测试您的MCP服务器
您可以使用标准HTTP工具测试MCP服务器:
# Test HTTP MCP server
curl http://localhost:8080/mcp
# Test HTTPS MCP server
curl https://localhost/mcp --insecure
# Check available tools (pretty print)
curl http://localhost:8080/mcp | jq '.tools'
# Verify specific tool availability
curl http://localhost:8080/mcp | jq '.tools[] | select(.name=="run_network_discovery")'如果您在本地安装了官方MCP SDK中的MCP Inspector工具,您也可以使用它,或者直接与Claude Desktop、Cline或其他MCP兼容客户端等AI代理框架集成。
______________________________________________________________________
单容器部署
对于想要更多控制或不需要蝙蝠鱼的高级用户:
REST API模式:
docker run -d \
-p 8000:8000 \
-e ARTIFACT_DIR=/data \
-v /path/to/artifacts:/data \
ghcr.io/username/network-discovery-mcp:latestMCP模式(HTTP):
docker run -d \
-p 8080:8080 \
-e ENABLE_MCP=true \
-e TRANSPORT=http \
-e ARTIFACT_DIR=/data \
-v /path/to/artifacts:/data \
ghcr.io/username/network-discovery-mcp:latestMCP模式(HTTPS):
docker run -d \
-p 443:443 -p 8080:8080 \
-e ENABLE_MCP=true \
-e TRANSPORT=https \
-e ARTIFACT_DIR=/data \
-v /path/to/artifacts:/data \
-v /etc/ssl/certs/fullchain.pem:/certs/fullchain.pem:ro \
-v /etc/ssl/private/privkey.pem:/certs/privkey.pem:ro \
ghcr.io/username/network-discovery-mcp:latest注: 在没有Batfish容器的情况下运行会禁用拓扑可视化和分析功能。
______________________________________________________________________
使用REST API
REST API提供对所有网络发现功能的编程访问。
完成发现工作流程
下面是使用REST API发现网络的完整示例:
步骤1:验证凭据(推荐)
在开始发现之前测试凭据,以避免浪费时间:
curl -X POST http://localhost:8000/v1/credentials/validate \
-H "Content-Type: application/json" \
-d '{
"seed_host": "192.168.1.1",
"username": "admin",
"password": "cisco123"
}'备注:The platform 参数是可选的。连接后,系统将自动检测操作系统。
答复:
{
"valid": true,
"latency_ms": 2340,
"detected_vendor": "Cisco",
"detected_model": "IOS-XE",
"can_read_config": true
}如果凭据无效,在浪费时间进行发现之前,您将收到带有建议的错误。
步骤2:从设备中播种
从种子设备开始发现:
curl -X POST http://localhost:8000/v1/seed \
-H "Content-Type: application/json" \
-d '{
"seed_host": "192.168.1.1",
"credentials": {
"username": "admin",
"password": "cisco123"
},
"methods": ["interfaces", "routing", "arp", "cdp"]
}'备注:平台自动检测自动发生。您可以选择提供 "platform": "cisco_ios" 如果检测失败,则作为回退。
答复:
{
"job_id": "net-disc-20251102-123456",
"status": "completed",
"targets_count": 256,
"targets_path": "/artifacts/net-disc-20251102-123456/targets.json"
}保存 job_id 用于后续操作。
步骤3:扫描发现的目标
扫描发现的目标以获取可达性:
curl -X POST http://localhost:8000/v1/scan \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-20251102-123456",
"ports": [22, 443],
"concurrency": 200
}'答复:
{
"job_id": "net-disc-20251102-123456",
"status": "completed",
"hosts_scanned": 256,
"hosts_reachable": 42
}第四步:指纹识别设备
确定供应商和型号:
curl -X POST http://localhost:8000/v1/fingerprint \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-20251102-123456"
}'答复:
{
"job_id": "net-disc-20251102-123456",
"status": "completed",
"hosts_fingerprinted": 42,
"identified_count": 38
}步骤5:收集配置
收集设备配置(平台自动检测):
curl -X POST http://localhost:8000/v1/state/collect \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-20251102-123456",
"credentials": {
"username": "admin",
"password": "cisco123"
},
"concurrency": 50
}'备注:登录后,系统会自动检测每个设备的操作系统,并运行相应的命令:
- 思科:
show running-config - 阿里斯塔:
show running-config - 朱尼珀:
show configuration | display set - 帕洛阿尔托:
show config running - Fortinet:
show full-configuration - 华为:
display current-configuration
答复:
{
"job_id": "net-disc-20251102-123456",
"status": "completed",
"device_count": 42,
"success_count": 38,
"failed_count": 4
}步骤6:生成拓扑可视化
构建蝙蝠鱼快照并生成可视化:
# Build Batfish snapshot
curl -X POST http://localhost:8000/v1/batfish/build \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-20251102-123456"
}'
# Load into Batfish
curl -X POST http://localhost:8000/v1/batfish/load \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-20251102-123456"
}'
# Generate visualization
curl -X GET "http://localhost:8000/v1/batfish/topology/html?job_id=net-disc-20251102-123456" \
-o network_topology.html
# Open in browser
open network_topology.html步骤7:检查作业状态
随时监控进度:
curl http://localhost:8000/v1/status/net-disc-20251102-123456答复:
{
"job_id": "net-disc-20251102-123456",
"seeder": {
"status": "completed",
"targets_count": 256,
"completed_at": "2025-11-02T12:34:56Z"
},
"scanner": {
"status": "completed",
"hosts_scanned": 256,
"hosts_reachable": 42,
"completed_at": "2025-11-02T12:38:45Z"
},
"fingerprinter": {
"status": "completed",
"hosts_fingerprinted": 42,
"completed_at": "2025-11-02T12:40:22Z"
},
"state_collector": {
"status": "completed",
"device_count": 42,
"success_count": 38,
"failed_count": 4,
"completed_at": "2025-11-02T12:55:33Z"
}
}处理失败:工作简历
如果作业中途失败(例如,在配置收集期间),您可以在不重新执行已完成的工作的情况下恢复它:
# Check for resumable jobs
curl http://localhost:8000/v1/jobs/resumable
# Resume a specific job
curl -X POST http://localhost:8000/v1/jobs/resume \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-20251102-123456",
"credentials": {
"username": "admin",
"password": "cisco123",
"platform": "cisco_ios"
}
}'恢复操作:
- 检测哪些阶段已成功完成
- 跳过已完成的工作
- 仅检索失败或不完整的阶段
- 保存所有成功的结果
这对于大型网络至关重要,因为瞬态故障不需要重新启动整个发现过程。
替代方案:直接从子网扫描
如果您不需要基于种子的发现,并且已经拥有IP地址或子网列表(来自NetBox、IPAM、电子表格等),则可以直接扫描它们:
curl -X POST http://localhost:8000/v1/scan/from-subnets \
-H "Content-Type: application/json" \
-d '{
"job_id": "manual-scan-001",
"subnets": ["192.168.1.0/24", "10.0.0.0/24"],
"ports": [22, 443],
"concurrency": 200
}'然后像往常一样继续指纹识别和配置收集。
与真相来源系统合作
如果你在真相源系统(NetBox、phpIPAM等)中维护一个清单,你可以提取IP地址并直接扫描它们,而无需发现种子设备。
示例:使用NetBox作为真实来源
# 1. Query NetBox for device IPs (this is pseudocode)
DEVICE_IPS=$(curl -H "Authorization: Token YOUR_TOKEN" \
https://netbox.example.com/api/dcim/devices/ | \
jq -r '.results[].primary_ip.address' | \
cut -d'/' -f1)
# 2. Convert to JSON array
SUBNETS=$(echo "$DEVICE_IPS" | jq -R -s -c 'split("\n")[:-1]')
# 3. Start scan with those IPs
curl -X POST http://localhost:8000/v1/scan/from-subnets \
-H "Content-Type: application/json" \
-d "{
\"job_id\": \"netbox-scan\",
\"subnets\": $SUBNETS,
\"ports\": [22, 443],
\"concurrency\": 200
}"
# 4. Continue with fingerprinting
curl -X POST http://localhost:8000/v1/fingerprint \
-H "Content-Type: application/json" \
-d '{"job_id": "netbox-scan"}'
# 5. Collect configs
curl -X POST http://localhost:8000/v1/state/collect \
-H "Content-Type: application/json" \
-d '{
"job_id": "netbox-scan",
"credentials": {
"username": "admin",
"password": "your_password",
"platform": "cisco_ios"
}
}'
# 6. Generate topology
curl -X POST http://localhost:8000/v1/batfish/build \
-H "Content-Type: application/json" \
-d '{"job_id": "netbox-scan"}'
curl -X POST http://localhost:8000/v1/batfish/load \
-H "Content-Type: application/json" \
-d '{"job_id": "netbox-scan"}'
curl -X GET "http://localhost:8000/v1/batfish/topology/html?job_id=netbox-scan" \
-o topology.html示例:使用带有IP地址的CSV文件
# 1. Convert CSV to subnet list
# Assuming devices.csv has a column "ip_address"
SUBNETS=$(tail -n +2 devices.csv | cut -d',' -f1 | jq -R -s -c 'split("\n")[:-1]')
# 2. Start scan
curl -X POST http://localhost:8000/v1/scan/from-subnets \
-H "Content-Type: application/json" \
-d "{
\"job_id\": \"csv-scan\",
\"subnets\": $SUBNETS,
\"ports\": [22, 443]
}"AI代理实例与真相来源
import mcp
import requests
# Connect to MCP server
client = mcp.Client("http://localhost:8080/mcp")
# 1. Retrieve device IPs from NetBox
netbox_response = requests.get(
"https://netbox.example.com/api/dcim/devices/",
headers={"Authorization": "Token YOUR_TOKEN"}
)
device_ips = [d["primary_ip"]["address"].split("/")[0]
for d in netbox_response.json()["results"]
if d.get("primary_ip")]
# 2. Scan the devices from NetBox
result = client.call_tool("scan_from_subnets", {
"job_id": "netbox-discovery",
"subnets": device_ips,
"ports": [22, 443]
})
# 3. Continue with fingerprinting and config collection
client.call_tool("fingerprint_devices", {"job_id": "netbox-discovery"})
client.call_tool("collect_device_configs", {
"job_id": "netbox-discovery",
"credentials": {
"username": "admin",
"password": "password",
"platform": "cisco_ios"
}
})
# 4. Generate topology
client.call_tool("build_batfish_snapshot", {"job_id": "netbox-discovery"})
client.call_tool("load_batfish_snapshot", {"job_id": "netbox-discovery"})
topology = client.call_tool("generate_topology_visualization", {"job_id": "netbox-discovery"})
print(f"Topology visualization saved to: {topology['path']}")在以下情况下,这种方法是理想的:
- 您已经在另一个系统中维护了设备清单
- 你想验证你的真实数据来源
- 您只需要发现特定的设备,而不是整个网络
- 您希望避免基于CDP/LDP的发现
______________________________________________________________________
与AI代理(MCP)一起使用
MCP接口提供了AI代理可以用来自主发现和分析网络的工具。
MCP工作流示例
以下是AI代理如何与MCP服务器交互:
import mcp
# Connect to MCP server
client = mcp.Client("http://localhost:8080/mcp")
# Step 1: Validate credentials first
validation = client.call_tool("validate_device_credentials", {
"seed_host": "192.168.1.1",
"username": "admin",
"password": "cisco123",
"platform": "cisco_ios"
})
if not validation["valid"]:
print(f"Invalid credentials: {validation['error']}")
print(f"Suggestion: {validation['suggestion']}")
exit(1)
print("Credentials validated successfully!")
# Step 2: Check system health
health = client.call_tool("check_system_health", {})
if not health["ready_for_scan"]:
print(f"System not ready: {health['issues']}")
exit(1)
# Step 3: Seed from device
result = client.call_tool("seed_device", {
"seed_host": "192.168.1.1",
"credentials": {
"username": "admin",
"password": "cisco123",
"platform": "cisco_ios"
},
"methods": ["interfaces", "routing", "arp", "cdp"]
})
job_id = result["job_id"]
# Step 4: Scan targets
client.call_tool("scan_targets", {
"job_id": job_id,
"ports": [22, 443]
})
# Step 5: Get job statistics
stats = client.call_tool("get_job_stats", {
"job_id": job_id
})
print(f"Found {stats['results']['scanning']['reachable_hosts']} devices")
# Step 6: Fingerprint devices
client.call_tool("fingerprint_devices", {
"job_id": job_id
})
# Step 7: Collect configs
result = client.call_tool("collect_device_configs", {
"job_id": job_id,
"credentials": {
"username": "admin",
"password": "cisco123",
"platform": "cisco_ios"
}
})
# Step 8: Generate topology
client.call_tool("build_batfish_snapshot", {"job_id": job_id})
client.call_tool("load_batfish_snapshot", {"job_id": job_id})
viz = client.call_tool("generate_topology_visualization", {"job_id": job_id})
print(f"Topology saved to: {viz['path']}")
# Step 9: Get final statistics
final_stats = client.call_tool("get_job_stats", {"job_id": job_id})
print(f"Discovery complete!")
print(f"- Devices discovered: {final_stats['results']['scanning']['reachable_hosts']}")
print(f"- Vendors identified: {final_stats['results']['vendors']}")
print(f"- Configs collected: {final_stats['results']['config_collection']['configs_collected']}")AI代理最佳实践
1.始终先验证凭据
在开始昂贵的发现操作之前,请验证凭据:
# GOOD: Validate first (10 seconds)
validation = client.call_tool("validate_device_credentials", {...})
if validation["valid"]:
# Proceed with discovery
# BAD: Skip validation, waste 30 minutes on wrong credentials
client.call_tool("seed_device", {...}) # Fails after 30 min2.大扫描前检查系统健康状况
health = client.call_tool("check_system_health", {})
if health["cpu"]["usage_percent"] > 80:
print("System busy, waiting...")
time.sleep(60)3.恢复失败的作业
# Check for failed jobs
resumable = client.call_tool("list_resumable_jobs", {})
if resumable["count"] > 0:
# Offer to resume
client.call_tool("resume_failed_job", {
"job_id": resumable["resumable_jobs"][0]["job_id"],
"username": "admin",
"password": "cisco123"
})4.使用作业统计进行报告
stats = client.call_tool("get_job_stats", {"job_id": job_id})
# Generate user-friendly report
print(f"""
Network Discovery Complete:
- Devices discovered: {stats['results']['scanning']['reachable_hosts']}
- Identification rate: {stats['results']['fingerprinting']['identification_rate'] * 100}%
- Vendor breakdown:
- Cisco: {stats['results']['vendors'].get('cisco', 0)}
- Juniper: {stats['results']['vendors'].get('juniper', 0)}
- Arista: {stats['results']['vendors'].get('arista', 0)}
- Configs collected: {stats['results']['config_collection']['configs_collected']}
""")______________________________________________________________________
GitHub操作集成
该存储库包括从GitHub Actions运行网络发现的工作流。
设置
- 将您的设备凭据添加为GitHub Secrets:
- 前往“设置”>“秘密和变量”>“操作” - 添加 DEVICE_USERNAME - 添加 DEVICE_PASSWORD
- 使用工作流:
创建 .github/workflows/discover-network.yml:
name: Discover Network
on:
workflow_dispatch:
inputs:
seed_host:
description: "Seed device IP or hostname"
required: true
default: "192.168.1.1"
platform:
description: "Device platform"
required: true
default: "cisco_ios"
type: choice
options:
- cisco_ios
- cisco_nxos
- juniper_junos
- arista_eos
jobs:
discover:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Start containers
run: docker compose up -d
- name: Wait for service
run: |
timeout 60 bash -c 'until curl -s http://localhost:8000/health; do sleep 2; done'
- name: Validate credentials
run: |
curl -X POST http://localhost:8000/v1/credentials/validate \
-H "Content-Type: application/json" \
-d '{
"seed_host": "${{ github.event.inputs.seed_host }}",
"username": "${{ secrets.DEVICE_USERNAME }}",
"password": "${{ secrets.DEVICE_PASSWORD }}",
"platform": "${{ github.event.inputs.platform }}"
}'
- name: Run discovery
run: |
JOB_ID=$(curl -X POST http://localhost:8000/v1/seed \
-H "Content-Type: application/json" \
-d '{
"seed_host": "${{ github.event.inputs.seed_host }}",
"credentials": {
"username": "${{ secrets.DEVICE_USERNAME }}",
"password": "${{ secrets.DEVICE_PASSWORD }}",
"platform": "${{ github.event.inputs.platform }}"
},
"methods": ["interfaces", "routing", "arp", "cdp"]
}' | jq -r '.job_id')
echo "JOB_ID=$JOB_ID" >> $GITHUB_ENV
# Scan
curl -X POST http://localhost:8000/v1/scan \
-H "Content-Type: application/json" \
-d "{\"job_id\": \"$JOB_ID\", \"ports\": [22, 443]}"
# Fingerprint
curl -X POST http://localhost:8000/v1/fingerprint \
-H "Content-Type: application/json" \
-d "{\"job_id\": \"$JOB_ID\"}"
# Collect configs
curl -X POST http://localhost:8000/v1/state/collect \
-H "Content-Type: application/json" \
-d "{
\"job_id\": \"$JOB_ID\",
\"credentials\": {
\"username\": \"${{ secrets.DEVICE_USERNAME }}\",
\"password\": \"${{ secrets.DEVICE_PASSWORD }}\",
\"platform\": \"${{ github.event.inputs.platform }}\"
}
}"
# Generate topology
curl -X POST http://localhost:8000/v1/batfish/build \
-H "Content-Type: application/json" \
-d "{\"job_id\": \"$JOB_ID\"}"
curl -X POST http://localhost:8000/v1/batfish/load \
-H "Content-Type: application/json" \
-d "{\"job_id\": \"$JOB_ID\"}"
curl -X GET "http://localhost:8000/v1/batfish/topology/html?job_id=$JOB_ID" \
-o topology.html
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: network-discovery-results
path: |
topology.html
/tmp/network_discovery_artifacts/${{ env.JOB_ID }}/运行工作流
- 转到GitHub中的“操作”选项卡
- 选择“发现网络”
- 点击“运行工作流”
- 输入种子设备IP和平台
- 查看工作流工件中的结果
______________________________________________________________________
api参考
核心发现端点
| 方法 | 端点 | 描述 |
|---|---|---|
| 职位 | /v1/seed | 从设备启动seeder,创建targets.json |
| 职位 | /v1/scan | 扫描现有作业中的目标 |
| 职位 | /v1/scan/from-subnets | 直接扫描特定子网 |
| 职位 | /v1/scan/add-subnets | 向现有作业添加子网 |
| 职位 | /v1/fingerprint | 指纹识别设备 |
| 职位 | /v1/state/collect | 收集设备配置 |
| 职位 | /v1/state/update/{hostname} | 重新收集单个设备配置 |
凭证管理端点
| 方法 | 端点 | 描述 |
|---|---|---|
| 职位 | /v1/credentials/validate | 在发现之前验证凭据 |
| 职位 | /v1/credentials/validate/batch | 针对多个设备进行验证 |
作业管理端点
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /v1/status/{job_id} | 获取作业状态和进度 |
| 得到 | /v1/jobs/resumable | 列出可以恢复的作业 |
| 职位 | /v1/jobs/resume | 恢复失败的作业 |
蝙蝠鱼终点
| 方法 | 端点 | 描述 |
|---|---|---|
| 职位 | /v1/batfish/build | 从配置构建蝙蝠鱼快照 |
| 职位 | /v1/batfish/load | 将快照加载到Batfish中 |
| 得到 | /v1/batfish/topology | 获取JSON格式的拓扑 |
| 得到 | /v1/batfish/topology/html | 生成交互式HTML可视化 |
| 得到 | /v1/batfish/networks | 列出所有网络 |
| 得到 | /v1/batfish/networks/{name}/snapshots | 列出网络快照 |
| 职位 | /v1/batfish/networks/{name}/snapshot/{snapshot} | 设置当前快照 |
数据检索端点
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /v1/scan/{job_id} | 获取扫描结果 |
| 得到 | /v1/scan/{job_id}/reachable | 仅获取可访问的主机 |
| 得到 | /v1/fingerprint/{job_id} | 获取指纹识别结果 |
| 得到 | /v1/state/{hostname} | 获取设备配置 |
| 得到 | /v1/artifacts/{job_id}/{filename} | 获取任何工件文件 |
系统端点
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /health | 基本健康检查 |
| 得到 | /ready | 准备状态检查与验证 |
| 得到 | /docs | 交互式API文档 |
______________________________________________________________________
MCP工具参考
播种机工具
seed_设备
- 从种子设备启动网络发现
- 参数:seed_host、凭据、方法、job_id
- 返回:job_id、状态、targets_count
get_targets
- 检索从种子设备收集的目标
- 参数:job_id
- 返回:具有IP和子网的目标数组
扫描工具
扫描目标
- 扫描目标以查找打开的管理端口
- 参数:job_id、端口、并发
- 返回:hosts_scanned,hosts_rea可达
scan_from_subnets
- 直接扫描特定子网(无需种子)
- 参数:job_id、子网、端口、并发
- 返回:hosts_scanned,hosts_rea可达
获取可访问的帖子
- 从扫描结果中仅获取可访问的主机
- 参数:job_id
- 返回:可达主机数组
指纹识别工具
指纹设备
- 确定设备供应商和型号
- 参数:job_id、snmp_community(可选)
- 返回:主机_指纹识别,标识_计数
get_fingerprint_results
- 获取指纹识别结果
- 参数:job_id
- 返回:供应商提供的详细指纹数据
配置收集器工具
collect_device_config
- 并行收集设备配置
- 参数:job_id、凭据、并发性
- 返回:设备计数、成功计数、失败计数
get_device_config
- 获取特定设备的配置
- 参数:job_id,主机名
- 返回:设备配置JSON
蝙蝠鱼工具
build_batfish_snapshot
- 根据收集到的配置构建蝙蝠鱼快照
- 参数:job_id
- 返回:snapshot_dir、device_count
load_batfish_snapshot
- 将快照加载到Batfish中进行分析
- 参数:job_id
- 返回:网络名称、快照名称
get_topology
- 获取JSON格式的网络拓扑
- 参数:job_id或网络名称+快照名称
- 返回:具有节点和边的拓扑图
生成拓扑可视化
- 生成交互式HTML可视化
- 参数:job_id或网络名称+快照名称
- 返回:HTML文件的路径
凭证验证工具
validate_device_credentials
- 快速证书测试(5-15秒)
- 参数:seed_host、用户名、密码、平台
- 返回:有效、latency_ms、供应商、platform_correct、错误、建议
- 在开始昂贵的查找操作之前使用此选项
validate_credentials_multiple
- 并行测试多个设备的凭据
- 参数:设备数组、用户名、密码、并发性
- 返回:总设备数、有效计数、无效计数、成功率、每台设备结果
- 可用于跨不同设备类型测试凭据
工作简历工具
求职失败
- 在不重新完成已完成工作的情况下恢复失败的工作
- 参数:job_id、阶段(可选)、凭据
- 返回:resumed_rom、phases_executed、summary
- 对于大型网络至关重要-在部分故障时节省数小时
list_resumable_jobs
- 获取可以恢复的作业列表
- 参数:无
- 返回:resumable_jobs数组,包含failed_phases和completed_phase
- 有助于主动提出恢复失败的工作
监视工具
检查系统健康
- 开始扫描前检查系统资源
- 参数:无
- 返回:CPU、内存、磁盘使用率、ready_for_scan状态
- 在大型扫描之前使用,以确保系统容量
get_job_stats
- 获取作业的详细统计数据
- 参数:job_id
- 返回:模块状态、扫描结果、供应商细分、时间
- 用于进度监控和报告
get_recent_job_history
- 分析最近的作业执行情况
- 参数:小时(默认:24),限制(默认:50)
- 返回:success_rate、failed_jobs、健康评估
- 用于识别趋势和重复出现的问题
get_system_推荐
- 获取智能建议和警告
- 参数:无
- 返回:警告、建议、quick_actions
- 用于主动问题检测
工件工具
获取广告内容
- 从作业目录检索任何工件文件
- 参数:job_id,文件名
- 返回:文件内容(文本或base64编码)
- 支持HTML、JSON、文本和二进制文件
______________________________________________________________________
配置
环境变量
核心设置
ARTIFACT_DIR:作业工件目录(默认值:/tmp/network_discovery_artifacts)DEFAULT_PORTS:要扫描的逗号分隔端口(默认值:22,443)DEFAULT_CONCURRENCY:并联操作限制(默认值:200)CONNECT_TIMEOUT:连接超时(秒)(默认值:1.5)LOG_LEVEL:记录详细程度(默认值:info)
蝙蝠鱼设置
BATFISH_HOST:蝙蝠鱼服务器主机名(默认值:batfish)BATFISH_PORT:Batfish服务器端口(默认值:9996)
服务器设置
HOST:服务器绑定地址(默认值:0.0.0.0)PORT:服务器端口(默认:REST:8000,MCP:8080)
MCP设置
ENABLE_MCP:启用MCP模式(默认:false)TRANSPORT:运输类型http或https(默认值:http)BASE_PATH:代理部署的URL基本路径(默认值:"")
Docker编写配置
该服务附带了两个Docker Compose文件:
docker-compose.yml (REST API模式)
services:
network-discovery:
environment:
- ARTIFACT_DIR=/artifacts
- DEFAULT_PORTS=22,443
- DEFAULT_CONCURRENCY=200
- BATFISH_HOST=batfish
ports:
- "8000:8000"
volumes:
- ./artifacts:/artifactsdocker-compose.mcp.yml (MCP模式)
services:
network-discovery-mcp:
environment:
- ENABLE_MCP=true
- TRANSPORT=http
- PORT=8080
- ARTIFACT_DIR=/artifacts
- BATFISH_HOST=batfish
ports:
- "8080:8080"
volumes:
- ./artifacts:/artifacts您可以自定义这些文件或覆盖值:
# Override concurrency
DEFAULT_CONCURRENCY=400 docker compose up -d
# Use custom artifact directory
ARTIFACT_DIR=/var/network-discovery docker compose up -d______________________________________________________________________
建筑
系统组件
网络发现MCP由六个主要模块组成:
- 播种机:连接到种子设备并发现网络拓扑
- 收集接口信息 - 检索路由表 - 收集ARP条目 - 通过CDP/LDP发现邻居 - 输出: targets.json, device_states/{host}.json
- 扫描仪:探测器发现了可达性目标
- 具有可配置并发性的并行端口扫描 - 测试管理端口(SSH、HTTPS等) - 输出: ip_scan.json, reachable.json
- 指纹识别器:确定设备供应商和型号
- 横幅分析 - SNMP探测(可选) - 模式匹配 - 输出: fingerprints.json
- 配置收集器:检索设备配置
- 多供应商支持(思科、瞻博网络、Arista等) - 具有重试逻辑的并行收集 - 凭证验证 - 输出: state/{hostname}.json
- 蝙蝠鱼装载机:准备网络进行分析
- 将配置转换为蝙蝠鱼格式 - 构建网络快照 - 装载到Batfish中进行分析 - 输出: batfish_snapshot/configs/{hostname}.cfg
- 拓扑可视化工具:生成交互式可视化
- 查询Batfish的拓扑数据 - 生成D3.js力定向图 - 输出: topology.html, topology.json
数据流
[Seed Device]
↓
[Seeder] → targets.json
↓
[Scanner] → ip_scan.json, reachable.json
↓
[Fingerprinter] → fingerprints.json
↓
[Config Collector] → state/*.json
↓
[Batfish Loader] → batfish_snapshot/configs/*.cfg
↓
[Topology Visualizer] → topology.html目录结构
network-discovery-mcp/
├── network_discovery/
│ ├── __main__.py # Entry point (REST API or MCP mode)
│ ├── api.py # FastAPI REST endpoints
│ ├── mcp_server.py # MCP tools implementation
│ ├── seeder.py # Network discovery seeding
│ ├── scanner.py # Port scanning
│ ├── fingerprinter.py # Device identification
│ ├── config_collector.py # Configuration collection
│ ├── batfish_loader.py # Batfish integration
│ ├── topology_visualizer.py # Visualization generation
│ ├── credential_validator.py # Credential testing
│ ├── job_resume.py # Job resumption logic
│ ├── metrics.py # System monitoring
│ ├── artifacts.py # File I/O operations
│ ├── config.py # Configuration management
│ └── workers.py # Async task coordination
├── tests/ # Unit tests
├── Dockerfile # Container image definition
├── docker-compose.yml # REST API deployment
├── docker-compose.mcp.yml # MCP deployment
└── requirements.txt # Python dependencies工件存储结构
每个发现作业都会创建一个目录结构:
{ARTIFACT_DIR}/{job_id}/
├── targets.json # Discovered network targets
├── device_states/
│ └── {hostname}.json # Per-device state from seeder
├── ip_scan.json # Full scan results
├── reachable.json # Filtered reachable hosts
├── fingerprints.json # Device identification results
├── state/
│ ├── {hostname1}.json # Device configurations
│ ├── {hostname2}.json
│ └── ...
├── batfish_snapshot/
│ └── configs/
│ ├── {hostname1}.cfg # Batfish-format configs
│ ├── {hostname2}.cfg
│ └── ...
├── topology.json # Topology graph data
├── topology.html # Interactive visualization
├── status.json # Job status tracking
└── error.json # Error details (if any)所有文件写入都是原子性的(写入 .tmp,然后重命名)以防止损坏。
______________________________________________________________________
故障排除
服务无法启动
问题:容器无法启动
docker compose up -d
# Error: port already in use解决方案:检查端口冲突
# Check what's using port 8000
lsof -i :8000
# Use different port
PORT=8001 docker compose up -d______________________________________________________________________
身份验证失败
问题:所有设备身份验证失败
Error: Authentication failed for all devices解决方案:首先验证凭据
# Test credentials before discovery
curl -X POST http://localhost:8000/v1/credentials/validate \
-H "Content-Type: application/json" \
-d '{
"seed_host": "192.168.1.1",
"username": "admin",
"password": "your_password",
"platform": "cisco_ios"
}'
# Check response for specific error
{
"valid": false,
"error": "Authentication failed - invalid username or password",
"suggestion": "Verify credentials for user 'admin' on this device"
}______________________________________________________________________
配置收集期间作业失败
问题:收集某些配置后作业失败
Status: 200/450 configs collected, then failure解决方案:恢复作业,而不是重新启动
# List resumable jobs
curl http://localhost:8000/v1/jobs/resumable
# Resume the failed job
curl -X POST http://localhost:8000/v1/jobs/resume \
-H "Content-Type: application/json" \
-d '{
"job_id": "net-disc-123",
"credentials": {"username": "admin", "password": "pass"}
}'
# This will retry only the 250 failed devices______________________________________________________________________
缓慢发现
问题:发现耗时太长
解决方案:检查系统资源
# Check system health
curl http://localhost:8000/v1/health
# Check specific job statistics
curl http://localhost:8000/v1/status/{job_id}
# Reduce concurrency if CPU high
curl -X POST http://localhost:8000/v1/scan \
-H "Content-Type: application/json" \
-d '{"job_id": "...", "concurrency": 50}'______________________________________________________________________
蝙蝠鱼连接问题
问题:拓扑生成失败
Error: Cannot connect to Batfish解决方案:验证蝙蝠鱼集装箱
# Check Batfish is running
docker compose ps
# Check Batfish logs
docker compose logs batfish
# Restart if needed
docker compose restart batfish
# Wait for Batfish to initialize
sleep 30______________________________________________________________________
大型网络超时
问题:大型子网超时
解决方案:增加超时或缩小范围
# Increase timeout
CONNECT_TIMEOUT=5.0 docker compose up -d
# Or scan in smaller batches
curl -X POST http://localhost:8000/v1/scan/from-subnets \
-H "Content-Type: application/json" \
-d '{
"job_id": "batch1",
"subnets": ["192.168.1.0/24"],
"concurrency": 100
}'______________________________________________________________________
查看日志
对于调试,请检查容器日志:
# REST API mode
docker compose logs -f network-discovery
# MCP mode
docker compose -f docker-compose.mcp.yml logs -f network-discovery-mcp
# Just errors
docker compose logs network-discovery | grep ERROR
# Specific time range
docker compose logs --since 30m network-discovery______________________________________________________________________
获得帮助
如果您遇到此处未涵盖的问题:
- 检查日志:
docker compose logs network-discovery - 查看作业状态:
curl http://localhost:8000/v1/status/{job_id} - 检查系统建议:使用
get_system_recommendationsMCP工具 - 查看中的工件文件
{ARTIFACT_DIR}/{job_id}/
______________________________________________________________________
其他资源
- API文档: http://localhost:8000/docs(交互式Swagger用户界面)
- GitHub发布: https://github.com/username/network-discovery-mcp/releases(版本历史和变更日志)
______________________________________________________________________
许可证
此项目根据LICENSE文件中指定的条款获得许可。
