VLAN повесили не туда, и прод два часа жил в тестовой сети
В пятницу вечером инженер поменял настройку на коммутаторе — рутинная задача, пять минут работы. К понедельнику продакшн-сервер два часа жил не в той сети: часть систем не видела его вовсе, а часть неожиданно получила доступ к тестовым ресурсам вместо боевых. Никто ничего не взламывал, никто не трогал код — просто один порт коммутатора настроили не на тот VLAN. Разбираем, как так вышло, почему это опаснее обычной сетевой недоступности и что делать, чтобы не повторить.
Содержание
Что вообще произошло
Плановая задача звучала безобидно: расширить сегмент тестового окружения и добавить в него новый коммутатор. В рамках этой работы инженер прошёлся по конфигурации портов на существующем свитче — где-то поменял VLAN на транковых портах, где-то переназначил access-порты под новые тестовые машины.
Один из портов, к которому физически подключён продакшн-сервер, в этот момент был перепутан с соседним портом того же блока (оба вели к серверам в одной стойке, оба на первый взгляд не подписаны однозначно). В результате access-порт продакшн-сервера получил VLAN тестового сегмента вместо боевого.
Кабель никто не трогал. Физически всё осталось как было. Но с точки зрения логической топологии сервер в тот момент оказался в другой сети — как будто его физически переставили в другую комнату, хотя он не сдвинулся ни на сантиметр.
Первые симптомы появились не сразу — сервер работал, отвечал на пинги из локальной подсети, и первые минуты ничего не выглядело сломанным. Проблема всплыла, когда:
- мониторинг из боевого сегмента перестал достучаться до сервера по внутреннему IP;
- при этом с сервера внезапно стал виден DNS тестового окружения и один из тестовых экземпляров базы данных, к которым продакшн в норме доступа не имеет.
Второй пункт — тот самый неприятный сценарий: не просто "сервер недоступен", а "сервер видит не то, что должен, и потенциально может обратиться не туда".
Как работает VLAN и почему ошибка в одну цифру ломает всё
VLAN (Virtual LAN, виртуальная локальная сеть) — это способ логически разделить один физический коммутатор на несколько независимых друг от друга сетей без физического разделения оборудования. Вместо того чтобы городить отдельный свитч под "прод", отдельный под "тест" и отдельный под "управление", вы берёте один физический свитч и делите его порты между несколькими VLAN — например, VLAN 10 для продакшна, VLAN 20 для тестового контура, VLAN 99 для управления самим сетевым оборудованием.
С точки зрения устройств внутри разных VLAN это выглядит как две совершенно разные сети: трафик из VLAN 10 не долетает до VLAN 20 без явной маршрутизации между ними (обычно через L3-коммутатор или роутер с настроенными правилами). Даже если кабели физически воткнуты в один и тот же свитч, устройства в разных VLAN друг друга "не видят" на канальном уровне.
Ключевой момент — принадлежность конкретного порта коммутатора к конкретному VLAN настраивается администратором вручную (или полуавтоматически, если есть система управления конфигурацией). Обычно это выглядит примерно так, на уровне логики конфигурации:
interface GigabitEthernet0/12
description prod-app-server-01
switchport mode access
switchport access vlan 10
Если вместо vlan 10 по ошибке ввести vlan 20, или применить эту команду не к порту 0/12, а к соседнему порту 0/13 — коммутатор не станет ругаться. Синтаксически команда корректна, порт переходит в указанный VLAN, конфигурация применяется без единой ошибки. Единственная проблема в том, что теперь сервер, физически подключённый к этому порту, логически находится в другом сегменте сети — том, где живут тестовые базы, тестовые релизы и совершенно другие правила доступа.
Это и есть суть проблемы: ошибка не в протоколе, не в оборудовании, не в коде. Ошибка — в одной цифре, введённой вручную в момент рутинного изменения. Коммутатор делает ровно то, что ему сказали, просто сказали не то, что имелось в виду.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверХронология расследования
Восстановить порядок событий удалось довольно быстро, потому что симптомы были специфичными — не "сервер лежит", а "сервер ведёт себя странно избирательно".
Момент 0. Инженер вносит плановые изменения VLAN на коммутаторе для расширения тестового сегмента. Изменения применяются, сессия закрывается, задача помечается выполненной.
+15 минут. Мониторинг фиксирует потерю связи с продакшн-сервером по внутреннему адресу мониторинга. Алерт уходит дежурному, но выглядит неоднозначно — сервис по внешнему IP отвечает нормально, значит "не похоже на полный даун".
+40 минут. Дежурный инженер подключается к серверу через внешний доступ (по счастью, внешний интерфейс сервера не зависел от изменённого VLAN) и начинает проверять сетевые настройки изнутри. ip addr и ip route на самом сервере выглядят нормально — адрес тот же, шлюз тот же, конфигурация ОС не менялась.
+55 минут. Проверка с внутреннего мониторингового узла показывает: сервер не отвечает на ARP-запросы из ожидаемой подсети продакшна. Одновременно кто-то из команды замечает, что с продакшн-сервера стал резолвиться внутренний DNS-сервер тестового окружения — а такого адреса продакшн знать не должен.
+70 минут. Это и есть переломный момент расследования: если сервер не виден из своей сети, но видит чужую сеть — значит, дело не в кабеле и не в самом сервере, а в том, к какому логическому сегменту подключён его физический порт. Внимание переключается с сервера на коммутатор.
+90 минут. На коммутаторе явно запрашивается конфигурация конкретного порта, к которому подключён сервер: show running-config interface GigabitEthernet0/12 (или эквивалент для используемой модели свитча). Значение switchport access vlan сравнивается с тем, что должно быть согласно документации по портам. Расхождение находится за минуту — порт числится в VLAN 20 (тест) вместо ожидаемого VLAN 10 (прод).
+95 минут. VLAN на порту возвращается к правильному значению. Связь с боевого мониторинга восстанавливается почти мгновенно — как только меняется членство порта в VLAN, устройство физически остаётся тем же, просто снова "видно" из правильного сегмента.
+120 минут. Финальная проверка: с сервера действительно пропал доступ к тестовому DNS и тестовой базе, боевой мониторинг видит сервер штатно, дополнительно вручную проверяется маршрутизация до других боевых узлов, чтобы исключить сопутствующие ошибки в том же изменении.
Итого — около двух часов с момента изменения до полного восстановления, из которых больше половины ушло на то, чтобы просто понять, где искать проблему, а не на само исправление (оно заняло меньше минуты).
Корневая причина
Формально причина простая: человеческая ошибка при ручном изменении конфигурации коммутатора. Инженер либо перепутал номер порта (применил правило не к тому интерфейсу), либо перепутал номер VLAN (ввёл значение соседнего сегмента). Оба варианта дают одинаковый результат и в реальности неотличимы друг от друга постфактум — конфигурация не хранит "что имелось в виду", только то, что было применено.
Но если копнуть на уровень глубже, есть системная причина, которая делает такую ошибку вероятной, а не случайной аномалией:
- Порты не были однозначно задокументированы. Соседние порты в одной стойке вели к серверам с похожим назначением, и различить их по одной лишь физической маркировке было сложно — приходилось сверяться с отдельной таблицей, которая на момент изменения оказалась не под рукой или устарела.
- Изменение вносилось вручную через CLI коммутатора, без промежуточного слоя проверки. Ни одна система не спросила "вы уверены, что хотите перевести порт с описанием prod-app-server-01 в тестовый VLAN?" — потому что такой проверки просто не существовало.
- Не было пост-проверки после изменения. Задача считалась выполненной по факту применения команды, а не по факту подтверждения, что сеть работает так, как задумано. Если бы сразу после изменения кто-то проверил доступность продакшн-сервера из боевого сегмента, инцидент занял бы минуты, а не два часа.
Ни один из этих пунктов не является чьей-то виной в духе "инженер невнимательный". Это ровно те точки, где обычно и рождаются подобные инциденты — на стыке ручного труда, неполной документации и отсутствия быстрой обратной связи о результате изменения. Если хотите почитать про то, как правильно оформлять такие разборы без поиска виноватых, у нас есть отдельный материал — как писать разбор инцидента, чтобы из него учились.
Почему это опаснее, чем "сервер недоступен"
Обычная сетевая недоступность неприятна, но безопасна в смысле данных: сервис не отвечает, вы это видите практически сразу, чините и восстанавливаете доступ. Здесь есть похожий по механике инцидент — ошиблись в правиле firewall и потеряли доступ к серверу, где ошибка тоже была в одну строку конфигурации, но последствие было однозначным — доступа просто не стало.
Ошибка с VLAN опаснее именно тем, что у неё два разных сценария, и один из них не выглядит как авария:
- Сервер стал недоступен из ожидаемых источников — это заметно сразу, мониторинг кричит, инцидент открывается немедленно.
- Сервер получил доступ к чужому сегменту — а это может остаться незамеченным намного дольше, если сервис продолжает отвечать снаружи и никто целенаправленно не проверяет, откуда он резолвит DNS или к какой базе цепляется.
Второй сценарий — это риск смешения окружений: продакшн-процесс, который в норме подключается строго к боевой базе данных по внутреннему адресу, вдруг видит DNS-имя, которое резолвится в тестовую базу (если имена в тестовом и боевом окружении случайно совпадают или похожи, а это бывает чаще, чем хотелось бы). В худшем случае это означает, что боевые данные могут на короткое время записаться не туда, или что тестовые данные — гораздо менее защищённые, часто с урезанными правами доступа и слабее контролируемые — окажутся видны процессу, который рассчитан на продакшн-уровень доверия.
Даже если в конкретном инциденте до реальной записи не в ту базу не дошло — сам факт, что окно возможности для этого существовало, стоит фиксировать как отдельный риск, а не как "ну обошлось же".
Практические выводы: явная проверка после каждого сетевого изменения
Главный вывод из этой истории простой и звучит скучно, но именно скучные правила и предотвращают инциденты: после любого изменения конфигурации коммутатора нужно явно проверить, что каждый затронутый сервер физически оказался там, где ожидалось — а не полагаться на то, что раз команда применилась без ошибок, значит всё в порядке.
Практически это можно сделать несколькими способами, и лучше комбинировать их, а не выбирать один:
Проверка изнутри сервера. Сразу после изменения VLAN проверьте с самого сервера, что он видит именно те ресурсы, которые должен, и не видит те, которых видеть не должен:
# Должен резолвиться и быть доступен — боевой ресурс
ping -c 3 prod-db.internal
# Не должен резолвиться и быть недоступен — тестовый ресурс
ping -c 3 staging-db.internal
Если второй ping внезапно проходит — это тревожный сигнал сам по себе, даже если первый тоже работает.
Проверка с точки зрения мониторинга. Не полагайтесь на то, что алерт молчит — значит, всё хорошо. Активно опросите систему мониторинга: видит ли она сервер по внутреннему адресу прямо сейчас, а не по последнему успешному чек-ину пятиминутной давности.
Проверка на самом коммутаторе. Прямо на свитче сверьте VLAN порта с ожидаемым значением командой вида show interfaces status (список портов с их текущим VLAN одной таблицей) или точечно по интерфейсу:
show running-config interface GigabitEthernet0/12
Сравните вывод switchport access vlan с тем, что записано в документации по портам — не по памяти, а по факту записанного значения.
Документирование портов и автоматизация вместо ручных правок
Помимо немедленной проверки после изменения, стоит закрыть системную причину, а не только симптом конкретного инцидента.
Таблица соответствия портов и VLAN. Должна существовать (и реально поддерживаться в актуальном состоянии, а не заводиться один раз и забываться) таблица вида:
| Порт коммутатора | Назначение | Ожидаемый VLAN | Подключённое устройство |
|---|---|---|---|
| Gi0/12 | prod | 10 | prod-app-server-01 |
| Gi0/13 | prod | 10 | prod-db-server-01 |
| Gi0/20 | staging | 20 | staging-app-server-01 |
| Gi0/48 | management | 99 | uplink to core switch |
Такая таблица не заменяет проверку после изменения, но резко снижает шанс перепутать порт при внесении правки — особенно если она открыта прямо во время работы, а не хранится где-то отдельно "для отчётности".
Описание на самом порту. Команда description prod-app-server-01 в конфигурации интерфейса стоит копейки по времени, но именно она позволяет при беглом просмотре конфигурации сразу увидеть, что порт критичный, а не просто "ещё один свободный слот".
Автоматизация вместо ручных правок через CLI. Там, где это оправдано по масштабу инфраструктуры, стоит переходить от ручных команд в консоли коммутатора к декларативной конфигурации через инструменты автоматизации — например, задавать состояние портов в виде плейбука и применять его целиком, а не вводить команды построчно. Это не убирает риск ошибки полностью (можно неправильно описать состояние и в плейбуке), но убирает конкретно класс ошибок "перепутал порт при ручном вводе в моменте", потому что конфигурация каждого порта явно видна в одном файле перед применением, а не собирается по одной команде за раз в интерактивной сессии. Если у вас в принципе есть сетевая инфраструктура на базе виртуализации, похожая тема разбирается в статье про сеть в Proxmox — мосты, VLAN и потерю доступа, где механизм ошибки очень похож, только на уровне гипервизора, а не физического свитча.
Отдельное правило для риска смешения окружений. Помимо стандартной проверки "сервер доступен там, где должен", после любого сетевого изменения стоит явно проверять и обратное — что сервер НЕ получил доступ туда, куда не должен. Это отдельный пункт чек-листа, и его легко пропустить, потому что интуитивно "всё работает" воспринимается как "всё в порядке", хотя на деле "всё работает, и вдобавок работает то, что не должно" — куда более опасный результат, чем просто "не работает". Если у вас есть отдельная тестовая среда, имеет смысл сразу закладывать в её сетевую схему такую изоляцию, которую физически (а не только по договорённости) сложно случайно нарушить — про выбор и настройку такой среды есть материал VPS для тестовой среды: что выбрать и как настроить.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Как быстро можно было бы поймать такую ошибку без потери двух часов?
Если сразу после изменения VLAN выполнить проверку доступности сервера из боевого сегмента (даже простым пингом с мониторингового узла), несоответствие обнаружилось бы за минуты, а не за час с лишним. Основная потеря времени в описанном случае — не в исправлении, а в том, что симптомы не сразу указывали на сетевой уровень.
Может ли VLAN сам по себе гарантировать полную изоляцию окружений?
VLAN обеспечивает изоляцию на канальном уровне при условии, что конфигурация портов и правил маршрутизации между VLAN настроена корректно. Если между VLAN настроена маршрутизация "разрешить всё" или ошибочно задан не тот VLAN на порту (как в этом разборе), изоляция нарушается не из-за недостатка технологии, а из-за ошибки в конфигурации.
Стоит ли использовать один и тот же коммутатор для прод и тестового окружения, разделяя их VLAN?
Это обычная и вполне рабочая практика — VLAN как раз для этого и придуманы. Но чем выше цена ошибки смешения окружений, тем больше смысла добавлять физическое разделение критичных узлов на отдельные порты/коммутаторы либо усиливать процесс проверки после каждого изменения, а не полагаться только на логическую изоляцию.
Что делать, если непонятно, какой именно порт коммутатора ведёт к серверу?
Свериться с таблицей соответствия портов, если она есть и актуальна; если её нет или она под вопросом — определить порт по MAC-адресу сервера через таблицу коммутации (show mac address-table или аналог), а не угадывать по расположению в стойке.
Нужно ли после такого инцидента менять пароли или считать данные скомпрометированными?
Сам по себе факт временной сетевой видимости не равен утечке данных — если в тестовом сегменте не было выполнено реальных запросов к боевым ресурсам (или наоборот), компрометации данных не происходит. Но стоит явно проверить логи на обеих сторонах за период инцидента, а не полагаться на предположение "наверное, обошлось".
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →