Данная статья посвящена вопросам правильной настройки IPv4 и IPv6 в сетевых конфигурациях, аналогичных тем, что применяются в Hetzner на базе KVM (так же потенциально подходит для любых других HVM, и для Xen).

Примеры конфигурации интерфейсов основаны на ifup, так как на хосте и большинстве виртуалок у меня Ubuntu. Гайд по IPv4 местами основан на статье из Hetzner Wiki, вопросы IPv6 я, в основном, гуглил.


Стартовые условия



У данного хостера вы сходу получаете один IPv4 адрес. Дополнительно к нему вы можете попросить/приобрести до трех IPv4-адресов и блоки подсетей. В данном примере будет рассматриваться следующую конфигураця:

IP хоста: 123.45.12.48
Шлюз: 123.45.12.1
Дополнительные IP: 123.45.53.11, 123.45.53.12, 123.45.53.13
Дополнительная подсеть: 123.45.90.112/29

Hetzner шлет все пакеты на MAC-адрес первого (и, обычно, единственного) интерфейса eth0, и ожидает, что все исходящие пакеты будут уходить с этого же MAC-адреса. Через саппорт можно попросить поставить другие MAC-адреса для дополнительных «поштучных» IP-адресов, что позволяет закинуть vnet* интерфейсы KVM-ок в один мост с eth0, но эту конфигурацию я рассматривать не буду.

Итак, что необходимо получить в итоговой конфигурации:
  • отсутствие NAT, каждая VM получает минимум один публичный IP-адрес;
  • хост занимается всем роутингом:
    • трафик между разными VM;
    • трифик между VM и интернетом;
    • централизовано фильтрует пакеты в iptables (можно ограничивать взаимодействие VM друг с другом и интернетом)
  • IP-адреса из выделенных подсетей не теряются (в демонстрационной подсети адреса 123.45.90.112 и 123.45.90.119 обычным методом использовать нельзя – это адреса сети и броадкаста)


Для настройки сети понадобятся следующие пакеты: bridge-utils, dhcp3-server, iptables, iproute2.

Настраиваем основной интерфейс хоста


В /etc/network/interfaces необходимо описать eth0 следующим образом:
auto eth0
iface eth0 inet static
  address 123.45.12.48
  netmask 255.255.255.255
  gateway 123.45.12.1
  pointopoint 123.45.12.1

Маска 255.255.255.255 означает, что все исходящие пакеты б��дут уходить на шлюз, через опцию pointopoint ifup определяет, что гейтвей технически находится на этом же интерфейсе (куда он, естественно, иначе не попадает из-за ограниченной маски). Это эквивалентно следующим правилам роутинга:
123.45.12.1 dev eth0 proto kernel scope link src 123.45.12.48
default via 123.45.12.1 dev eth0 metric 100


Настраиваем по мосту для VM



Поскольку в задачу входит ограничение трафика между VM, их нельзя засунуть в один мост. Для каждого дополнительного IP-адреса и каждого адреса из подсети /29 необходимо описать отдельный мост:
auto br112
br112 iface inet static
  address 172.30.112.1
  netmask 255.255.255.0
  pre-up brctl addbr br112
  post-up route add -host 123.45.90.112 br112
  post-down brctl delbr br112

Каждый мост будет называться br<xxx>, где xxx – последний байт IPv4 адреса. На нем поднимается приватный IPv4 адрес из 172.30.xx.0/24 (зачем это надо – описано далее), тут же в описании интерфейса привязан brctl (создание моста в pre-up, уничтожение в post-down), и настраивается роутинг (публичный IP-адрес определяется на этом мосту).

Абсолютно идентично описываются br11, br12, br13, и br113–br119.

Настраиваем DHCP



Так как pointopoint конфигурация затруднена в процессе инсталляции некоторых OS, на каждом мосту для VM будет работать DHCP-сервер, который даст базовую конфигурацию IPv4, достаточную для завершения установки.

