VLAN — разделение одного провода на много сетей
Допустим, у вас офис на 200 человек. Маркетинг, разработка, бухгалтерия, гости — всем нужен интернет. Можно купить четыре отдельных свитча, прокинуть четыре кабельных трассы, поставить четыре роутера. Дорого, неудобно, неуправляемо. А можно купить один свитч с поддержкой VLAN и логически разделить его на четыре виртуальных свитча. Это то, что VLAN делает.
VLAN (Virtual LAN) — это технология, позволяющая на одном физическом свитче создавать несколько изолированных broadcast domains. Кадр с одного VLAN никогда не попадёт в другой VLAN без явного роутинга через L3-устройство. Это даёт безопасность, экономию железа и гибкость.
В этом уроке посмотрим, что такое тег 802.1Q, чем отличается trunk-порт от access-порта, и где VLAN-ы используются в реальной инфраструктуре. Знание VLAN-ов нужно DE, потому что в дата-центрах, в Kubernetes-кластерах с CNI вроде Calico/VLAN, в офисных сетях — VLAN-ы везде. И когда вы видите в ip addr интерфейс eth0.10 — вы знаете, что это VLAN 10 на eth0.
Зачем VLAN — разбиваем broadcast domain
Главные проблемы большой плоской сети без VLAN:
- Broadcast storm risk. ARP, DHCP, mDNS — всё broadcast. 500 машин в одном broadcast domain = много шума. Если кто-то сделает loop — broadcast storm и сеть умирает.
- Безопасность. Любой может ARP-spoof’ить любого. Маркетинг видит трафик бухгалтерии (через ARP poisoning).
- Маштабирование. MAC-table свитчей имеет лимиты. Если у вас 50,000 устройств в одном broadcast domain — свитчи не справляются.
VLAN решает это разделением: вы говорите свитчу «port 1-8 — это VLAN 10 (разработка), port 9-16 — VLAN 20 (маркетинг)». Все кадры маркируются тегами VLAN-а внутри свитча. Кадры из VLAN 10 не попадают в порты VLAN 20.
NetworkPolicy: основы изоляции трафика в кластереС точки зрения хостов это выглядит как два разных свитча. Между VLAN-ами нет L2-связности — нужен роутер.
Tagged vs untagged — два режима порта
У свитч-порта с поддержкой VLAN есть два главных режима: access и trunk.
Access port. Порт привязан к одному VLAN. Подключённое устройство не знает про VLAN-ы вообще — оно отправляет обычные Ethernet-кадры (без тегов). Свитч сам добавляет VLAN ID когда кадр заходит, и убирает когда кадр выходит.
Trunk port. Порт может пропускать несколько VLAN-ов. Кадры идут с VLAN-тегом. Используется для подключения свитчей друг к другу, гипервизоров с виртуалками в разных VLAN, или хостов, которые сами знают про VLAN-ы (Linux-сервер с vlan модулем).
Типичная топология:
- Свитч1 порт 1 — access VLAN 10 — подключён ноутбук разработчика.
- Свитч1 порт 24 — trunk (VLAN 10, 20, 30) — идёт в свитч2 в соседней комнате.
- Свитч2 порт 1 — access VLAN 20 — маркетинг.
- Свитч1 порт 23 — trunk — идёт в роутер, который умеет маршрутизировать между VLAN.
802.1Q — как тегается кадр
VLAN-тег — это 4 байта, которые свитч вставляет между src MAC и EtherType обычного Ethernet-кадра. Стандарт называется IEEE 802.1Q.
Особенности:
- VLAN ID — 12 бит, значит максимум 4094 VLAN-а на одном свитче. Для дата-центров с десятками тысяч клиентов это мало — придумали VXLAN с 24-битным VNI (16 миллионов сетей).
- Native VLAN. В trunk-порту обычно один VLAN ID помечен как «native» — кадры в нём идут БЕЗ тега. Это для совместимости с устройствами, которые не понимают теги. Обычно настраивается осторожно (security risk — VLAN hopping).
- QinQ (802.1ad). Два тега друг за другом — провайдеры используют это, чтобы пробросить клиентский VLAN внутри своего.
Когда кадр приходит в access-порт без тега — свитч добавляет тег своего VLAN. Когда кадр уходит из access-порта — свитч снимает тег. Хост ничего не знает про VLAN. Это PVID (Port VLAN ID).
В trunk-порту наоборот — кадры идут с тегом. И отправитель, и получатель должны знать про VLAN.
VLAN на Linux
Linux нативно умеет VLAN-ы через модуль 8021q. Вы можете создать виртуальный интерфейс, привязанный к VLAN:
# Загрузить модуль 802.1Q (обычно уже загружен в современных дистрибутивах):
sudo modprobe 8021q
# Создать VLAN 10 на eth0:
sudo ip link add link eth0 name eth0.10 type vlan id 10
sudo ip link set eth0.10 up
sudo ip addr add 10.10.10.5/24 dev eth0.10
# Создать VLAN 20:
sudo ip link add link eth0 name eth0.20 type vlan id 20
sudo ip link set eth0.20 up
sudo ip addr add 10.20.20.5/24 dev eth0.20
# Теперь eth0 -- физический интерфейс, eth0.10 и eth0.20 -- VLAN-интерфейсы
ip -d link show eth0.10
# eth0.10@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
# link/ether ... brd ...
# vlan protocol 802.1Q id 10 <REORDER_HDR> ...
Что происходит на проводе: пакеты, отправленные через eth0.10, в исходящем направлении получают 802.1Q-тег с VLAN ID = 10. Свитч на другом конце должен быть настроен как trunk с разрешённым VLAN 10, иначе он эти кадры дропнет (или они уйдут в native VLAN).
# Захватить VLAN-тегированные кадры:
sudo tcpdump -i eth0 -e 'vlan' -c 3
# 12:34:56.789 a4:83:e7:1a:bb:cc > 00:1c:42:00:00:18, ethertype 802.1Q (0x8100),
# length 102: vlan 10, p 0, ethertype IPv4, ...
# 'vlan 10' -- это VID из тега
# 'p 0' -- priority (PCP)
В выводе видим ethertype 802.1Q вместо ethertype IPv4 — это потому что после src MAC сразу идёт тег, а EtherType 0x0800 спрятан после тега.
Inter-VLAN routing — как связать VLAN-ы
Внутри L2 разные VLAN-ы изолированы. Чтобы машина из VLAN 10 могла достучаться до сервера в VLAN 20, нужен L3-роутинг. Варианты:
1. Роутер с разными интерфейсами в разных VLAN. Каждый VLAN — своя подсеть, у роутера в каждой свой IP. Обычная маршрутизация.
2. Router-on-a-stick. Один физический интерфейс роутера, на нём через trunk заведено несколько VLAN-сабинтерфейсов. На каждом сабинтерфейсе — свой IP. Дёшево, но bottleneck.
3. L3 switch. Свитч с поддержкой роутинга. Внутри ASIC-чипа делает inter-VLAN routing — быстро, без bottleneck. Стандарт для современных DC.
Без роутинга пакеты между VLAN-ами не ходят, даже если устройства подключены к одному свитчу.
VLAN в реальных кейсах
1. Корпоративная сеть. VLAN-ы для отделов, плюс отдельный VLAN для гостевого Wi-Fi (изолирован от внутренних). На свитчах настроены trunk-и между этажами, на роутере — ACL’и.
2. Дата-центр / DevOps. Каждый клиент / приложение / окружение — свой VLAN. Например, VLAN 100 = prod web, VLAN 101 = prod DB, VLAN 200 = staging. Network policies строятся через ACL.
3. Гипервизоры. Каждая VM может быть подключена в свой VLAN. ESXi/Proxmox virtual switch имеет уровень VLAN tagging.
4. Telecom. Провайдеры используют QinQ — свой VLAN снаружи + клиентский VLAN внутри. Это позволяет на одном физическом проводе обслуживать сотни клиентов без коллизий VLAN ID.
5. VoIP. Отдельный VLAN для телефонов, с QoS (PCP=7). Голос идёт с высшим приоритетом — никаких задержек даже если сеть забита.
Где VLAN не работает или мешает
1. VLAN hopping. Атака: если native VLAN не настроен правильно, можно перейти из VLAN 1 в VLAN 10 двойным тегированием. Современные свитчи защищены, но в legacy — осторожно.
2. 4094 — предел. Для гипер-DC мало. Решение — VXLAN, GENEVE, NVGRE: overlay-сети с 24-битным ID поверх IP.
3. VLAN-aware Linux требует MTU-внимания. VLAN-тег добавляет 4 байта. Если у вас MTU = 1500 на trunk-порте, а в VLAN-интерфейсе тоже MTU = 1500 — получится 1504 байт на проводе. Большинство свитчей это нормально проглатывают (стандарт «baby giant» 1518+4=1522), но не все. В случае проблем уменьшайте MTU VLAN-интерфейса на 4.
4. Spanning Tree. STP считает топологию для всей L2-сети. Большие плоские топологии с VLAN-ами могут страдать от долгого convergence. Решение — RSTP, MSTP, или вообще L3 между свитчами (spine-leaf).
Попробуй сам
# 1. Посмотреть, поддерживает ли ваше ядро VLAN:
modprobe 8021q
lsmod | grep 8021q
# 2. Создать VLAN-интерфейс (нужен root):
sudo ip link add link eth0 name eth0.42 type vlan id 42
sudo ip link set eth0.42 up
ip -d link show eth0.42
# 3. Посмотреть на трафик VLAN'а:
sudo tcpdump -i eth0 -e -nn 'vlan 42'
# В другом терминале пинговать через VLAN-интерфейс:
ping -I eth0.42 ...
# 4. Удалить VLAN:
sudo ip link del eth0.42
# 5. Если у вас Linux bridge -- VLAN-aware mode:
sudo ip link add br-vlan type bridge vlan_filtering 1
sudo ip link set br-vlan up
sudo bridge vlan add vid 10 dev br-vlan self
# Полноценный программный свитч с VLAN-support
# 6. В Docker -- посмотреть, какие сети есть:
docker network ls
docker network inspect bridge # Docker bridge -- свой broadcast domain без VLAN
Самое наглядное: создать VLAN-интерфейс и снять tcpdump на физическом интерфейсе с фильтром vlan — вы увидите кадры с тегом и сможете руками разобрать структуру.