Proxmox NAT — konfiguracja iptables MASQUERADE dla maszyn wirtualnych i kontenerów
Stawiasz kilka VM-ek albo kontenerów LXC na jednym hoście Proxmox VE, podpinasz je do prywatnego mostu vmbr1 z adresacją typu 192.168.23.0/24 — i okazuje się, że gadają tylko między sobą, a internet jest dla nich nieosiągalny. Proxmox sam nie konfiguruje NAT-u, bo nie wie, którym interfejsem mają wychodzić Twoje guesty i czy w ogóle chcesz, żeby wychodziły. Trzy regułki iptables zamieniają host w router dla prywatnej sieci, a generator Proxmox NAT robi to za Ciebie — bez literówek w POSTROUTING i bez zgadywania, czy MASQUERADE idzie do nat czy filter. W tym artykule pokażę pełną konfigurację, wyjaśnię co robi każda dyrektywa, i wymienię błędy, na które uderza się najczęściej.
Generator Proxmox NAT — co robi i komu się przyda
Generator Proxmox NAT na vps-web.com bierze dwa parametry — nazwę interfejsu publicznego (najczęściej vmbr0) i podsieć prywatną z maską CIDR (np. 192.168.23.1/24) — i zwraca trzy bloki poleceń: regułę SNAT przez MASQUERADE, regułę conntrack dla ruchu zwrotnego oraz polecenia zapisujące konfigurację na trwałe przez iptables-persistent. Narzędzie obsługuje też tryb usuwania (-D zamiast -A), co jest przydatne przy reorganizacji adresacji albo migracji na inny interfejs uplinkowy.
Generator pisałem z myślą o trzech grupach administratorów. Pierwsza to ci, którzy stawiają jeden VPS u dostawcy z jednym publicznym IPv4 i potrzebują na nim zmieścić kilka maszyn wirtualnych z dostępem do sieci. Druga to homelabowcy, którzy budują wewnętrzne środowisko testowe (Kubernetes, Active Directory, sieć dla CI/CD) i nie chcą wystawiać każdej VM-ki na zewnątrz. Trzecia to ci, którzy zwyczajnie nie chcą za każdym razem ręcznie sprawdzać, czy POSTROUTING jest w tabeli nat czy mangle, i wolą wygenerować gotowy fragment do wklejenia.
Wynik wkleja się bezpośrednio do terminala na hoście Proxmox. Reguły zaczynają działać natychmiast — iptables nie wymaga restartu usług ani przeładowania interfejsów. Po sprawdzeniu, że konfiguracja faktycznie działa, trzeci blok zapisuje stan do pliku, żeby przeżył reboot.
Praktyka — pełna konfiguracja NAT na Proxmox VE krok po kroku
Dla orientacji: w przykładzie zakładam, że vmbr0 to most podpięty do fizycznej karty z publicznym IP, a vmbr1 to most prywatny dla VM-ek z adresacją 192.168.23.0/24. Host ma na vmbr1 adres 192.168.23.1 i to ten adres jest gateway-em dla guestów. Generator wypluwa polecenia dla dowolnej Twojej kombinacji — tu pokazuję, dlaczego każde z nich robi to, co robi.
Most prywatny dla guestów
Generator zakłada, że most vmbr1 jest już zdefiniowany. Jeśli nie — wpis w /etc/network/interfaces na hoście Proxmox wygląda tak:
auto vmbr1
iface vmbr1 inet static
address 192.168.23.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
Kluczowy jest bridge-ports none — to znaczy, że most nie jest podpięty do żadnej fizycznej karty. Łączy wyłącznie interfejsy wirtualne VM-ek i kontenerów. Linia address 192.168.23.1/24 ustawia hosta jako bramę dla podsieci — ten adres wpiszesz jako gateway w konfiguracji każdej VM-ki podpiętej do vmbr1.
Po zapisie pliku zastosuj zmiany komendą ifreload -a (Proxmox używa ifupdown2) albo zrestartuj hosta. Następnie podepnij VM-kę do vmbr1, nadaj jej adres np. 192.168.23.10/24, gateway 192.168.23.1, DNS 1.1.1.1 — i jest gotowa do gadania z internetem, jak tylko dodasz reguły NAT.
Blok 1 — SNAT przez MASQUERADE
Pierwsza i najważniejsza reguła:
iptables -t nat -A POSTROUTING -s '192.168.23.0/24' -o vmbr0 -j MASQUERADE
Dopisuje regułę do łańcucha POSTROUTING w tabeli nat. POSTROUTING to ostatni łańcuch, przez który przechodzi pakiet zanim opuści hosta — czyli idealne miejsce do podmiany adresu źródłowego. Reguła mówi: każdy pakiet z podsieci 192.168.23.0/24 wychodzący przez interfejs vmbr0 ma mieć adres źródłowy podmieniony na ten, który aktualnie ma vmbr0. To robi target MASQUERADE — wariant SNAT (Source NAT), który nie wymaga wpisywania publicznego IP na sztywno, bo pobiera go z interfejsu wyjściowego w locie. W praktyce: jeśli Twój dostawca zmieni Ci publiczny adres albo przesiądziesz się na inny interfejs uplinkowy, regułka nadal działa bez edycji.
Apostrofy wokół podsieci to mały detal — niektóre powłoki próbują interpretować znaki w notacji CIDR i apostrofy gwarantują, że literał trafia do iptables bez modyfikacji. To dobry nawyk obronny.
Blok 2 — conntrack dla ruchu zwrotnego
Druga reguła pozwala wracającym pakietom dotrzeć do guesta:
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Jeśli łańcuch FORWARD ma domyślną politykę DROP — co Proxmox czasem konfiguruje sam, gdy włączysz firewall na poziomie node-a — pakiety odpowiedzi z internetu zostaną odrzucone, zanim dotrą do VM-ki. Reguła jawnie akceptuje pakiety, które należą do połączenia już zestawionego (ESTABLISHED — handshake TCP zakończony, leci ruch) albo logicznie powiązanego z innym (RELATED — np. kanał danych FTP, błąd ICMP do istniejącej sesji UDP).
Moduł conntrack to mechanizm, który robi z linuksowego firewalla firewall stateful. Za każdym razem, gdy guest otwiera połączenie na zewnątrz, conntrack zakłada wpis w tablicy jądra z adresami, portami i stanem. Gdy odpowiedź wraca, conntrack rozpoznaje ją i oznacza jako ESTABLISHED — ta jedna linijka ją wpuszcza. Bez conntrack musiałbyś pisać dziesiątki reguł bezstanowych dla każdego protokołu i portu, i nigdy nie byłyby w pełni poprawne. Z conntrack dostajesz to za darmo.
Blok 3 — trwały zapis konfiguracji
Trzeci blok rozwiązuje pułapkę, na której wykłada się najwięcej ludzi:
apt-get install iptables-persistent -y
iptables-save > /etc/iptables/rules.v4
cat /etc/iptables/rules.v4
Reguły iptables żyją w pamięci. Po restarcie hosta albo systemctl restart networking znikają. Spotkałem to u wielu administratorów: NAT skonfigurowany, działa, idą do domu zadowoleni — wracają w poniedziałek po rutynowym reboocie i nic nie działa, bo reguły były tylko w RAM-ie.
Pakiet iptables-persistent instaluje usługę systemd, która przy starcie ładuje reguły z /etc/iptables/rules.v4 (i rules.v6 dla IPv6). iptables-save serializuje aktualny stan pamięci do formatu, który ten plik konsumuje. cat na końcu to sanity check — zobacz, czy plik faktycznie się zapisał, zanim zaufasz mu na produkcji.
Jeśli kiedykolwiek zmienisz reguły, pamiętaj ponownie odpalić iptables-save > /etc/iptables/rules.v4. To najczęściej popełniany błąd — ktoś poprawia regułę, testuje, działa, zakłada, że jest na trwałe. Nie jest. Aktualizujesz pamięć, nie plik.
IP forwarding — bez tego cała reszta nie zadziała
Generator skupia się na iptables, ale samo iptables nie wystarczy. Jądro Linuksa domyślnie nie przekazuje pakietów między interfejsami. Trzeba mu jawnie pozwolić:
sysctl -w net.ipv4.ip_forward=1
Żeby ustawienie przeżyło reboot, edytuj /etc/sysctl.conf (albo wrzuć osobny plik do /etc/sysctl.d/) i dodaj:
net.ipv4.ip_forward = 1
Potem sysctl -p żeby zastosować. Bez tego żadna z reguł iptables nic nie zrobi — pakiety nigdy nie dojdą do POSTROUTING, bo host odmówi ich routingu już na poziomie kernela. Oficjalna dokumentacja Proxmoxa opisuje to w sekcji Network Configuration → Masquerading (NAT) with iptables.
Weryfikacja, że NAT faktycznie działa
Po wklejeniu reguł zrób trzy szybkie sprawdzenia:
# Reguły NAT z licznikami pakietów i bajtów
iptables -t nat -L POSTROUTING -n -v
# Reguły FORWARD
iptables -L FORWARD -n -v
# Licznik MASQUERADE w czasie rzeczywistym
watch -n 1 'iptables -t nat -L POSTROUTING -n -v'
Liczniki obok każdej reguły rosną, gdy faktycznie trafia w nią ruch. Jeśli pingujesz coś z guesta, a licznik stoi na zerze — pakiet nie trafia w regułę. Najczęściej to znaczy, że źródłowy adres nie pasuje do podsieci, którą wpisałeś w generatorze, albo IP forwarding jest wyłączony. Jeśli licznik rośnie, ale guest nadal nie ma internetu — problem jest w FORWARD albo w DNS-ach guesta, nie w NAT.
Z poziomu guesta:
# Surowe IP — pomija DNS
ping -c 3 1.1.1.1
# Test DNS
ping -c 3 google.com
# Test TCP wychodzący
curl -v https://example.com
ping 1.1.1.1 działa, ping google.com nie? NAT jest OK, DNS na guescie nie jest. Nic nie pinguje? Wracaj od końca: pingnij bramę (192.168.23.1), sprawdź IP forwarding, sprawdź conntrack.
Częste błędy i pułapki
Po reboocie wszystko przestało działać
Najczęstszy problem — reguły były w pamięci, pakiet iptables-persistent nie został zainstalowany, plik /etc/iptables/rules.v4 nie istnieje albo zawiera starą wersję. Sprawdź systemctl status netfilter-persistent i porównaj wynik iptables-save z zawartością /etc/iptables/rules.v4. Jeśli się różnią — wykonaj iptables-save > /etc/iptables/rules.v4 jeszcze raz.
Reguła w POSTROUTING jest, licznik rośnie, ale guest nadal nie ma internetu
W 90% przypadków winowajcą jest łańcuch FORWARD z domyślną polityką DROP. Sprawdź iptables -L FORWARD -n -v --line-numbers. Jeśli widzisz policy DROP i nie ma reguły akceptującej ruch z vmbr1 do vmbr0 — guest wysyła pakiet, NAT go przepuszcza, ale wraca i jest dropowany. Reguła conntrack z generatora wpuszcza ruch zwrotny, ale dla pierwszego pakietu w drugą stronę potrzebujesz dodatkowo:
iptables -A FORWARD -i vmbr1 -o vmbr0 -j ACCEPT
albo zmień politykę FORWARD na ACCEPT (mniej bezpieczne, ale prostsze w homelabie).
iptables: command not found na świeżym Proxmoxie
Najnowsze wersje Debiana/Proxmoxa potrafią przyjść z nftables jako domyślnym backendem. Polecenie iptables faktycznie jest, ale w wariancie iptables-nft — to wrapper na nftables zachowujący starą składnię. Działa tak samo, generator produkuje kompatybilne polecenia. Jeśli wolisz natywne nftables, regułki trzeba przepisać, ale to osobny temat.
Reguła conntrack jest, ale po włączeniu firewalla PVE pakiety wciąż się gubią
Firewall Proxmox VE (pve-firewall) używa własnej strefy conntrack przez moduł xt_CT. Jeśli włączasz firewall na poziomie node-a albo VM-ki, dodatkowo potrzebujesz:
iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
To wpis z oficjalnego wiki Proxmoxa. Bez niego conntrack gubi pakiety przechodzące przez bridge'e firewallowe (fwbr*).
rp_filter blokuje pakiety na hostach z wieloma interfejsami
Reverse path filtering (/proc/sys/net/ipv4/conf/*/rp_filter) odrzuca pakiety, których adres źródłowy nie zgadza się z tablicą routingu wziętą od strony wejścia. Na hoście z bondingiem albo dwoma uplinkami potrafi cicho zabijać NAT. Sprawdź wartości:
sysctl -a 2>/dev/null | grep rp_filter
Jeśli widzisz 1 na interfejsie wyjściowym i NAT nie działa mimo poprawnych reguł — ustaw 2 (loose mode) albo 0 (off) i dopisz na trwałe do /etc/sysctl.conf.
Guest pinguje IP, ale nie rozwiązuje nazw
To nie problem NAT-u, to problem DNS-ów wewnątrz guesta. Sprawdź /etc/resolv.conf w VM-ce — czy w ogóle coś tam jest. Sprawdź, czy DNS, który tam wpisałeś, jest osiągalny po dodaniu reguły MASQUERADE (dig @1.1.1.1 google.com z poziomu guesta). 99% przypadków: użytkownik wpisał IP guestowi statycznie, zapomniał o DNS-ach.
Mieszanie składni Debian/Ubuntu w /etc/network/interfaces
Stare przykłady z internetu używają bridge_ports (z podkreślnikiem), nowy ifupdown2 w Proxmoxie chce bridge-ports (z myślnikiem). Obie wersje przeważnie działają, ale przy ifreload -a nowy parser potrafi się zaciąć na starej składni. Trzymaj się myślników.
FAQ — najczęściej zadawane pytania
Dlaczego moje VM-ki na vmbr1 widzą się nawzajem, ale nie mają internetu?
Bo most vmbr1 jest mostem wewnętrznym (bridge-ports none) — przekazuje pakiety tylko między portami wirtualnymi VM-ek. Żeby pakiet wyszedł do internetu, musi przejść przez routing hosta (czyli musisz mieć włączone net.ipv4.ip_forward=1) i mieć podmieniony adres źródłowy na publiczny (czyli regułę MASQUERADE w POSTROUTING). Generator robi obie te rzeczy.
Czy MASQUERADE jest lepszy od SNAT --to-source?
To zależy. MASQUERADE bierze adres źródłowy dynamicznie z interfejsu wyjściowego — idealny, gdy publiczny IP może się zmienić (DHCP, dynamiczne IP od providera). SNAT --to-source 1.2.3.4 jest minimalnie szybszy (jeden lookup mniej na pakiet) i przewidywalny, ale wymaga hardkodowania IP. Dla 95% scenariuszy MASQUERADE jest właściwym wyborem — i to on jest w generatorze.
Czy NAT wpływa na wydajność sieci?
Na nowoczesnym sprzęcie zauważalnie nie. Conntrack zżera trochę pamięci (mniej więcej 300 bajtów na połączenie), a SNAT to dodatkowy lookup w tablicy hashy. Dla hosta z kilkudziesięcioma VM-kami i normalnym ruchem to pomijalne. Problem zaczyna się przy 100k+ równoczesnych połączeń — wtedy patrz na net.netfilter.nf_conntrack_max i nf_conntrack_buckets.
Jak dodać port forwarding z internetu do konkretnej VM-ki?
NAT z generatora obsługuje tylko ruch wychodzący (SNAT). Dla ruchu przychodzącego (DNAT, czyli klasyczny port forwarding) jest osobny generator Proxmox IPTables na vps-web.com, który produkuje regułę w stylu iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.23.10:80. Dla pełnego, dwukierunkowego NAT-u potrzebujesz obu generatorów.
Czy mogę użyć tego samego setupu dla IPv6?
Tak, ale z gwiazdką. Składnia jest analogiczna z ip6tables zamiast iptables i ULA (np. fd00::/8) zamiast prywatnej IPv4. W praktyce większość hostingów daje pełen blok IPv6 (np. /64), więc rzadziej trzeba NAT-ować — można każdej VM-ce dać własny globalny IPv6. Jeśli jednak musisz NAT-ować, używaj NAT66 z ip6tables -t nat, a regułę persystencji zapisuj do /etc/iptables/rules.v6.
Po zmianie podsieci VM-ki straciły internet — co się stało?
Stara reguła MASQUERADE wciąż wisi w POSTROUTING z poprzednią podsiecią, a nowej nie ma. Wygeneruj polecenia z trybem usuwania dla starej podsieci, wykonaj je, potem dodaj nowe. Sprawdź iptables -t nat -L POSTROUTING -n -v — powinna być jedna reguła z aktualną podsiecią, nie dwie. Zapisz z iptables-save > /etc/iptables/rules.v4 po każdej takiej zmianie.
Czy reguła conntrack w FORWARD to nie za szeroka furtka?
Dla NAT-u wychodzącego jest dokładnie tak szeroka, jak musi być — wpuszcza tylko pakiety, które są częścią zestawionego połączenia zainicjowanego przez Twoje guesty. Atakujący z internetu nie może otworzyć połączenia do 192.168.23.10, bo first-packet z zewnątrz nie ma stanu ESTABLISHED ani RELATED. Furtka byłaby szeroka, gdybyś dał -A FORWARD -j ACCEPT bez warunków.
Co zrobić, gdy iptables -t nat -L pokazuje regułę dwa razy?
Wykonałeś dwa razy polecenie z -A. -A zawsze dopisuje regułę na końcu łańcucha, niezależnie od tego, czy już tam jest. Usuń duplikaty: iptables -t nat -D POSTROUTING -s '192.168.23.0/24' -o vmbr0 -j MASQUERADE tyle razy, ile masz nadmiarowych kopii, potem dodaj jedną. Generator z trybem usuwania robi to za Ciebie — produkuje identyczne polecenie z -D.
Następne kroki
Reguły z generatora pokrywają outbound NAT — pakiety wychodzące z VM-ek do internetu. Dla pełnego setupu na pojedynczym publicznym IP potrzebujesz jeszcze dwóch rzeczy.
Pierwsza to inbound NAT, czyli przekierowywanie portów z zewnątrz do konkretnych VM-ek (np. żeby SSH na porcie 2222 hosta trafiał do 192.168.23.10:22). To rola generatora Proxmox IPTables na vps-web.com, który produkuje reguły DNAT w PREROUTING. Druga to zabezpieczenia: domyślna polityka INPUT z DROP-em i jawnymi ACCEPT-ami tylko na SSH i wybrane porty, fail2ban do throttle-owania prób brute-force, ograniczenie SSH do konkretnych źródłowych IP. Generator daje minimum, żeby NAT działał — bezpieczna produkcyjna konfiguracja to dodatkowych kilka rzeczy ponad.
Wideo wersję tego tutoriala oraz inne materiały o Proxmoxie znajdziesz na moim kanale YouTube — jest tam demo na żywym serwerze, łącznie z weryfikacją reguł i typowymi pomyłkami przy wpisywaniu adresacji.
Pełną konfigurację z Twoimi parametrami wygenerujesz w generatorze Proxmox NAT na vps-web.com — formularz wypełni się szybciej, niż otworzysz nano /etc/network/interfaces.