Модифицируем конфиг dhcp3 в /etc/dhcp3/dhcpd.conf следующим образом:
authoritative;
default-lease-time 3600;
max-lease-time 3600;
ddns-update-style ad-hoc;
log-facility local7;
use-host-decl-names on;

option subnet-mask 255.255.255.0;
option domain-name "lan";
option domain-name-servers xx.yy.100.100, xx.yy.99.99, xx.yy.98.98; <-- заменяем на актуальные DNS–серверы

subnet 172.30.11.0 netmask 255.255.255.0 {
    option routers 172.30.11.1;
    range 172.30.11.10 172.30.11.200;
}

subnet 172.30.12.0 netmask 255.255.255.0 {
    option routers 172.30.12.1;
    range 172.30.12.10 172.30.12.200;
}

subnet 172.30.13.0 netmask 255.255.255.0 {
    option routers 172.30.13.1;
    range 172.30.13.10 172.30.13.200;
}

subnet 172.30.112.0 netmask 255.255.255.0 {
    option routers 172.30.112.1;
    range 172.30.112.10 172.30.112.200;
}

...

subnet 172.30.119.0 netmask 255.255.255.0 {
    option routers 172.30.119.1;
    range 172.30.119.10 172.30.119.200;
}


Также объясняем, на каких интерфейсах dhcp3 должен работать: в файле /etc/default/dhcp3-server изменяем INTERFACES:
INTERFACES="br11 br12 br13 br112 br113 br114 br115 br116 br117 br118 br119"

После чего перезапускаем dhcp3:
/etc/init.d/dhcp3-server restart

Настройка iptables



#!/bin/sh
it="/sbin/iptables"

MY_NET="123.45.90.112/29 123.45.53.11/32 123.45.53.12/32 123.45.53.13/32"
MY_NET_DHCP="172.30.0.0/16"
HOST_IP="123.45.12.48"
MAIN_IF="eth0"

# INPUT
$it -F INPUT

$it -A INPUT -p udp --dport 67 -i br+ -j ACCEPT
# настраиваем другие политики INPUT
#$it -A INPUT -j DROP

# FORWARD
$it -F FORWARD

$it -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

for NET in $MY_NET; do
$it -A FORWARD -i br+ -o $MAIN_IF -s $NET -j ACCEPT # VM[fixed_ip] --> net
done

for NET in $MY_NET_DHCP; do
$it -A FORWARD -i br+ -o $MAIN_IF -s $NET -j ACCEPT # VM[dhcp] --> net
done

for SOURCE_NET in $MY_NET $MY_NET_DHCP; do
for DEST_NET in $MY_NET; do
$it -A FORWARD -i br+ -o br+ -s $SOURCE_NET -d $DEST_NET -j ACCEPT # VM <--> VM
done
done

for NET in $MY_NET; do
$it -A FORWARD -i $MAIN_IF -o br+ -d $NET -j ACCEPT # net --> VM
done
$it -A FORWARD -i $MAIN_IF -o gbr1 -d $MY_NET_PVT -j ACCEPT # net --> PVT

$it -P FORWARD DROP

# POSTROUTING
$it -t nat -F POSTROUTING
for NET in $MY_NET_DHCP; do
$it -t nat -A POSTROUTING -o $MAIN_IF -s $NET -j SNAT --to-source $HOST_IP # nat the dhcp
# NAT для приватных IP-адресов от DHCP
done

echo 1 > / proc/sys/net/ipv4/ip_forward


Настройка VM



Ну и последний этап – непосредственно настроить VM. Для libvirt/KVM описываем сеть через мост:
<interface type='bridge'>
  <source bridge='brXX'/>
  <model type='virtio'/>
</interface>


При этом, на первичной загрузке виртуалка получит приватный адрес от DHCP, а уже после установки необходимо зафиксировать на ней публичный IP:
auto eth0
iface eth0 inet static
  address 123.45.90.116
  netmask 255.255.255.255
  gateway 123.45.12.48
  pointopoint 123.45.12.48


Объем статьи вышел достаточно большой, так что про IPv6 напишу отдельно.