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

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

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

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

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

После того как он заработает, идем в /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 DNSport=0
# Listen NAT interfaceinterface=vmbr1
# Strictly binding to the bridgebind-interfaces
# Optionally set a domain name#domain=example.org
# Set default gatewaydhcp-option=3,192.168.100.1
# Set DNS servers to announcedhcp-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

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

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

aptitude 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

Заключение

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

30 комментариев

  • Да, год уже прошел с написания поста, но я сейчас наткнулся, это единственная статья с внятным объяснением, спасибо огромное

  • ❓ А как быть например если хост проксмока нее имеет прямого выхода в инет?
    Например с маршрутизатором с NAT.
    Пробрасывать порты на маршрутизаторе не сложно но как быть например что VNC консоли через веб запускаются на следующем свободном порту из диапазона 5900-6000. Как в таком случае пробросить?

    • Не до конца понял, но вам, очевидно, надо диапазон портов пробросить. Это уже легко загуглить по «iptables пробросить диапазон портов».

  • Добрый день! Случайно нашел вашу статью, где вы все просто и доходчиво объяснили. Однако у меня чего-то не заработало. Вот конфигурация бриджа
    auto vmbr1
    iface vmbr1 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    bridge_ports eth1
    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 MASQUERAD
    у меня главный интерфейс vmbr0 если его поставить мащине она есть в интернете, я хочу создать виртуальную машину которая будет одновременно и в локальной сети 192.168.1.0/24 и что б оона выходила в инет. Делал все по вашему описанию, только в бридже прописал еще eth1. Так как машина должна быть и в локальной сети. Но интернета у нее нету))) Если Вам не трудно направть меня по пправильному пути, а то я запутался. (

    • Если вам нужна виртуалка, которая будет торчать за NAT — тогда у вас как бы никаких проблем не будет, если сделаете всё точно по инструкции. Если же и без NAT и в локалке — тогда либо с подсетью, которая будет на одном бридже работать, либо у виртуалки два интерфейса — на внешний IP под vmbr0 и на локальный IP под vmbr1.

      • Здравстуйте еще раз. Спасибо за быстрый ответ). Мне нужна виртуалка, которая будет торчать за NAT и в локалке. Причем локалка также будет входить в мир. Я так понял, что мне прийдется сделать две виртуалки. Одну с двумя интерфейсами — на мир под vmbr0 и на локалку под vmbr1. На ней настроить шлюз для выхода локалки в мир. И другую на которой запустить базу и сервисы для локалки, которая также будет торчать в локалке и ходить в мир через шлюз. Я правильно вас понял? Если я создаю виртуалку под vmbr0 она сразу смотрит в мир. Мне нужна виртуалка которая смотрит в сеть и к ней можно б было подключиться извне для изменения настроек. Я думал если сделаю по инструкции, то разрешу виртуальным машинам на vmbr1 подключаться к интернету через vmbr0. Хотя я делаю по вашей инструкции и делал как описано в http://pve.proxmox.com/wiki/Network_Model#Masquerading_.28NAT.29. Моя виртуалка на vmbr1 в мир не ходит(((. Если меняю на vmbr0. Я сразу в интернете. Даже отключал eth1, хотя он здесь точно ни при чем. Никак не могу настроить ))). В Proxmox я новичок, всего неделю))). Хотя ихняя задумка мне нравится)

        • Я правильно вас понял?

          Нет! Перечитайте ответ еще раз, пожалуйста. Ключевые слова — «либо». То есть это разные варианты, а не всё в одном. Да и вы вообще что-то не то вычитали.

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

          Делаете так, как описано здесь и пробрасываете нужные порты с помощью iptables (Google). Тогда сможете подключиться к вашей виртуалке снаружи не выделяя ей отдельный IP. Данная инструкция именно о виртуалках за NAT — то есть, не имеющих своего IP.
          Чтобы виртуалка могла иметь доступ в интернет здесь используется маскарад (те два правила для iptables). Чтобы подключиться к ней снаружи — нужно пробросить порты (тот же самый гугл). Либо же вы можете просто с помощью того же SSH подключиться к ней с хоста — тогда не нужно пробрасывать порты.

          Никак не могу настроить ))). В Proxmox я новичок, всего неделю)))

          Неважно, сколько вы пользуетесь Proxmox VE. Вам нужно разобраться с сетью в Linux-системах.

          • Спасибо за ответ. Пошел читать инфу. В линуксе я тоже неделю))). Когда я делаю все по вашей инструкции у меня нету интернета на виртуальной машине, для простоты я на виртуалку винду накатил. Когда включаю на vmbr0, на виртуалке появляется интернет, но она висит в мире, и ее видно из интернета, она получает белый ip. По инструкции интернета нету))). Пока спасибо за информацию — буду искать инфу))). Если получится — отпишусь 😉

            • Значит, что-то в конфигурации не так, как описано. Только что повторял данную настройку на новом сервере.
              Удачи.

  • Обновил пост. Добавил информацию про пакет автоматически сохраняющий правила iptables и настройку DHCP-сервера.

  • Как настроить сеть, так чтобы VM со шлюзом общалась через eth0 с провайдером, через eth1 c локалкой, а также через третий мост с другими VM на proxmoxe?

    Настроил мосты! Все отлично работает! Только не могу теперь попасть в веб интерфейс самого proxmoxa, так как не открывается страница https://xx.xx.xx.yxx:8006, а если просто набрать xx.xx.xx.yxx то попадаю в веб интерфейс самой VM_101. Как разрешить ситуацию так, чтоб был доступ извне и к VM_101 и к веб интерфейсу самого proxmoxa?
    (VM_101 он же шлюз для локалки и других VM)

    PROXMOX
    /etc/network/interfaces
    # network interface settings
    auto lo
    iface lo inet loopback

    auto eth0
    iface eth0 inet manual

    auto eth1
    iface eth1 inet manual

    auto vmbr0
    iface vmbr0 inet static
    address xx.xx.xx.yxx
    netmask 255.255.255.0
    gateway xx.xx.xx.yx
    bridge_ports eth0
    bridge_stp off
    bridge_fd 0

    auto vmbr1
    iface vmbr1 inet static
    address 192.168.100.254
    netmask 255.255.255.0
    bridge_ports eth1
    bridge_stp off
    bridge_fd 0

    iface vmbr2 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    bridge_ports eth2
    bridge_stp off
    bridge_fd 0

    VM_101 он же шлюз для локалки и других VM

    /etc/network/interfaces

    # The loopback network interface
    auto lo
    iface lo inet loopback

    # The primary network interface
    auto eth1
    iface eth1 inet static
    address xx.xx.xx.yxx(тот же что и у vmbr0 proxmoxa)
    netmask 255.255.255.0
    network xx.xx.xx.0
    broadcast xx.xx.xx.255
    gateway xx.xx.xx.1
    dns-nameservers 89.28.1.1
    ###################################
    auto eth2
    iface eth2 inet static
    address 192.168.100.254
    netmask 255.255.255.0
    ##########################
    auto eth0
    iface eth0 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    pre-up iptables-restore < /etc/network/firewall.rules

    • Ну, вы немного упустили подробности про то, как у вас вообще выдаются адреса, например. Если взять тот же Hetzner, там есть два способа получить адреса:
      1. Вам выдаётся адрес через DHCP по MAC самим Hetzner’ом. Таких адресов может быть до пяти на сервер. Виртуалки, которые должны получать эти IP должны быть на том бридже, который настроен на основной адрес из них — адрес вашего хоста.
      2. Вы можете получить подсеть. Тогда вам нужно настроить отдельный мост под эту подсеть, самим хостом занять её первый адрес и остальным виртуалкам выдавать вручную или через DHCP адреса в этой подсети, а гейтом на виртуалках указывать адрес хоста в этой подсети. Таким образом в данной конфигурации у вас хост имеет два внешних адреса — свой изначальный из пункта 1 (такой там всегда один выдают) и первый адрес из подсети.

      Я прошу прощения, но не очень понял из ваших конфигов что и как должно быть. Также непонятно, сколько у вас адресов, чего вы хотите добиться — NAT или выдачи внешнего IP виртуальной машине.
      А если у вас вместо хоста отвечает виртуальная машина — значит вы либо что-то не так настроили — очевидность, но без подробностей сложно что-то сказать.

      Попробуйте обратиться на unixforum, например. Там есть специальные разделы и вам могут помочь достаточно быстро.

  • Добрый день , спасибо за вашу статью все получилось , но виртуалки имеющие адреса 192.168.1.XX спокойно пингуют хост машину 192.168.1.1 , но не видят друг друга. Подскажите как сконфигурировать так , чтобы машины могли соединять друг с другом как в локальной сети ?

    • Они и так должны соединяться, если висят на одном бридже.
      Возможно, у вас где-то слишком жестоко настроен файрвол: на хосте или на самих виртуалках.

  • Дмитрий

    Все сделал в соответсвии со статьей, получаю вот такую ошибку

    Job for isc-dhcp-server.service failed.See ‘systemctl status isc-dhcp-server.service’ and ‘journalctl -xn’ for details.

    • Очевидно, что по какой-то причине DHCP-сервер не может запуститься. В общем-то, в сообщении об ошибке и написано, куда можно посмотреть за причинами.

      • Чисто для информации:

        Я сам отказался со временем от ISC DHCP потому, что с ним очень много проблем.

        В посте уже есть обновлённая инструкция для другого сервера.

  • Виталий

    Отличная статья, у меня заработало. Делал первый раз.

  • Добрый день, а как сделать чтобы Виртуальные машины могли попадать на белый ip из внутренней сети. Мне нужно чтобы сервис был доступен по белому ip отовсюду.

    • Я не очень понимаю, что такое «белый IP из внутренней сети».
      К тому же, если вы хотите белый IP, то вам нужна не схема с NAT, которая тут описана.

  • Спасибо за статью. Но у меня есть 2 интернет канала с статическими айпи, как можно забалансить это все?
    Так же у меня на 3х виртуалках будут крутиться сайты, расскажите как это все забалансить и настроить? Может нужен статический белый айпи что бы сайты на виртуалках работали?

    • Про балансировку ничего не подскажу — не занимался этим.

      Может нужен статический белый айпи что бы сайты на виртуалках работали?

      В принципе ни то ни то не обязательно чтобы сайты работали, но вряд ли какой-то провайдер даст вам светить портами наружу через NAT, поэтому внешний (реальный/белый) IP нужен. Статический адрес не обязательно иметь, т.к. можно настроить динамический DNS. Но когда адрес статический и белый одновременно — это проще всего.

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

    • виртмашина не видит бридж при подключении к нему

      Как можно подключаться к бриджу, который не виден? Вы очень непонятно описываете проблему.

      DHCP сервер тоже результата не дал — машина тупо не получает адрес.

      Ну вот на этом этапе уже можно заподозрить, что что-то сделано не так.

      это работает либо только у автора, либо не работает даже у него

      Вы меня раскусили. Это был фантастический рассказ.

  • День добрый. Вопрос, с помощью DHCP-сервера с мостом, можно как-то зашейпить траф при доступе непосредственно в глобал?

  • Подскажите как организовать мосты для подобной схемы: На сервере с проксмоксом виртуалка, у нее 2 порта, один получает интернет из реальной сети, на другом она раздает по DHCP сотую подсеть (100.0), что бы клиенты подключенные к этому интерфейсу получали адреса и могли выходить в интернет. (То есть это типичный dhcp сервер на виртуалке). Сделал 2 моста, у виртуалки 2 интерфейса, на первый интерфейс мост где настроена сеть с инетом ( на виртуалке он появляется и получает адрес по dchp, т.к в этой сети он есть и все ок), на второй интерфейс мост на котором настроена 100 подсеть. Клиент подключенный к этому интерфейсу получает адрес (dhcp на виртуалке работает, c клиента эта сотая подсеть пингуется), но на клиенте нет доступа в инет. Клиент получает днс яндекса, шлюз виртуалки (на мосту с 100 подсетью адрес 100.1, на виртуалке которая раздает адреса — 100.10, она назначена клиентам в качестве шлюза). На реальной конструкции когда в качестве серва реальный комп и нет этих мостов все работает, а тут с мостами не могу догнать что к чему. Если поняли о чем я, буду рад помощи.

    • Если я правильно вас понял, то вы делаете из виртуалки «роутер» с NAT.

      но на клиенте нет доступа в инет

      Следовательно вам нужно как минимум на этой виртуалке:

      • Включить в ядре и разрешить в файрволе форвардинг
      • Настроить маскарад
      • Не только давать IP-адрес, но и просовывать маршрут через эту виртуалку или на клиенте DHCP делать установку дефолтного маршрута

      Вот тут про форвардинг и маскарад я коротко показывал для коллег как можно поднять виртуалку с каким-нибудь VPN в качестве гейтвея для хоста, на которой она работает. Похожая логика должна быть применима и к вашей ситуации.

      Вы когда говорите, что «нет доступа в интернет» — это может значить десятки разных вариантов проблем.

      Посмотрите таблицу маршрутов (ip route), сделайте трассировку (traceroute и/или mtr) чтобы посмотреть где обрывается прохождение вашего трафика и т.п.


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *