Проверяйте изменения в сети до их внедрения в production.
Netdryrun — инструмент с открытым исходным кодом (Apache-2.0), который проверяет изменения в сети в реальной лаборатории containerlab и выдает результат «пройдено/не пройдено» с подтверждающими данными. Он работает как CLI, GitHub Action и MCP-сервер для AI-агентов.
Команды разработки не выпускают код, не запустив тесты. Изменения в сети заслуживают того же подхода: примените их в реальной лаборатории, проверьте поведение сети и внедряйте только после успешной проверки. Netdryrun позволяет выполнить такую проверку одной командой, одним шагом CI или одним вызовом инструмента для AI-агента.
Уже есть лаборатория containerlab? Добавьте в нее Netdryrun за 10 минут: зафиксируйте ее штатное состояние, добавьте одно правило проверки и запускайте тесты при каждом pull request.
Netdryrun™ разворачивает топологию как настоящую виртуальную сеть (containerlab), применяет конфигурации и проверяет фактическое поведение сети: BGP-сессии, количество префиксов, маршруты и доступность. Инструмент выявляет описанные в проверках ошибки, например утечку маршрута, до того, как изменение попадет в production. При этом он сохраняет команды и исходный вывод, чтобы проверяющий мог их изучить.
$ 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 и состояния сессий в этом случае недостаточно: все сессии установлены, все адреса отвечают. (Статический анализатор, например Batfish, также выявит именно эту утечку. На странице Batfish показан другой случай: его пропускает анализатор, но выявляет лабораторная проверка.)
Статус: v0.4.0. Работает в Linux и WSL2. Поддерживает драйверы для FRR, Nokia SR Linux, SONiC (docker-sonic-vs), Arista EOS (cEOS, образ необходимо предоставить самостоятельно) и Juniper cJunosEvolved (бета-версия, образ необходимо предоставить самостоятельно). На наборе тестов v1 (30 реалистичных изменений BGP: 19 опасных и 11 безопасных) Netdryrun правильно оценил 24 из 30 случаев, проверки только с помощью ping — 20 из 30, а проверки, требующие, чтобы все сессии были установлены, — 15 из 30. Netdryrun одобрил 5 из 19 опасных изменений (проверки только с помощью ping — 10 из 19) и заблокировал 1 из 11 безопасных. В v2 (18 случаев, составленных после v1 для проверки ошибок, допущенных в v1) Netdryrun правильно оценил 16 из 17 детерминированных случаев, проверки только с помощью ping — 9 из 17, а проверки состояния всех сессий — 7 из 17. Результат 18-го случая зависит от запуска в этой лаборатории, поэтому он не включен в оценку; на странице приведены повторные запуски. Ожидаемые результаты были зафиксированы до проведения проверок на одной топологии FRR. Это сравнение методов тестирования, а не оценка надежности в production. Методика, каждый пропущенный случай и повторный запуск одной командой описаны на странице набора тестов. Данные о происхождении результатов: оба набора проверок запускались в Netdryrun 0.3.1.
Почему Netdryrun
-
Проверяет поведение, а не синтаксис. Разница между конфигурациями показывает, что изменилось, но не позволяет понять, установится ли BGP и какие маршруты в итоге получит каждый маршрутизатор. Реальная плоскость управления показывает, как ведет себя ПО маршрутизации.
-
Создан для CI. Один GitHub Action, код завершения «пройдено/не пройдено», сводка в формате Markdown в задании, JUnit XML и JSON-файл с подтверждающими данными — всеми командами и исходным выводом.
-
Ожидает сходимости по заданным правилам. Положительная проверка считается пройденной после двух успешных измерений с интервалом 3 секунды, выполненных до истечения тайм-аута. Отрицательные проверки («этот маршрут должен отсутствовать») и проверки атрибутов наилучшего маршрута ожидают, пока все настроенные BGP-сессии на узле не будут установлены, а количество префиксов не стабилизируется. Сессии, которые, согласно проверке, должны быть отключены, не учитываются. Затем выдерживается 10-секундный период стабилизации, после чего условие должно оставаться верным в течение 10 секунд. Период стабилизации и время подтверждения можно настроить. Если до истечения тайм-аута на узле по-прежнему не обнаружены соседи BGP, проверки все равно выполняются, а результат сообщает, что сходимость BGP не была подтверждена. В сценарии сбоя проверки начинаются только после того, как сбой проявится в BGP; в противном случае запуск завершается с кодом 2. Положительные проверки также должны оставаться успешными в течение заданного времени. Код завершения 0 означает, что проверки пройдены; 1 — что проверки завершились с ошибками; 2 — что тестирование не проводилось из-за проблемы с конфигурацией или лабораторией; 3 — что результат не определен. Правила основаны на измерениях; подробности см. в разделе семантика сходимости.
Быстрый старт
Попробуйте в браузере (без установки)
В Codespace уже установлены Docker, containerlab и Netdryrun. Когда в терминале появится Ready, выполните:
bash examples/agent-demo/demo.sh
Изменение, вызывающее утечку маршрута, будет отклонено, а после исправления все проверки пройдут. Для работы используются бесплатные часы Codespaces, доступные в вашей учетной записи GitHub (машина с 2 ядрами). Подробнее.
На собственном компьютере
Требования: Linux или WSL2, Docker, containerlab, Python 3.10+. В Ubuntu 24.04 и Debian 12 обычная команда pip install вне виртуального окружения запрещена из-за сообщения «externally managed environment». Используйте pipx: sudo apt install pipx && pipx ensurepath, затем откройте новый терминал. Также подойдут uv tool install netdryrun или pip install netdryrun в активированном виртуальном окружении.
pipx install netdryrun
git clone https://github.com/netdryrun/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 # re-run the checks in my-lab/netdryrun.yml
Команда record создает проверки для каждой установленной BGP-сессии, задает для каждой из них допустимый диапазон количества префиксов — от текущего значения до значения, превышающего его на 20%, но не менее 2, — запрещает получение через BGP маршрута по умолчанию или подсети канала связи и записывает до 50 маршрутов BGP для каждого узла. Сессии, отключенные на момент записи, в проверки не добавляются.
Рекомендация (0.3.3 и 0.4.0): заданный диапазон позволяет пропустить утечку одного или двух дополнительных префиксов от соседа. До выхода версии 0.4.1 используйте при записи параметр
--exact-prefixesи добавляйте проверкиpresent: falseдля префиксов, которые не должны поступать. Рекомендация. Проверьте созданные правила: удалите условия для параметров, которые могут изменяться, и добавьте отрицательные проверки, напримерpresent: false. Зафиксируйте результат в репозитории — после этого каждое последующее изменение можно будет проверять по этим правилам локально или в 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
Сценарии отказа имитируют неисправность, проверяют, что сеть продолжает работать, а затем восстанавливают исходное состояние. Они могут отключать каналы связи или, начиная с версии 0.3.1, заставлять соседа 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), предусмотрены команды setup: nodes: {sonic1: {setup: [...]}}.
| Проверка | FRR | SR Linux | Arista EOS (cEOS) | SONiC (VS) |
|---|---|---|---|---|
bgp_session | ✅ | ✅ | ✅ | ✅ |
bgp_prefixes (принятое количество = полученные префиксы минус отклонённые политикой) | ✅ | ✅ | ✅ | ✅ |
route — маршрут присутствует / отсутствует | ✅ | ✅ | ✅ | ✅ |
bgp_route — атрибуты лучшего маршрута: communities (стандартные, большие, общеизвестные), AS path (точное совпадение или регулярное выражение), local preference, MED, next hop | ✅ | ✅ | ✅ | ✅ |
ping — успешная / неуспешная проверка связи | ✅ | ✅ | ✅ | ✅ |
| Как выполняется проверка | Лабораторная среда запускается в CI при каждом push | Лабораторная среда запускается в CI при каждом push | Парсеры проверяются на выводе, полученном в работающих лабораторных средах; в CI лабораторная среда не запускается | Парсеры проверяются на выводе, полученном в работающих лабораторных средах; в CI лабораторная среда не запускается |
Команды
| Команда | Назначение |
|---|---|
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 — результат не определён (ошибка конфигурации или лабораторной среды, неисправность не проявилась либо произошла внутренняя ошибка; добавьте --debug, чтобы получить трассировку), 3 — результат неубедителен (лабораторная среда не достигла состояния, пригодного для проверки, поэтому запуск ничего не говорит об изменении), 130/143/129 — выполнение прервано сигналом SIGINT/SIGTERM/SIGHUP после очистки лабораторной среды.
GitHub Action
name: Network dry run
on: pull_request
jobs:
dryrun:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: netdryrun/Netdryrun@v0.4.0
with:
path: network/ # folder containing netdryrun.yml
Action устанавливает containerlab, выполняет проверки и загружает отчёты JSON и JUnit как артефакт. Если какая-либо проверка не пройдена, задание завершается с ошибкой. Выходные параметры: status, passed, failed, inconclusive-reason.
Для AI-агентов (MCP)
Сервер внесён в официальный реестр MCP (io.github.netdryrun/netdryrun), а также опубликован на Glama; навык агента доступен и на Smithery.
AI может предлагать изменения в сети. Netdryrun проверяет их результат. Агенты: ознакомьтесь с файлом AGENTS.md.
Агенты для программирования не ищут средства проверки самостоятельно: в нашем тестировании они не стали искать такое средство. Подключите Netdryrun к рабочему процессу агента за две минуты — как проверку pull request, правило в AGENTS.md или MCP-сервер: Добавьте его туда, где работает ваш агент.
AI-агенты начинают вносить изменения в сети. Netdryrun служит для них защитным барьером: это сервер MCP, который позволяет агенту проверить изменение в работающей лабораторной среде и продолжить работу, только если все проверки пройдены.
pipx install netdryrun # or uv tool install netdryrun
Добавьте сервер в свой MCP-клиент, например Claude Code:
claude mcp add netdryrun -- netdryrun mcp
Инструменты: dry_run (развернуть среду, выполнить проверки, удалить среду и вынести вердикт), run_checks (выполнить проверки в уже запущенной среде), record_baseline (сохранить снимок заведомо исправной среды в виде проверок), validate, check_types. Каждый результат содержит отдельное поле verdict: CHECKS PASSED (only what the checks cover), DO NOT APPLY THIS CHANGE или INCONCLUSIVE: the lab did not reach a testable state; ..., если лабораторная среда не запустилась. Вердикт CHECKS PASSED (only what the checks cover) означает лишь, что в лабораторной среде пройдены все проверки из файла, и сам по себе не подтверждает безопасность изменений. Изменение может нарушить работу того, что не проверяется, и всё равно получить такой результат: в нашей оценке AI-агентов агент добавил redistribute connected в рамках «чистого рефакторинга» и прошёл проверку, поскольку дополнительные маршруты не проверялись. Если изменение не должно менять поведение, сначала сохраните базовую конфигурацию. Начиная с версии 0.3.2 строки вердиктов зафиксированы (в версии 0.3.1 при успешной проверке выводилось SAFE TO PROCEED; ориентируйтесь на status, а не на текст). В результатах с ошибками перечисляются все непройденные проверки, причины, фрагмент данных проверки и одна команда для следующей диагностики, доступная только для чтения. Формат результата опубликован в виде JSON Schema: mcp-result-v1.json.
Демонстрация (examples/agent-demo): в задаче сказано, что новый блок адресов заказчика должен быть доступен со стороны вышестоящего узла и пира. Очевидное решение проходит все проверки задачи, включая проверку сессии и ping, но приводит к утечке маршрутов, поэтому Netdryrun его отклоняет. Исправление из двух строк проходит те же проверки. (Сценарий воспроизводит обе попытки; он запускается в CI.)
Навык агента
Файл skills/netdryrun/SKILL.md описывает правила для агента, работающего с кодом: перед применением изменений маршрутизации проверять их в dry-run, приводить вердикт, останавливаться при неубедительном результате, не создавать и не ослаблять проверки ради успешного прохождения и использовать record_baseline, если проверок нет. Установите навык из Git URL репозитория (начиная с версии 0.3.2):
git clone --depth 1 https://github.com/netdryrun/Netdryrun /tmp/netdryrun
mkdir -p ~/.claude/skills && cp -r /tmp/netdryrun/skills/netdryrun ~/.claude/skills/ # Claude Code, every project
Чтобы сделать навык доступным всем, кто работает в одном репозитории, скопируйте папку в .claude/skills/netdryrun/ и добавьте её в репозиторий. Другие клиенты, поддерживающие Agent Skills (папку с файлом SKILL.md), используют ту же папку. Для работы навыка требуется MCP-сервер, описанный выше; без него агент использует CLI.
Модель безопасности:
-
Сервер никогда не обращается к рабочей сети. У него нет инструментов для отправки конфигурации куда-либо: он только создаёт и проверяет лабораторные среды.
-
Результаты работы инструментов содержат нормализованные результаты проверок, а не полный вывод устройств. Поле
detailможет включать фрагмент текста из лабораторной среды, например баннер или описание маршрута. Начиная с версии 0.3.2 для каждой непройденной проверки также приводится короткий фрагмент данных: каждый фрагмент занимает одну строку и ограничен по длине. Ни один из них не меняет значенияstatusилиverdict. Необработанные данные сохраняются в JSON-отчёте. -
Лабораторная среда — это код: containerlab запускает контейнеры с привилегированным доступом. Указывайте серверу только те топологии, которым доверяете, и используйте его на машине, на которой вы готовы запускать Docker.
Сравнение с другими инструментами
Netdryrun дополняет эти инструменты, а не заменяет их.
| Инструмент | Для чего подходит лучше всего | В чём помогает Netdryrun |
|---|---|---|
| Batfish | Статический анализ конфигураций без запуска оборудования; быстро и с широким охватом | Netdryrun запускает реальный control plane и проверяет поведение во время работы: сходимость, фактически установленные сессии и маршруты, которые действительно попали в RIB |
| pyATS / Genie | Полноценная тестовая среда с глубокими парсерами Cisco | Netdryrun — это небольшой декларативный YAML-файл и один GitHub Action: писать тестовый код не нужно |
| containerlab | Запускает лабораторную среду | Netdryrun управляет containerlab, но не заменяет его |
Netdryrun добавляет ожидание сходимости перед положительными проверками; отрицательные проверки выполняются только после сходимости и должны оставаться истинными. Маршруты, которые получены, но не выбраны, считаются присутствующими. Каждый запуск формирует итоговый результат «пройдено/не пройдено» и файл с доказательствами.
Ограничения
-
Маршрутизаторы в лабораторной среде — не ваши производственные маршрутизаторы. Успешная проверка на FRR, SR Linux, SONiC VS или Arista cEOS — весомое подтверждение корректности логики протоколов и намерений, заложенных в политике, но не доказательство поведения оборудования, работы в масштабе или особенностей конкретной версии. Для тестирования реального кода Arista используйте собственный лицензированный образ cEOS.
-
Проверки охватывают одноадресный BGP для IPv4/IPv6 (сессии, количество префиксов, атрибуты лучшего маршрута), маршруты и ping, а также сценарии отказа: отключение канала, изоляцию узла и внедрение маршрута (только FRR). Проверки маршрутов уже поддерживают маршруты из любых протоколов (
protocol: ospf,isis,static,connected, ...); проверки соседства OSPF/IS-IS и пути/traceroute появятся позже. -
В выпущенной версии пока нет драйверов для Cisco и Juniper. Для их лабораторных образов нужна учётная запись у производителя, а сами образы нельзя распространять. Поэтому для этих драйверов, как и для cEOS, потребуется собственный образ. Следующими в плане развития идут Juniper и Cisco NX-OS.
О том, как проверяются и выпускаются результаты и какие доказательства подтверждают каждое утверждение: Как это устроено.
План развития
Это направление развития, а не обязательство: версия выпускается, когда все условия её релиза выполнены, а не к определённой дате.
-
0.4.1 (текущая): исправление GHSA-cg9f-xjw5-38ph, бета-версии Cisco NX-OS и MikroTik, усиление защиты цепочки поставок
-
Позже: контракт состояния маршрутизатора для всех драйверов, бета-версия Cumulus, надёжность проверок и подписанные подтверждения результатов, бета-версия размещённой проверки, затем OSPF/IS-IS, пути, EVPN и MPLS — по мере спроса
Полный план развития: netdryrun.com/roadmap.
Если Netdryrun помог вам обнаружить проблему, поставьте ⭐ — так другим инженерам и агентам будет проще найти этот проект.
Лицензия
Apache-2.0. «Netdryrun» и логотип Netdryrun являются товарными знаками; подробности см. в файле TRADEMARKS.md.