Назад | Перейти на главную страницу

Маршрутизация Linux с двумя сетевыми картами (локальная сеть против Интернета) с NAT и мостом для виртуальных машин

Моя настройка:

В этой настройке есть только одна физическая машина, хост-система для виртуальных машин (ВМ) с двумя сетевыми адаптерами.

Один сетевой адаптер (eth0) подключен к внутренней сети (подсети LAN, например, 10.x.x.x / 24) и должен использоваться для внутреннего трафика.

Другой сетевой адаптер (eth1) подключен к общедоступному Интернету (для него настроен общедоступный маршрутизируемый IP-адрес). Это соединение должно использоваться для перенаправления общедоступного интернет-трафика на внутренние IP-адреса виртуальных машин (входящий трафик) и для разрешения виртуальным машинам доступа к общедоступному интернету (исходящий трафик) через NAT.

Виртуальные машины используют IP-адреса в подсети LAN (10.x.x.x / 24, то же, что и eth0)

У меня есть мостовое устройство (br0), настроенное для виртуальных сетевых интерфейсов виртуальных машин (vnet0, vnet1, ...) и LAN-NIC (eth0). Это значит:

Проблемы

Связь внутри LAN работает нормально. Также VM-Host доступен через общедоступный IP-адрес и имеет доступ в Интернет.

Моя проблема заключается в настройке NAT, позволяющей виртуальным машинам также получать доступ к общедоступному Интернету.

Я пробовал использовать простое (S) правило NAT:

iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102

В то время как y.y.y.102 - это общедоступный маршрутизируемый IP-адрес второй сетевой карты (eth1).

Я обнаружил, что мне нужно включить ip_forward и bridge-nf-call-iptables:

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

В противном случае пакеты с мостом не будут обрабатываться iptables.

Теперь пакеты от виртуальных машин, похоже, проходят через следующие цепочки iptables:

Но не все пакеты, кажется, прибывают в PRE / POSTROUTING по какой-либо причине, которую я пока не мог понять.

Однако интереснее tcpdump -i eth0 vs. tcpdump -i eth1 покажите, что пакеты (я пытался пропинговать внешний IP-адрес из виртуальной машины), похоже, отправляются через неправильный интерфейс eth0 (= LAN-NIC). Было применено даже правило NAT, поэтому адрес источника был изменен на IP-адрес другого сетевого адаптера (eth1).

Вопросы:

Как я могу настроить систему для вывода пакетов с NAT с общедоступным IP-адресом в качестве адреса источника для отправки через правильный сетевой адаптер (eth1)?

Мне как-то нужно добавить eth1 в мост (br0)? Если да, как мне правильно назначить общедоступный IP-адрес? Обычно IP-адрес необходимо настроить на мостовом устройстве. Нужно ли назначать мосту псевдоним (общедоступный IP-адрес на br0: 0)?

Детали конфигурации

Конфигурация маршрутизации в хост-системе:

# ip r
default via y.y.y.126 dev eth1
10.x.x.0/24 dev br0  proto kernel  scope link  src 10.x.x.11
y.y.y.96/27 dev eth1 proto kernel  scope link  src y.y.y.102

Конфигурация сетевой карты:

# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.x.x.11  netmask 255.255.255.0  broadcast 10.x.x.255
        inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
        ether ##:##:##:##:##:##  txqueuelen 0  (Ethernet)
        RX packets 2139490  bytes 243693436 (232.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29085  bytes 2398024 (2.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
        ether ##:##:##:##:##:##  txqueuelen 1000  (Ethernet)
        RX packets 2521995  bytes 290600491 (277.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 383089  bytes 48876399 (46.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device memory 0xdfa60000-dfa7ffff

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet y.y.y.102  netmask 255.255.255.224  broadcast y.y.y.127
        inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
        ether ##:##:##:##:##:##  txqueuelen 1000  (Ethernet)
        RX packets 2681476  bytes 597532550 (569.8 MiB)
        RX errors 0  dropped 130  overruns 0  frame 0
        TX packets 187755  bytes 21894113 (20.8 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device memory 0xdfa00000-dfa1ffff

Конфигурация моста:

# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.002590eb1900       no              eth0
                                                        vnet0

И правила iptables:

# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  723  106K DROP       udp  --  *      *       y.y.y.0/24           0.0.0.0/0            udp spt:5404
  586 40052 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    5   420 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
    2   458 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4
    2   458 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1343  173K ACCEPT     tcp  --  *      *       10.x.x.2             0.0.0.0/0            tcp spt:3389
 1648  127K ACCEPT     tcp  --  *      *       0.0.0.0/0            10.x.x.2             tcp dpt:3389
   18  1040 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4
   18  1040 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 525 packets, 84016 bytes)
 pkts bytes target     prot opt in     out     source               destination


# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 13 packets, 1218 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 5 packets, 420 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 13 packets, 880 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 14 packets, 920 bytes)
 pkts bytes target     prot opt in     out     source               destination
    5   300 SNAT       all  --  *      *       10.x.x.0/24          !10.x.x.0/24           to:y.y.y.102

А вот перехваченный пакет с NAT (ping от ВМ) на сетевой карте:

# tcpdump -i eth0
12:53:55.243350 IP y.y.y.102 > y.y.y.110: ICMP echo request, id 2, seq 5, length 40

Вывод "ip rule":

# ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
  1. Убедитесь, что ваши виртуальные машины имеют IP-адреса на 10.x.x.x / 24 (сетевая маска 255.255.255.0)

  2. Установите 10.x.x.11 (IP-адрес br0) в качестве шлюза по умолчанию для ваших виртуальных машин.

  3. Включить переадресацию IP на физическом хосте

  4. Включите SNAT с помощью:

    iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102
    

iptables -t nat -I POSTROUTING -s 10.x.x.x / 24! -d 10.x.x.x / 24 -j SNAT --to-source г.г.г.102

это должно быть изменено на

iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102

Согласно вашему первому правилу, должны обрабатываться только пакеты с адресатом 10.x.x.x. Итак, как насчет внешнего трафика в вашу сеть? (источник - со всего мира, пункт назначения - ваш публичный IP :)

Как я могу настроить систему для вывода пакетов с NAT с общедоступным IP-адресом в качестве адреса источника для отправки через правильный сетевой адаптер (eth1)?

читайте выше. Просто измените правило NAT.

Мне как-то нужно добавить eth1 в мост (br0)? Если да, как мне правильно назначить общедоступный IP-адрес? Обычно IP-адрес необходимо настроить на мостовом устройстве. Нужно ли назначать мосту псевдоним (общедоступный IP-адрес на br0: 0)?

Ни в коем случае, если вы не знаете, что и почему вы это делаете. Держите внутренние и внешние интерфейсы отдельно. Разрешить только маршрутизацию.

Я описал вами конфигурацию вживую (производственную) более 5 лет. Бесперебойная работа для 3 хост-серверов и 25 виртуальных машин, включая мостовые соединения через туннели openvpn.

Сообщение Сильвио помогло мне получить аналогичную конфигурацию. В дополнение к его сообщению, вот еще несколько вещей, которые мне нужно было сделать.

  1. В более новых версиях ядер Linux (например, Redhat 7) вам нужно будет включить модуль ядра моста:

    modprobe br_netfilter
    

а затем, чтобы сделать это изменение постоянным при перезапуске сервера, добавьте ту же строку в файл с именем /etc/modules-load.d/.conf

  1. После того, как я включил br_netfilter, мне также пришлось включить правила пересылки iptable для виртуальных машин, например:

    iptables -I FORWARD -d 10.x.x.x/24 -j ACCEPT
    iptables -I FORWARD -s 10.x.x.x/24 -j ACCEPT
    
  2. Вместо SNAT я использовал правило маскарада, поскольку мне нужен был только один маршрут в пределах объекта размещения сервера.

    iptables -t nat -A POSTROUTING -s <single-local-vm-ip>/32 -d <my-destination-subnet>/24 -p tcp -j MASQUERADE --to-ports 1024-65535