На границе сети VLAN 100 превращается в VLAN 200: как описать трансляцию идентификаторов в NetBox 4.2
Если на вашей стороне это VLAN 100, а у оператора тот же линк живёт как VLAN 200 — это нормально, если кто-то это записал. С версии 4.2 в NetBox для этого есть модель VLANTranslationPolicy с правилами VLANTranslationRule — их вешают на порт через UI или REST API. Разбираю синтаксис и ограничения модели на примере офиса на 22 рабочих места.
Почему обычный список VLAN не хранит соответствие ID на границе сети
В NetBox VLAN — это объект с vid, именем, группой и статусом на конкретной площадке или в конкретном VLAN group. Он прекрасно отвечает на вопрос «что такое VLAN 100 в этом офисе». Но он ничего не знает про то, как этот же сегмент называется по другую сторону границы — на аплинке к провайдеру, на транке между филиалами или на стыке с сетью подрядчика. А эта граница есть почти в каждой сети, где я внедряю NetBox для документирования: у провайдера Ethernet-канала нумерация VLAN своя, внутренняя, и с вашей она никогда не обязана совпадать.
До версии 4.2 эту привязку в NetBox можно было только имитировать: заводить второй VLAN-объект с тем же именем в отдельной VLAN group «внешние», писать в comments порта что-то вроде «на стороне оператора это VLAN 200» и надеяться, что через полгода это поле кто-то откроет перед заменой коммутатора. Запрос на нормальную модель для 1:1 трансляции VLAN ID между группами лежал в трекере NetBox под номером 7336 не один год, его приняли в разработку и включили в веху v4.2 — то есть сообщество явно упиралось в эту дыру достаточно часто, чтобы это стало отдельной фичей, а не костылём.
В релизе 4.2.0 (вышел 6 января 2025 года) это наконец появилось как первоклассная сущность: VLANTranslationPolicy — именованная политика, VLANTranslationRule — конкретное правило внутри неё вида «локальный VID → удалённый VID». Политику можно один раз описать и переиспользовать на любом числе портов, а не копировать комментарий из порта в порт. Добавили и пару REST-эндпоинтов — /api/ipam/vlan-translation-policies/ и /api/ipam/vlan-translation-rules/ — так что это не только функция формы в вебе, но и то, что можно завести скриптом при массовом описании сети.
Модель данных: что на самом деле хранят VLANTranslationPolicy и VLANTranslationRule
VLANTranslationPolicy устроена скромно: по факту у неё один содержательный собственный атрибут — name, строка до 100 символов, обязательно уникальная в рамках инсталляции. Остальное — description, comments, tags, custom fields — она получает от базового класса PrimaryModel, как и большинство объектов NetBox. Сама по себе политика ничего не транслирует, это просто именованный контейнер, к которому потом привязываются правила и порты. Логика в том, чтобы описать схему трансляции один раз («аплинк к оператору X», «транк на филиал Y») и вешать её на десятки интерфейсов без копирования.
Собственно трансляцию описывает VLANTranslationRule: обязательная ссылка policy на политику (при удалении политики правила удаляются вместе с ней, on_delete=CASCADE), два числовых поля local_vid и remote_vid с проверкой диапазона 1–4094, и необязательное description до 200 символов. Модель жёстко следит за целостностью: в рамках одной политики действует ограничение уникальности отдельно на пару (policy, local_vid) и отдельно на пару (policy, remote_vid). Это значит, что связка местный↔удалённый VID внутри политики строго один-к-одному: один local_vid не может смотреть в два разных remote_vid, и наоборот, два local_vid не могут указывать на один remote_vid.
Ниже — как это выглядит в сравнении со старым способом хранить эту информацию (свободный текст/таблица вне NetBox) и новой моделью:
| Что нужно | Было (таблица/комментарий) | Стало (VLANTranslationPolicy) |
|---|---|---|
| Хранение пары ID | текст, не валидируется | поля local_vid/remote_vid, диапазон 1–4094 |
| Уникальность пары | вручную, никто не проверяет | UniqueConstraint (policy, local_vid) и (policy, remote_vid) |
| Переиспользование на портах | копипаста комментария | одна политика на много интерфейсов |
| Доступ по API | нет | /api/ipam/vlan-translation-policies/, /api/ipam/vlan-translation-rules/ |
| Аудит изменений | не ведётся | правило пишет объект изменений и на себя, и на родительскую политику |
Последнее — не мелочь: у VLANTranslationRule переопределён to_objectchange, и изменение конкретного правила попадает в журнал изменений связанной политики тоже. Когда через полгода кто-то спросит «кто поменял маппинг VID на этом порту», ответ находится за один клик, а не за архивом переписки.
Как политика попадает на порт: Interface, VMInterface и связь с режимом Q-in-Q
Поле vlan_translation_policy добавлено в общий базовый класс интерфейсов, поэтому оно одинаково доступно и на физическом DCIM-интерфейсе, и на VMInterface виртуальной машины — если у вас гипервизор или контейнерный хост с транком, который тоже подчиняется чужой нумерации VLAN на внешней стороне, трансляцию можно описать точно так же. Это внешний ключ на VLANTranslationPolicy с on_delete=PROTECT: NetBox физически не даст удалить политику, пока хотя бы один интерфейс на неё ссылается — сначала придётся руками отвязать все порты. Мелочь, но именно она спасает от ситуации «случайно снёс политику, и полсети потеряла описание границы».
Ключевое свойство здесь — переиспользование: одна и та же политика вешается на любое число интерфейсов. Если у вас, например, сеть разбита на VLAN по отделам и у каждого коммутатора есть однотипный аплинк с одинаковой схемой трансляции VID, политику заводят один раз и назначают на все такие порты — а не плодят N одинаковых правил под разными именами. При массовой смене схемы (провайдер перенумеровал VLAN на своей стороне) достаточно поправить local_vid/remote_vid в одном правиле, и это применится ко всем портам, которые на эту политику ссылаются.
Отдельно стоит не путать трансляцию с режимом Q-in-Q, который в NetBox 4.2 добавили тем же релизом: у поля «802.1Q Mode» интерфейса появилось четвёртое значение — Q-in-Q (IEEE 802.1ad), с отдельным полем под SVLAN. Q-in-Q — это двойная инкапсуляция, внешний тег поверх внутреннего, сохраняющий оба ID одновременно. VLANTranslationPolicy — это подмена одного ID на другой в рамках того же уровня инкапсуляции. Механизмы разные и в реальной сети решают разные задачи, но раз оба появились в одном релизе, я на практике вижу, как их путают уже на этапе выбора, какое поле заполнять на интерфейсе.
REST API: как завести политику и правила без единого клика в UI
Форма в вебе удобна для одной политики, но если вы документируете сеть с десятками однотипных аплинков, быстрее пройти через API — тем более что в 4.2 под это выделены отдельные эндпоинты. Сначала создаём саму политику:
curl -s -X POST https://netbox.example.com/api/ipam/vlan-translation-policies/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "klishe-profi-isp-uplink",
"description": "Трансляция VID на аплинке к оператору"
}'Ответ вернёт id созданной политики — он понадобится для правил.
Дальше заводим само правило (или сразу несколько — эндпоинт принимает как один объект, так и список объектов для пакетного создания):
curl -s -X POST https://netbox.example.com/api/ipam/vlan-translation-rules/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"policy": 3,
"local_vid": 100,
"remote_vid": 200,
"description": "Офис -> хэндофф провайдера"
}'policy здесь — числовой ID политики, а не имя: политика должна существовать до создания правила, нативно вложенного создания «политика + правила одним запросом» эндпоинт не поддерживает.
Осталось привязать политику к порту — это делается не через сам объект политики, а PATCH-запросом к интерфейсу:
curl -s -X PATCH https://netbox.example.com/api/dcim/interfaces/482/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"vlan_translation_policy": 3}'Тот же PATCH с "vlan_translation_policy": null политику с порта снимает. Я обычно заворачиваю эти три вызова в один Python/Ansible-плейбук при массовом описании границы сети — так за один прогон закрывается вся пачка однотипных аплинков, а не по одному в вебе.
Кейс: «Клише Профи» — VLAN 100 у нас, VLAN 200 у провайдера
Производство печатей и штампов «Клише Профи» — 22 рабочих места, один офис, один аплинк-канал у оператора связи. Офисная сеть живёт в VLAN 100, а через аплинк идут арендованная облачная 1С, IP-телефония и заказы от интернет-магазина на гравировку. У провайдера на их стороне хэндоффа этот же канал числится как VLAN 200 — так у них устроена внутренняя нумерация клиентских портов, и на это мы повлиять не можем. До того как я занялся их сетью, это соответствие 100↔200 нигде не было записано, кроме заметки в блокноте инженера, который когда-то поднимал канал.
Инцидент, который сделал это видимой проблемой: провайдер по своей заявке переключил клиента на другой порт агрегирующего коммутатора и попросил нас продиктовать VLAN ID со своей стороны. Диктовали 100 — то есть свой внутренний, а не тот, что был согласован на границе. Порт подняли с неверным маппингом, офис на 22 рабочих места простоял без доступа к 1С и телефонии порядка 40 минут, пока не подняли ту самую переписку годичной давности и не сверили правильную пару.
После этого завёл в NetBox политику klishe-profi-isp-uplink с description «граница с провайдером, хэндофф аплинка» и одним правилом: local_vid 100, remote_vid 200, description «офисный VLAN — внешний VID хэндоффа провайдера». Политику привязал к интерфейсу пограничного коммутатора, через который идёт аплинк. Порядок действий, который я теперь применяю к каждому пограничному порту, — в списке ниже; всё вместе заняло меньше времени, чем сам инцидент.
Правило в NetBox не меняет конфигурацию коммутатора само по себе — это документация, а не SDN-контроллер. Реальную трансляцию (или просто корректную нумерацию VLAN на порту) я всё равно настраиваю руками на оборудовании. Но теперь при любом обращении к провайдеру, при замене порта или при передаче сети другому инженеру нужный VID со своей и с чужой стороны — это одна карточка в NetBox, а не блокнот, который может потеряться вместе с человеком, который его вёл.
- Завести VLANTranslationPolicy с именем по схеме «клиент/направление-uplink»
- Добавить правило local_vid → remote_vid с описанием, что это за граница
- Привязать политику к интерфейсу пограничного порта через PATCH или форму
- Сверять факт на коммутаторе с записью в NetBox при любой смене порта у провайдера
Чего трансляция VID в NetBox не делает — и где на этом спотыкаются
Первое и самое важное ограничение я уже назвал в кейсе: NetBox — это Source of Truth для документации сети, а не система управления конфигурацией. VLANTranslationPolicy и её правила нигде не отправляют команды на свитч. Если у вас настроена сетевая документация как отдельный процесс, добавление этой модели логично встраивается туда же: сначала фиксируете факт в NetBox, потом (или параллельно) настраиваете реальную трансляцию на оборудовании — vendor-специфичной командой вроде маппинга VLAN на порту у Cisco или Q-in-Q/VLAN mapping у других производителей.
Второе — жёсткая схема 1:1 внутри одной политики. Ограничения уникальности на (policy, local_vid) и на (policy, remote_vid) исключают модель «много локальных VID схлопываются в один внешний» в рамках одной и той же политики: если реальная топология именно такая (агрегация нескольких внутренних VLAN в один внешний на границе), для каждой такой пары придётся заводить отдельную политику или пересматривать сетевой дизайн — сама модель вас на многие-к-одному не пустит, и это осознанное ограничение разработчиков, а не баг.
Третье — PROTECT на связи интерфейса с политикой ловит не всех. Он защищает от удаления самой политики, пока она используется хотя бы одним портом, но ничего не мешает создать правило с правильными на вид числами и забыть привязать политику к нужному интерфейсу — тогда данные в NetBox корректны, а граница сети по-прежнему не описана там, где реально нужна. Я в таких случаях после массового заведения политик прогоняю сверку: выбираю все интерфейсы с типом «аплинк»/«транк» по тегу и фильтром API проверяю, у скольких из них поле vlan_translation_policy пустое.
Как сделать трансляцию VID частью документации сети, а не разовой правкой
Смысла заводить VLANTranslationPolicy разово, для одного инцидента, немного — это работает как система, только если стало правилом при описании любого пограничного порта. Я завожу его в тот же момент, что и сам интерфейс в NetBox: если порт — это аплинк к внешней стороне (провайдер, филиал, подрядчик) и есть хоть малейший шанс, что нумерация VLAN у них своя, сразу спрашиваю заказчика или смотрю в акт подключения, какой ID там на самом деле, и завожу правило, а не оставляю «уточнить потом».
Если у вас в компании уже есть практика документировать инфраструктуру в NetBox целиком, трансляция VID — это не отдельный проект, а ещё одно поле в чек-листе на вводе нового интерфейса в границе сети. Отдельно рекомендую единый нейминг политик (у меня — «клиент-направление-uplink» или «площадка1-площадка2-trunk»): когда политик становится больше десятка, найти нужную по осмысленному имени в разы быстрее, чем перебирать список правил по ID.
Раз в квартал я прогоняю по API простую сверку: выгружаю все интерфейсы с непустым vlan_translation_policy, для каждого — реальный VID на порту (по факту с оборудования, не из NetBox) и сравниваю с local_vid в привязанном правиле. Разошлось — значит, кто-то поменял конфигурацию на коммутаторе и не обновил документацию, и это повод разобраться раньше, чем разойдётся окончательно и обернётся простоем вроде того, что был у «Клише Профи».
Частые вопросы
С какой версии NetBox доступна трансляция VLAN ID?
С 4.2.0, вышедшей 6 января 2025 года. Модели VLANTranslationPolicy и VLANTranslationRule и эндпоинты /api/ipam/vlan-translation-policies/ и /api/ipam/vlan-translation-rules/ доступны во всех последующих релизах ветки 4.2 и новее; в 4.2.5 добавили массовое назначение политики при bulk-редактировании интерфейсов, в 4.2.8 — фильтрацию интерфейсов по политике.
Можно ли назначить одну политику на несколько интерфейсов сразу?
Да, это и есть основной сценарий использования: политика — переиспользуемый объект, а не разовая настройка одного порта. Один и тот же VLANTranslationPolicy можно привязать к любому числу интерфейсов Interface и VMInterface.
Что будет, если попытаться удалить политику, которая привязана к порту?
NetBox не даст это сделать: поле vlan_translation_policy на интерфейсе ссылается на политику с on_delete=PROTECT. Сначала нужно отвязать политику от всех интерфейсов (или удалить сами интерфейсы), и только потом политика удалится.
Работает ли трансляция VID для виртуальных машин, не только для физических портов?
Да. Поле vlan_translation_policy определено на общем базовом классе интерфейсов, поэтому доступно и на физическом Interface в DCIM, и на VMInterface в модуле виртуализации.
Меняет ли создание правила в NetBox реальную конфигурацию коммутатора?
Нет. NetBox документирует факт трансляции, но не отправляет команды на оборудование. Реальный маппинг VLAN ID на порту нужно настроить отдельно, средствами конкретного вендора, и потом сверять с записью в NetBox.
Как быстро загрузить в NetBox много правил трансляции сразу?
Через bulk-создание: POST на /api/ipam/vlan-translation-rules/ с телом-массивом объектов вместо одного объекта создаст сразу несколько правил одним запросом — стандартный для REST API NetBox паттерн пакетных операций.
Источники
- NetBox Docs — VLAN Translation Policy (models/ipam/vlantranslationpolicy) — Проверены поля модели VLANTranslationPolicy (name) и VLANTranslationRule (policy, local_vid, remote_vid), уникальность пар (policy, local_vid) и (policy, remote_vid), возможность назначения на Interface и VMInterface. https://netboxlabs.com/docs/netbox/models/ipam/vlantranslationpolicy/
- NetBox — Release Notes, version 4.2 — Подтверждена дата выхода 4.2.0 (2025-01-06) и формулировка фичи «policies which track the translation of VLAN IDs», добавление полей vlan_translation_policy на Interface/VMInterface и режима Q-in-Q; в 4.2.5 — bulk-назначение политики, в 4.2.8 — фильтрация по политике. https://netboxlabs.com/docs/netbox/release-notes/version-4.2/
- GitHub — netbox-community/netbox, issue #7336 (VLAN Translation) — Проверена исходная постановка задачи (1:1 маппинг VLAN между группами, потребность в полях API/UI/CSV), статус issue закрыт, веха — v4.2. https://github.com/netbox-community/netbox/issues/7336
- NetBox Labs — NetBox 4.2 Is Now Generally Available (blog) — Проверена формулировка назначения фичи и то, что VLAN translation вышла в одном релизе с поддержкой Q-in-Q инкапсуляции (SVLAN, режим интерфейса Q-in-Q) и другими IPAM/DCIM-изменениями 4.2. https://netboxlabs.com/blog/netbox-4-2-generally-available/
- GitHub — netbox-community/netbox, исходный код models/vlans.py (тег v4.2.0) — Проверен точный код классов VLANTranslationPolicy (PrimaryModel, name unique max_length=100) и VLANTranslationRule (FK policy CASCADE, local_vid/remote_vid PositiveSmallIntegerField 1–4094, UniqueConstraint по (policy, local_vid) и (policy, remote_vid), переопределённый to_objectchange). https://github.com/netbox-community/netbox/blob/v4.2.0/netbox/ipam/models/vlans.py
- NetBox Docs — Interface (models/dcim/interface) — Проверено поле vlan_translation_policy на интерфейсе (FK, необязательное) и значения режима 802.1Q Mode, включая добавленный в 4.2 режим Q-in-Q с полем SVLAN. https://netboxlabs.com/docs/netbox/models/dcim/interface/



