Skip to content

KVM VPS на Proxmox за NAT с пробросом портов и DHCP

Часто, когда сервер арендуется у какого-либо хостинг-провайдера, к нему прилагается от одного до нескольких IP-адресов. Если сервер “каноничный” и все сервисы устанавливаются прямо на ОС, деля ресурсы между собой как придется, то данной проблемы может и не возникнуть. Но если же планируется четкое разделение ресурсов сервера посредством виртуализации, то в какой-то момент может появиться надобность либо в дополнительных IP-адресах, либо в организации NAT и пробросе портов. Если, конечно, сервисы смотрят наружу.

Note

Пост обновлён 07.03.2023 с целью актуализации.

Warning

Данный пост частично потерял актуальность. Принципы описанные в нём всё ещё работают - аналогичным образом недавно настраивался PVE 9+. Но применять его в режиме пошаговой инструкции не стоит, т.к. различные детали вроде сохранения файрвола между перезапусками изменились, а также часть настроек уже лучше делать средствами PVE или в других файлах.

Сетевой мост (Bridge)

Организовать NAT для нескольких виртуальных машин довольно просто. В Proxmox “из коробки” доступно создание сетевых мостов (хотя удобнее это делать сразу в конфиге, т.к. PVE съедает комментарии и меняет форматирование). Для наших целей создадим бридж vmbr1 с ip-адресом 192.168.1.1 и стандартной маской 255.255.255.0 , которая предоставит в наше распоряжение все 256 адресов.

Proxmox. Сетевой мост.
Proxmox. Сетевой мост.

После того как он заработает, идем в /etc/network/interfaces и немного правим конфигурацию созданного бриджа:

auto vmbr1
iface vmbr1 inet static
        address 192.168.1.1
        netmask 255.255.255.0
        bridge_ports none
        bridge_stp off
        bridge_fd 0
        post-up echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up iptables -t nat -A POSTROUTING -s '192.168.1.0/24' -o vmbr0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '192.168.1.0/24' -o vmbr0 -j MASQUERADE

Здесь мы разрешаем виртуальным машинам на vmbr1 подключаться к интернету через vmbr0 . Стоит отметить, что последние две строчки с добавлением и удалением правил файрвола могут отличаться по причине того, что в моем случае главным интерфейсом сервера является бридж vmbr0 и сеть настраивается на него. У меня он работает для получения несколькими виртуальными машинами реальных IP-адресов от внешнего гейта. Если у вас сеть настраивается на eth0, то он и должен быть вместо vmbr0. В остальном разницы никакой нет.
Также, включать ip_forward можно в /etc/sysctl.conf.

net.ipv4.ip_forward=1

Проброс портов (Port forwarding)

Далее, если необходимо пробросить определенные порты на нужные виртуальные машины. Это можно сделать с помощью iptables:

iptables -A PREROUTING -t nat -i vmbr0 -p tcp -d %ext_ip_on_vmbr0% --dport %ext_port% -j DNAT --to %int_ip_on_vmbr1%:%int_port%

Где

%ext_ip_on_vmbr0% — внешний IP-адрес, который находится на vmbr0 . Если не указать этого параметра, то порт будет пробрасываться со всех адресов на этом бридже.
%ext_port% — внешний порт по которому будут обращаться к серверу из интернета.
%int_ip_on_vmbr1% — внутренний IP виртуальной машины на vmbr1 .
%int_port% — внутренний порт, на котором будет работать сервис в виртуальной машине.

Ну и после применения правил для нужных портов можно посмотреть все ли правильно:

iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere xxx.yyy.ru tcp dpt:33122 to:192.168.1.2:22
DNAT tcp -- anywhere xxx.yyy.ru tcp dpt:33222 to:192.168.1.3:22

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.1.0/24 anywhere

Сохранение правил файрвола

Если все верно — остается сделать так, чтобы при перезагрузке правила восстанавливались.

Новый вариант

Используйте пакет iptables-persistent.

Старый вариант

Для этого можно воспользоваться iptables-save и скриптами инициализации сети.

