Netdryrun について
Netdryrunは、ネットワークエンジニアやCIを使うチーム向けに、仮想containerlabトポロジーで設定変更をデプロイ前にテストします。BGPセッション、経路、プレフィックス、到達性など実際の制御プレーンの挙動を検証し、本番環境に触れずに証拠を出力します。
主な機能
- 01仮想ネットワークラボで変更をテスト
- 02BGP、経路、プレフィックス、pingを検査
- 03正常時の挙動をベースラインとして記録
- 04GitHub Actionsで検査を実行
- 05Markdown、JUnit、JSONレポートを出力
活用シーン
- 01プルリクエストでネットワーク変更を検証
- 02本番投入前に経路リークを検出
- 03ラボを記録済みベースラインと比較
- 04エージェントに変更案を検証させる
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 は現実的な BGP 変更 30 件中 24 件を正しく判定しました(ping のみのチェックは 30 件中 20 件、全セッション確立チェックは 30 件中 15 件)。より難しい v2 では 18 件中 16 件でした(それぞれ 18 件中 9 件、7 件)。どちらも、メンテナーが 1 つの FRR トポロジーで作成した小規模なベンチマークです。期待される判定は実行前にコミットされており、どちらも Netdryrun 0.2.0 で実行しました。これらは手法を比較するものであり、本番環境における信頼性の推定値ではありません。フィードバックや問題の報告を歓迎します。
理由
- 構文ではなく、動作をテストします。 リンターや設定差分では、BGP が確立するか、プレフィックスがリークするかはわかりません。実際のコントロールプレーンなら検証できます。
- CI 向けに構築されています。 GitHub Actions を 1 つ使うだけで、成功/失敗の終了コード、ジョブ内の 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 の隣接ルーターに本来送信すべきでないルートをアナウンスさせたりして、max-prefix 制限やインポートフィルターが実際に機能していることを確認できます。
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)には、nodes: {sonic1: {setup: [...]}} のように setup コマンドを指定します。
| チェック | FRR | SR Linux | Arista EOS (cEOS) | SONiC (VS) |
|---|---|---|---|---|
bgp_session | ✅ | ✅ | ✅ | ✅ |
bgp_prefixes(accepted = received からポリシーで拒否された数を引いたもの) | ✅ | ✅ | ✅ | ✅ |
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 レポートをアーティファクトとしてアップロードします。チェックが 1 つでも失敗すると、ジョブは失敗します。出力:status、passed、failed、inconclusive-reason。
AI エージェント向け(MCP)
AI はネットワーク変更を提案できます。Netdryrun が結果を検証します。 エージェントの方は AGENTS.md をお読みください。
AI エージェントがネットワークを変更し始めています。Netdryrun は安全確認の仕組みを提供します。エージェントが実際のラボで変更をドライランし、すべてのチェックに合格した場合にのみ先へ進めるようにする MCP サーバーです。
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 によって拒否されます。2 行の修正を加えると、同じチェックに合格します。(2 つの試行をスクリプトで再現します。CI で実行されます。)

安全性モデル:
- サーバーが本番環境に触れることはありません。どこにも設定をプッシュするツールはなく、ラボの構築とテストのみを行います。
- ツールの結果に含まれるのは正規化されたチェック結果であり、デバイスの生の出力ではありません。そのため、ラボ内のテキスト(バナーやルートの説明)がエージェントに指示を注入することはありません。生の証跡は JSON レポートファイルに出力されます。
- ラボはコードです。containerlab は特権コンテナを実行します。サーバーは、信頼できるトポロジーのみを、Docker の実行を許可できるマシンで指定してください。
比較
Netdryrun はこれらのツールを補完するものであり、置き換えるものではありません。
| ツール | 最も得意なこと | Netdryrun の役割 |
|---|---|---|
| Batfish | 何も起動せずに設定を静的解析します。高速で幅広く対応します | Netdryrun は実際のコントロールプレーンを実行するため、収束、タイマー、実際に RIB に反映される内容など、実行時の動作を確認できます |
| pyATS / Genie | Cisco の高度なパーサーを備えた、フル機能のテストフレームワークです | Netdryrun は簡潔な宣言型 YAML ファイルと 1 つの GitHub Action で利用でき、テストコードを書く必要はありません |
| containerlab | ラボを実行します | Netdryrun は containerlab を操作するものであり、置き換えるものではありません |
Netdryrun が追加する機能:肯定チェックは収束を待ち、否定チェックは収束後にのみ実行され、条件が維持されている必要があります。受信したものの選択されていないルートも存在するものとして扱い、実行ごとに合否結果と証跡ファイルを 1 つずつ生成します。
正直な制限事項
- ラボのルーターは本番環境のルーターではありません。FRR、SR Linux、SONiC VS、Arista cEOS で合格しても、プロトコルのロジックとポリシーの意図を裏付ける強い証拠にはなりますが、ハードウェア、規模、バージョン固有の動作を証明するものではありません。Arista では、実際のベンダーコードをテストするために、ご自身のライセンス済み cEOS イメージをご用意ください。
- チェック対象は IPv4/IPv6 ユニキャスト BGP(セッション、プレフィックス数、ベストパス属性)、ルート、ping です。障害シナリオには、リンクダウン、ノード分離、ルート注入(FRR のみ)が含まれます。今後、OSPF/IS-IS 隣接関係やパス/traceroute などのチェックを追加する予定です。
結果の確認方法と、(主に AI エージェントが)コードを記述する方法については、構築方法をご覧ください。
ロードマップ
- 障害の再現: ルートリークや大量の経路取り消しなど、実際に発生した有名な障害を、実行可能なラボとテストパックとして再構築します。あなたの変更によって障害が起きていたでしょうか?
- さらに多くの障害シナリオ、チェックの種類(OSPF/IS-IS、traceroute)、ドライバー
- 差分付きの PR コメントと、変更チケット用の署名済み証跡
ライセンス
Apache-2.0。「Netdryrun」と Netdryrun のロゴは商標です。詳細は TRADEMARKS.md をご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。