关于 Netdryrun
Netdryrun 面向网络工程师及使用 CI 的团队,可在虚拟 containerlab 拓扑中测试配置变更。它检查真实控制平面的行为,包括 BGP 会话、路由、前缀和可达性,并生成测试证据,不会触碰生产环境。
主要功能
- 01在虚拟网络实验室测试变更
- 02检查 BGP、路由、前缀和 ping
- 03记录已知正常状态作为基线
- 04在 GitHub Actions 中运行检查
- 05导出 Markdown、JUnit 和 JSON 报告
适用场景
- 01在拉取请求中验证网络变更
- 02在上线前发现路由泄漏
- 03将实验室与已记录基线比较
- 04让 Agent 验证拟议变更
MCP 相关
MCP 服务提供部署和测试实验室、对运行中的实验室执行检查、验证配置及列出检查类型的工具。它会返回判定结果,不会向生产环境推送配置。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
5收录的工具列表 · 更新于 1 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| path | string | 是 | |
| keep_lab | boolean | 否 |
详细介绍
在网络变更影响生产环境之前进行测试。
Netdryrun™ 会将你的网络拓扑启动为真实的虚拟网络(containerlab),应用你的配置,并检查网络的实际行为:BGP 会话、前缀数量、路由和可达性。它能在路由泄漏等错误影响生产环境之前将其捕获,并留下值得审查者信赖的证据。