iptables-save > /etc/iptables.up.rules

Создадим скрипт загрузки правил:

nano /etc/network/if-pre-up.d/iptables

И впишем в него команду загрузки правил из сохраненного ранее файла:

#!/bin/bash
/sbin/iptables-restore < /etc/iptables.up.rules

Не забудем дать права на исполнение этому файлу:

chmod +x /etc/network/if-pre-up.d/iptables

Более простой альтернативой будет установка пакета iptables-persistent , который сам будет сохранять правила при выключении или перезагрузке, а при загрузке загружать их снова. Более подробно - здесь (англ).

Все. Проброс портов работает.

Настройка сети в гостевой ОС

Ручная настройка (static)

Наиболее простым вариантом является задание адреса виртуальной машины вручную. В самых простых случаях, можно воспользоваться им.

Для этого в настройках гостевой ОС прописываем такие параметры:

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
address 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1

address - ip-адрес данной машины. Естественно, у всех машин этой подсети он должен быть разный.

netmask - это маска подсети. Точно такая же как указывалось при создании сетевого моста.

gateway - ip-адрес, на котором сидит сам хост, через который будет происходить роутинг во внешнюю сеть.

Динамическая конфигурация (DHCP)

Чтобы не настраивать сеть вручную можно установить DHCP-сервер. Особенно это будет полезно, если в подсети будет находиться много виртуальных машин - настраивать сеть вручную на каждой не придётся.

Новый вариант: dnsmasq

Устанавливаем сервер:

apt-get install dnsmasq

Настраиваем конфигурацию в /etc/dnsmasq.conf:

# Disable DNS
port=0
# Listen NAT interface
interface=vmbr1
# Strictly binding to the bridge
bind-interfaces
# Optionally set a domain name
#domain=example.org
# Set default gateway
dhcp-option=3,192.168.100.1
# Set DNS servers to announce
dhcp-option=6,8.8.8.8
# Push default route
#dhcp-option=121,0.0.0.0/0,192.168.1.1
# Dynamic range of IPs to make available to LAN PC and the lease time.
# Ideally set the lease time to 5m only at first to test everything works okay before you set long-lasting records.
dhcp-range=192.168.1.10,192.168.1.100,720h
# Provide IPv6 DHCP leases, the range is constructed using the network interface as prefix
#dhcp-range=::f,::ff,constructor:enp0s0
# If you’d like to have dnsmasq assign static IPs to some clients, bind the LAN computers NIC MAC addresses:
#dhcp-host=aa:bb:cc:dd:ee:ff,192.168.1.50
#dhcp-host=aa:bb:cc:ff:dd:ee,192.168.1.51

Старый вариант: isc-dhcp-server

Warning

Дополнение от 07.03.2023

Использование этого сервера больше не рекомендуется. За годы он показал себя плохо вызывая различные проблемы, а последний раз после его установки он вообще отказывался работать.

Устанавливаем сервер:

apt-get install isc-dhcp-server

В файле /etc/dhcp/dhcpd.conf большинство параметров можно оставить неизменными, однако директиву authoritative; нужно раскомментировать. Также может быть полезным увеличить время выдачи адресов с помощью параметров:

default-lease-time 40320;
max-lease-time 40320;

И, самое главное, нужно описать настройки нашей подсети:

# NAT subnet on vmbr1
subnet 192.168.1.0 netmask 255.255.255.0 {
 range 192.168.1.2 192.168.1.254;
 option routers 192.168.1.1;
 option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Здесь range - это диапазон адресов, которые будет выдавать DHCP-сервер. domain-name-servers - это DNS-сервера, которые будут использоваться на гостевых машинах. В данном примере это Google Public DNS.

Далее в файле /etc/default/isc-dhcp-server настраиваем какие интерфейсы будет слушать наш сервер:

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="vmbr1"

Для надёжности можно ещё прикрыть его файрволом от запросов извне.

После настройки перезапускаем DHCP

service isc-dhcp-server restart

Заключение

Настройка закончена. Теперь гостевые машины будут получать настройки сети автоматически во время установки ОС.