Подробный гайд: Практикумы по настройке виртуальных сетей в Linux
Цель:
Пошаговое освоение механизмов сетевой виртуализации Linux: network namespaces, veth, bridge, VLAN, маршрутизация и NAT. Все примеры работают на современных дистрибутивах (Ubuntu 22.04/24.04, Debian 12, Fedora 39+, RHEL 9) с iproute2 ≥ 5.15.
Требования и подготовка
| Компонент | Проверка |
|---|---|
| Права | sudo -i или работа под root |
iproute2 |
ip -V |
bridge (утилита) |
bridge -V (обычно входит в iproute2) |
iptables/nftables |
iptables -V или nft -v |
| Ядро ≥ 5.10 | uname -r |
Все команды выполняются от root. Для отладки используйте set -x в bash или выводите ip -d link, bridge -d vlan, iptables -t nat -L -n -v.
Базовые концепции
| Механизм | Назначение | Аналог в физическом мире |
|---|---|---|
network namespace |
Изолированный сетевой стек (интерфейсы, маршруты, firewall, ARP) | Отдельный компьютер |
veth pair |
Виртуальный кабель с двумя концами | Патч-корд между свитчем и ПК |
bridge |
Виртуальный коммутатор L2 | Ethernet-свитч |
VLAN (802.1Q) |
Логическая сегментация на одном канале | Виртуальные LAN на свитче |
routing/NAT |
L3-связность и трансляция адресов | Роутер с маскойрадингом |
Практикум 1: veth и сетевые пространства
Цель:
Создать два изолированных сетевых пространства и связать их виртуальным кабелем.
Шаги
# 1. Создаём пространства имён
ip netns add ns1
ip netns add ns2
# 2. Создаём пару veth
ip link add veth-ns1 type veth peer name veth-ns2
# 3. Размещаем концы в разных namespace
ip link set veth-ns1 netns ns1
ip link set veth-ns2 netns ns2
# 4. Поднимаем интерфейсы и назначаем IP
ip netns exec ns1 ip addr add 10.10.1.1/24 dev veth-ns1
ip netns exec ns1 ip link set dev veth-ns1 up
ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip addr add 10.10.1.2/24 dev veth-ns2
ip netns exec ns2 ip link set dev veth-ns2 up
ip netns exec ns2 ip link set lo up
Проверка
ip netns exec ns1 ping -c 3 10.10.1.2
ip netns exec ns2 arp -n
Очистка
ip netns del ns1
ip netns del ns2
Практикум 2: Linux Bridge (виртуальный свитч)
Цель:
Объединить несколько namespace через общий мост L2.
Шаги
# 1. Создаём bridge
ip link add br-lab type bridge
ip link set br-lab up
# 2. Создаём veth-пары для двух namespace
ip link add veth1a type veth peer name veth1b
ip link add veth2a type veth peer name veth2b
# 3. Привязываем "хостовые" концы к мосту
ip link set veth1a master br-lab
ip link set veth2a master br-lab
ip link set veth1a up
ip link set veth2a up
# 4. Размещаем вторые концы в namespace
ip netns add nsA
ip netns add nsB
ip link set veth1b netns nsA
ip link set veth2b netns nsB
# 5. Настраиваем IP внутри namespace
ip netns exec nsA ip addr add 192.168.100.10/24 dev veth1b
ip netns exec nsA ip link set dev veth1b up
ip netns exec nsA ip link set lo up
ip netns exec nsB ip addr add 192.168.100.20/24 dev veth2b
ip netns exec nsB ip link set dev veth2b up
ip netns exec nsB ip link set lo up
Проверка
# L2-связность
ip netns exec nsA ping -c 2 192.168.100.20
# Состояние моста
bridge link show
ip -d link show br-lab
Очистка
ip link del br-lab
ip netns del nsA
ip netns del nsB
Практикум 3: VLAN на мосту (802.1Q)
Цель:
Сегментировать трафик внутри одного bridge с помощью тегов VLAN.
Подготовка (продолжаем с предыдущего bridge)
# Включаем фильтрацию VLAN на мосту
ip link set br-lab type bridge vlan_filtering 1
# Добавляем VLAN 10 для veth1a, VLAN 20 для veth2a
bridge vlan add dev veth1a vid 10 pvid untagged
bridge vlan add dev veth2a vid 20 pvid untagged
# Убираем дефолтный VLAN 1 (опционально, но рекомендуется)
bridge vlan del dev veth1a vid 1
bridge vlan del dev veth2a vid 1
pvid означает, что входящий безтеговый трафик автоматически помечается указанным VID. untagged означает, что при выходе тег снимается (как на access-порту свитча).
Проверка изоляции
# Добавляем третий namespace в VLAN 10
ip link add veth3a type veth peer name veth3b
ip link set veth3a master br-lab
ip link set veth3a up
ip link set veth3b netns nsC # предварительно: ip netns add nsC
ip netns exec nsC ip addr add 192.168.100.30/24 dev veth3b
ip netns exec nsC ip link set dev veth3b up
ip netns exec nsC ip link set lo up
bridge vlan add dev veth3a vid 10 pvid untagged
# Ping между VLAN 10 должен работать, между 10↔20 — нет
ip netns exec nsA ping -c 2 192.168.100.30 # OK
ip netns exec nsA ping -c 2 192.168.100.20 # Fail (разные VLAN)
Просмотр таблицы VLAN
bridge vlan show
Очистка VLAN
bridge vlan del dev veth1a vid 10
bridge vlan del dev veth2a vid 20
bridge vlan del dev veth3a vid 10
ip link del br-lab
ip netns del nsA nsB nsC
Практикум 4: Маршрутизация и NAT (выход в интернет)
Цель:
Настроить шлюз по умолчанию для namespace и маскарадинг через физический интерфейс хоста.
Шаги
# 1. Включаем IP-форвардинг
sysctl -w net.ipv4.ip_forward=1
# Для персистентности: echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
# 2. На хосте: назначаем IP на bridge (он будет шлюзом)
ip addr add 192.168.100.1/24 dev br-lab
# 3. В namespace: добавляем маршрут по умолчанию
ip netns exec nsA ip route add default via 192.168.100.1
ip netns exec nsB ip route add default via 192.168.100.1
# 4. Включаем NAT (замените eth0 на ваш внешний интерфейс)
EXTERNAL_IF=$(ip route get 8.8.8.8 | awk '{print $5; exit}')
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o "$EXTERNAL_IF" -j MASQUERADE
# Разрешаем форвардинг для этой подсети
iptables -A FORWARD -i br-lab -o "$EXTERNAL_IF" -j ACCEPT
iptables -A FORWARD -o br-lab -i "$EXTERNAL_IF" -m state --state RELATED,ESTABLISHED -j ACCEPT
Проверка
ip netns exec nsA ping -c 2 8.8.8.8
ip netns exec nsA curl -s ifconfig.me
Современная альтернатива iptables → nftables
nft add table inet nat_lab
nft add chain inet nat_lab postrouting { type nat hook postrouting priority 100 \; }
nft add rule inet nat_lab postrouting ip saddr 192.168.100.0/24 oifname "$EXTERNAL_IF" masquerade
Очистка NAT
iptables -t nat -F
iptables -F FORWARD
Практикум 5: Персистентная настройка через systemd-networkd
Временные настройки исчезают после перезагрузки. Для production используйте systemd-networkd или NetworkManager.
Пример конфигурации
# /etc/systemd/network/10-br-lab.netdev
[NetDev]
Name=br-lab
Kind=bridge
# /etc/systemd/network/10-br-lab.network
[Match]
Name=br-lab
[Network]
Address=192.168.100.1/24
IPForward=yes
# /etc/systemd/network/20-veth1a.netdev
[NetDev]
Name=veth1a
Kind=veth
Peer=veth1b
# /etc/systemd/network/20-veth1a.network
[Match]
Name=veth1a
[Network]
Bridge=br-lab
# /etc/systemd/network/30-nsA.network
[Match]
Name=veth1b
[Network]
Address=192.168.100.10/24
Gateway=192.168.100.1
# Перенос интерфейса в namespace автоматически
# /etc/systemd/network/30-nsA.link
[Match]
MACAddress=... # или использовать Name=
[Link]
NamespacePath=/run/netns/nsA
systemd-networkd не создаёт netns автоматически. Рекомендуется запускать ip netns add nsA через systemd сервис с Before=systemd-networkd.service.
Применение
systemctl enable --now systemd-networkd
networkctl reload
Отладка и чек-лист
| Симптом | Команда проверки | Решение |
|---|---|---|
ping: connect: Network is unreachable |
ip netns exec ns ip route |
Добавить маршрут или поднять lo |
Destination Host Unreachable |
bridge link, ip -d link |
Проверить UP состояние и master |
| Нет интернета | iptables -t nat -L -n -v, sysctl net.ipv4.ip_forward |
Включить форвардинг, проверить NAT правило и внешний интерфейс |
| VLAN не изолирует | bridge vlan show |
Убедиться в vlan_filtering 1 и корректных pvid |
| Конфликт MAC | ip -d link show |
Явно задать MAC: ip link set dev X address aa:bb:cc:dd:ee:ff |
Полезные команды:
ip netns list
ip netns exec <ns> bash # интерактивная сессия в namespace
watch -n 1 'bridge vlan show; echo; ip link show'
tcpdump -i br-lab -nn -e vlan # анализ тегов и MAC
Куда двигаться дальше
| Тема | Инструменты | Описание |
|---|---|---|
| Open vSwitch | ovs-vsctl, ovs-dpctl |
Production-grade виртуальный свитч с OpenFlow |
| CNI (Container Network Interface) | bridge, flannel, calico, cilium |
Сетевая модель Kubernetes/контейнеров |
| eBPF/XDP | cilium, xdp-tools |
Программируемый датаплэн в ядре |
| Автоматизация | Ansible, netplan, nmcli |
Declarative-конфигурация в production |
Шаблон bash-скрипта для быстрого развёртывания
#!/usr/bin/env bash
set -euo pipefail
NS="ns1 ns2"
BR="br-vlab"
SUBNET="10.99.0.0/24"
GW="10.99.0.1"
cleanup() { ip link del "$BR" 2>/dev/null || true; for n in $NS; do ip netns del $n 2>/dev/null || true; done; }
trap cleanup EXIT
cleanup
sysctl -w net.ipv4.ip_forward=1 >/dev/null
ip link add "$BR" type bridge && ip link set "$BR" up
ip addr add "$GW/24" dev "$BR"
i=2
for n in $NS; do
ip netns add $n
ip link add veth-h-$n type veth peer name veth-$n
ip link set veth-h-$n master "$BR" && ip link set veth-h-$n up
ip link set veth-$n netns $n
ip netns exec $n ip addr add "10.99.0.$i/24" dev veth-$n
ip netns exec $n ip link set dev veth-$n up
ip netns exec $n ip link set lo up
ip netns exec $n ip route add default via "$GW"
i=$((i+1))
done
echo "Сеть готова. Тест: ip netns exec ns1 ping -c 2 10.99.0.3"
Совет:
Все временные объекты удаляйте после экспериментов (ip link del, ip netns del, iptables -F). В production используйте декларативные конфигурации (netplan, systemd-networkd, NetworkManager) и CI/CD для валидации.