$ netdryrun run examples/frr-bgp-broken
Deploying lab ndr-frr-broken (3 nodes)...
[PASS] r1: BGP session to 10.0.12.2 is established -- state is established (6.3s)
[PASS] r1: ping 192.168.3.1 from 192.168.1.1 expects success -- 3/3 replies (2.3s)
... (3 more passing checks trimmed)
[FAIL] r1: route 0.0.0.0/0 via bgp is absent -- unexpectedly present via bgp (not selected) (0.1s)
FAILED: 5 passed, 1 failed (6 checks)
这次运行捕获了一条已接收但未被选中的泄漏默认路由。ping 测试或配置检查器都无法发现它。
状态:**v0.3.0,早期版本。**目前可在 Linux 和 WSL2 上使用 FRR、Nokia SR Linux、SONiC(docker-sonic-vs)和 Arista EOS(cEOS,需自备镜像)。在判定语料库中,Netdryrun 对 24/30 项真实 BGP 变更做出了正确判断(仅 ping 检查为 20/30,全部会话均已建立检查为 15/30);在难度更高的 v2 中,对 16/18 项做出了正确判断(两种检查方法分别为 9/18 和 7/18)。这两项都是维护者基于单个 FRR 拓扑编写的小型基准测试;预期判定结果在任何运行之前就已提交,并且两项测试均使用 Netdryrun 0.2.0 运行:它们用于比较方法,并不代表生产环境可靠性估算。非常欢迎反馈和问题报告。
为什么选择它
- **测试行为,而非语法。**检查器和配置差异无法判断 BGP 是否会建立连接,或前缀是否会泄漏。真实的控制平面可以。
- **专为 CI 打造。**只需一个 GitHub Action,即可获得通过/失败退出码、作业中的 Markdown 摘要、JUnit XML,以及包含每条命令和原始输出的 JSON 证据文件。
- **不会谎报收敛状态。**正向检查会等待网络收敛。负向检查(“此路由必须不存在”)只会在网络收敛后运行,并且必须在一段时间内持续成立,因此不会仅仅因为 BGP 尚未建立就通过。
快速入门
在浏览器中试用(无需安装)
该 codespace 已预装 Docker、containerlab 和 Netdryrun。终端显示 Ready 后,运行:
bash examples/agent-demo/demo.sh
有路由泄漏的变更会被拒绝,修复后则会通过所有检查。它会使用你 GitHub 账户的免费 Codespaces 时长(2 核机器)。详情。
在自己的机器上
要求:Linux 或 WSL2、Docker、containerlab、Python 3.10+。
pip install netdryrun
git clone https://github.com/netdryrun/netdryrun && cd netdryrun
netdryrun run examples/frr-bgp # 3 FRR routers, should pass
netdryrun run examples/srl-frr # SR Linux + FRR, should pass
netdryrun run examples/frr-bgp-broken # a bad change, should fail
在自己的 containerlab 拓扑上运行(3 条命令)
netdryrun record my-lab/topology.clab.yml --deploy # snapshot today's behavior into my-lab/netdryrun.yml
# ...edit your configs (the change you want to test)...
netdryrun run my-lab # did anything break?
record 会记录所有已建立的 BGP 会话、前缀数量和 BGP 路由,作为基线。审查并提交基线,之后的每次变更都会在本地或 CI 中以此为依据进行测试。
netdryrun.yml
lab: topology.clab.yml # your containerlab topology
timeout: 90 # seconds a positive check may wait for convergence
checks:
- type: bgp_session # session reaches a state (default: established)
node: r1
neighbor: 10.0.12.2
- type: bgp_prefixes # accepted prefix count within a range
node: r1
neighbor: 10.0.12.2
min: 1
max: 10
- type: route # route present (or absent), optionally via a protocol
node: r1
prefix: 192.168.3.0/24
protocol: bgp
- type: ping # reachability, optionally from a source address
node: r1
source: 192.168.1.1
target: 192.168.3.1
- type: route # negative check: must stay absent after convergence
node: r1
prefix: 0.0.0.0/0
protocol: bgp
present: false
故障场景会破坏某些东西,检查网络是否仍能正常运行,然后恢复原状。它们可以关闭链路,也可以让 FRR 邻居通告不该通告的路由,以验证最大前缀数限制或导入过滤器是否确实有效:
scenarios:
- name: r1-r2 link fails
link_down: {node: r1, interface: eth1}
checks:
- {type: ping, node: r1, source: 192.168.1.1, target: 192.168.2.1} # rerouted via r3
- {type: bgp_session, node: r1, neighbor: 10.0.12.2, state: down}
- name: customer floods 200 prefixes
inject_routes: {node: ce1, count: 200, from: 10.100.16.0/24}
checks:
- {type: bgp_prefixes, node: up1, neighbor: 10.0.2.1, max: 51} # the limit stops the flood
每项检查也接受 name、timeout 和 vrf。Ping 接受 expect: failure 和 count。驱动程序会根据拓扑自动检测;可以通过 nodes: {r1: {driver: frr}} 覆盖。启动后配置的节点(SONiC)使用 setup 命令:nodes: {sonic1: {setup: [...]}}。
| 检查项 | FRR | SR Linux | Arista EOS (cEOS) | SONiC (VS) |
|---|---|---|---|---|
bgp_session | ✅ | ✅ | ✅ | ✅ |
bgp_prefixes(已接受 = 收到的路由减去被策略拒绝的路由) | ✅ | ✅ | ✅ | ✅ |
route 存在 / 不存在 | ✅ | ✅ | ✅ | ✅ |
bgp_route 最佳路径属性:团体属性(标准、大型、众所周知)、AS 路径(精确匹配或正则表达式)、本地优先级、MED、下一跳 | ✅ | ✅ | ✅ | ✅ |
ping 成功 / 失败 | ✅ | ✅ | ✅ | ✅ |
命令
| 命令 | 功能 |
|---|---|
netdryrun run [path] | 部署实验环境、运行检查并销毁实验环境。添加 --keep 可保留环境以进行调试 |
netdryrun check [path] | 针对已运行的实验环境执行检查 |
netdryrun validate [path] | 验证 netdryrun.yml,不运行任何内容 |
netdryrun record topology.clab.yml | 将已知正常的实验环境快照保存为 netdryrun.yml 基线,无需手动编写检查 |
报告:--json FILE(完整证据)、--markdown FILE、--junit FILE。在 GitHub Actions 下,摘要会自动附加到作业页面。退出代码:0 表示通过,1 表示检查失败,2 表示配置或实验环境错误,3 表示无法确定(实验环境始终未达到可测试状态,因此运行结果无法说明此次变更的情况)。
GitHub Action
name: Network dry run
on: pull_request
jobs:
dryrun:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: netdryrun/[email protected]
with:
path: network/ # folder containing netdryrun.yml
该 Action 会安装 containerlab、运行检查、将 JSON 和 JUnit 报告上传为构件,并在任何检查失败时使作业失败。输出:status、passed、failed、inconclusive-reason。
面向 AI Agent(MCP)
AI 可以提出网络变更。Netdryrun 会验证结果。 Agent:请阅读 AGENTS.md。
AI Agent 正开始变更网络。Netdryrun 为它们提供了一道安全关卡:一个 MCP 服务,让 Agent 在真实实验环境中试运行变更,并且仅在所有检查都通过时继续执行。
pip install netdryrun
将其添加到你的 MCP 客户端(例如 Claude Code):
claude mcp add netdryrun -- netdryrun mcp
工具:dry_run(部署、检查、销毁、给出结论)、run_checks(针对正在运行的实验环境执行)、validate、check_types。每个结果都包含独立的 verdict 字段:SAFE TO PROCEED、DO NOT APPLY THIS CHANGE,或者在实验环境始终未启动时显示 INCONCLUSIVE: the lab did not reach a testable state; ...。
演示(examples/agent-demo):工单要求让客户的新网段能够到达上游和对等节点。一个看似合理的变更通过了工单中的所有检查、会话检查和 Ping 检查,但泄漏了路由;Netdryrun 拒绝了它。两行修复通过了相同的检查。(对这两次尝试进行脚本化重放;CI 会运行它。)

