%20%D1%81%20NAT%20%D0%B8%20%D0%BC%D0%BE%D1%81%D1%82%D0%BE%D0%BC%20%D0%B4%D0%BB%D1%8F%20%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85%20%D0%BC%D0%B0%D1%88%D0%B8%D0%BD.png)
Моя установка:
В этой конфигурации есть только одна физическая машина — хост-система для виртуальных машин (ВМ) с двумя сетевыми адаптерами.
Одна сетевая карта (eth0) подключена к внутренней сети (подсеть LAN, например, 10.xxx/24) и должна использоваться для внутреннего трафика.
Другой сетевой адаптер (eth1) подключен к публичному Интернету (он имеет настроенный публичный маршрутизируемый IP). Это подключение будет использоваться для переадресации трафика публичного Интернета на внутренние IP-адреса виртуальных машин (входящий трафик) и для предоставления виртуальным машинам доступа к публичному Интернету (исходящий трафик) через NAT.
Виртуальные машины используют IP-адреса в локальной подсети (10.xxx/24, как и eth0)
У меня есть устройство моста (br0), настроенное для виртуальных сетевых интерфейсов виртуальных машин (vnet0, vnet1, ...) и LAN-NIC (eth0). Это означает:
- br0 имеет IP-адрес в подсети LAN (10.xxx/24)
- eth0 добавлен в мост
- vnet0, vnet1, ... (используемые виртуальными машинами) динамически добавляются к мосту
Проблемы
Связь внутри локальной сети работает нормально. Также 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
Тогда как yyy102 — это общедоступный маршрутизируемый 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:
- "FORWARD" (обычный) - я принимаю их там (-j ACCEPT, счетчик увеличивается)
- "PREROUTING" (nat) - я принимаю их там (политика ПРИНЯТЬ, счетчик увеличивается)
- "POSTROUTING" (nat) - Они соответствуют правилу SNAT
Но, похоже, не все пакеты доходят до 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
- IP: yyy126 — наш маршрутизатор для публичного Интернета.
- IP: yyy102 — публичный IP хост-компьютера
- IP: 10.xx11 — это LAN IP хост-машины.
- ПОДСЕТЬ: 10.xx0/24 — это локальная сеть
- ПОДСЕТЬ: yyy96/27 — это публичная IP-подсеть
Конфигурация сетевой карты:
# 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»:
# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
решение1
Проверьте, что ваши виртуальные машины имеют IP-адреса в диапазоне 10.xxx/24 (маска сети 255.255.255.0)
Установите 10.xx11 (IP-адрес br0) в качестве шлюза по умолчанию для ваших виртуальных машин.
Включить переадресацию IP на физическом хосте
Включите SNAT с помощью:
iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102
решение2
iptables -t nat -I POSTROUTING -s 10.xxx/24 ! -d 10.xxx/24 -j SNAT --to-source yyy102
это должно быть изменено на
iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102
Согласно вашему первому правилу, должны обрабатываться только пакеты с назначением на 10.xxx. Так что насчет трафика извне в вашу сеть? (источник - со всего мира, назначение - ваш публичный IP :)
Как настроить систему для вывода NAT-пакетов с публичным IP-адресом в качестве исходного адреса для отправки через правильный сетевой адаптер (eth1)?
читайте выше. Просто измените правило NAT.
Нужно ли мне как-то добавлять eth1 к мосту (br0)? Если да, то как правильно назначить публичный IP-адрес? Обычно IP-адрес нужно настроить на устройстве моста. Нужно ли мне назначать псевдоним мосту (публичный IP на br0:0)?
Ни в коем случае, если вы не знаете, что и почему вы это делаете. Разделяйте внутренние и внешние интерфейсы. Разрешите только маршрутизацию.
Я описал вам конфигурацию live (production) более 5 лет. Работает гладко для 3 хост-серверов и 25 виртуальных машин, включая мостовые соединения через туннели openvpn.
решение3
Пост Сильвио помог мне заставить работать похожую конфигурацию. В дополнение к его посту, вот пара вещей, которые мне также нужно было сделать.
В новых версиях ядер Linux (например, Redhat 7) вам потребуется включить модуль ядра bridge:
modprobe br_netfilter
а затем, чтобы сделать это изменение постоянным при перезапусках сервера, добавьте ту же строку в файл с именем /etc/modules-load.d/.conf
После включения 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
Вместо 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