安全模型:
- 服务绝不会触碰生产环境。它没有任何可向任何地方推送配置的工具;它只会构建和测试实验环境。
- 工具结果包含规范化的检查结果,而不是原始设备输出,因此实验环境中的文本(横幅、路由描述)无法向 Agent 注入指令。原始证据会写入 JSON 报告文件。
- 实验环境就是代码:containerlab 会运行特权容器。只将服务器指向你信任的拓扑,并在你愿意运行 Docker 的机器上运行。
对比
Netdryrun 与这些工具互补,不会取代它们。
| 工具 | 最擅长的事情 | Netdryrun 的定位 |
|---|---|---|
| Batfish | 对配置进行静态分析,无需启动任何设备;速度快、覆盖面广 | Netdryrun 运行真实的控制平面,因此能观察运行时行为:收敛、计时器,以及实际进入 RIB 的内容 |
| pyATS / Genie | 功能全面的测试框架,配有深入的 Cisco 解析器 | Netdryrun 只需一个简洁的声明式 YAML 文件和一个 GitHub Action,无需编写测试代码 |
| containerlab | 运行实验室 | Netdryrun 驱动 containerlab,不会取代它 |
Netdryrun 的新增能力:正向检查会等待收敛,负向检查仅在收敛后运行且必须始终成立,已接收但未被选中的路由也会计为存在,并且每次运行都会生成一个通过/失败结果和一个证据文件。
客观说明局限
- 实验室路由器并非生产路由器。在 FRR、SR Linux、SONiC VS 或 Arista cEOS 上通过测试,能有力证明协议逻辑和策略意图,但不能证明硬件、规模或特定版本下的行为。对于 Arista,请自备授权的 cEOS 镜像,以测试真实的厂商代码。
- 检查涵盖 IPv4/IPv6 单播 BGP(会话、前缀数量、最佳路径属性)、路由和 ping,以及链路断开、节点隔离和路由注入(仅限 FRR)故障场景。更多检查即将推出:OSPF/IS-IS 邻接关系、路径跟踪。
了解如何检查结果,以及由谁编写代码(主要是 AI Agent):构建方式。
路线图
- 故障重演: 将著名的真实故障(路由泄漏、大规模撤销)重建为可运行的实验室和检查包。你的更改会导致其中某次故障吗?
- 更多故障场景、更多检查类型(OSPF/IS-IS、traceroute)和驱动程序
- 在 PR 中添加差异评论,并为变更单提供签名证据
许可证
Apache-2.0。“Netdryrun”和 Netdryrun 徽标均为商标;详见 TRADEMARKS.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。