Przejdź do treści
Lekcja 74 z 117

Kurs › Moduł 8 › Lekcja 74

Routing, NAT, przekierowanie portów, bonding i mostki

⏱ ok. 10 min czytania· moduł 8: Sieć

Po tej lekcji: kursant dodaje trasy chwilowo i na stałe, zamienia serwer w router z NAT-em, przekierowuje port na inną maszynę w firewalld i nftables, a w nmcli łączy dwie karty w bond i buduje mostek dla maszyn wirtualnych.

Wstęp

Masz serwer z dwiema kartami sieciowymi. Jedna patrzy na sieć biurową, druga na zaplecze, gdzie stoi baza danych. Laptop widzi serwer. Serwer widzi bazę. A laptop bazy nie widzi, choć serwer jest dosłownie pośrodku.

Dziś zrobimy z serwera skrzyżowanie. Nauczysz się mówić systemowi „do tej sieci jedź tamtędy”, przepuszczać ruch przez serwer, chować całą sieć za jednym adresem i przekierowywać port na inną maszynę. Na deser połączymy dwie karty w jedną, żeby wyciągnięcie kabla nie było katastrofą.

Uwaga od razu: wszystko, co dziś zmieniamy, dotyczy sieci. Rób to na maszynach wirtualnych z dostępem do konsoli, a nie przez SSH na jedynym serwerze firmy.

Tablica tras, czyli drogowskazy

Pamiętasz tablicę tras z ip route? To drogowskazy na skrzyżowaniu. „Do sieci 10.0.0.0/24 prosto, kartą vcli”. „Wszystko inne: do bramy domyślnej”. Jak drogowskazu brak, system rozkłada ręce.

ip route
ping -c1 10.1.0.2
10.0.0.0/24 dev vcli proto kernel scope link src 10.0.0.20
ping: connect: Network is unreachable

„Sieć nieosiągalna”. Laptop nie ma pojęcia, gdzie leży sieć 10.1.0.0/24. Dopisujemy drogowskaz: do tej sieci jedź przez serwer 10.0.0.10.

sudo ip route add 10.1.0.0/24 via 10.0.0.10
ip route
ip route get 10.1.0.2
10.0.0.0/24 dev vcli proto kernel scope link src 10.0.0.20
10.1.0.0/24 via 10.0.0.10 dev vcli
10.1.0.2 via 10.0.0.10 dev vcli src 10.0.0.20 uid 0

via to brama, czyli następny przystanek. ip route get to pytanie do systemu: „którędy pojechałbyś do tego adresu?”. Najlepsze narzędzie do sprawdzania, czy drogowskazy mówią to, co myślisz. Usuwanie: sudo ip route del 10.1.0.0/24.

Haczyk: ip route add żyje do restartu. To kreda na asfalcie. Pierwszy deszcz, czyli restart, i nie ma śladu.

Trasy na stałe

[RHEL] W NetworkManagerze trasę dopisujesz do profilu połączenia. Plus przed nazwą znaczy „dodaj do listy”, a nie „zastąp”:

sudo nmcli connection modify br0 +ipv4.routes "10.20.0.0/16 192.168.50.254"
sudo nmcli connection up br0
nmcli -g ipv4.routes connection show br0
ip route
10.20.0.0/16 192.168.50.254
default via 192.168.50.1 dev br0 proto static metric 425
10.20.0.0/16 via 192.168.50.254 dev br0 proto static metric 425
192.168.50.0/24 dev br0 proto kernel scope link src 192.168.50.10 metric 425

-ipv4.routes z tą samą wartością usuwa trasę. Zmiany w profilu działają dopiero po nmcli connection up, czyli po ponownym podniesieniu połączenia.

[Ubuntu] W netplanie trasy dopisujesz pod kartą, w sekcji routes:

      routes:
        - to: default
          via: 192.0.2.254
        - to: 10.20.0.0/16
          via: 192.0.2.1

I jak w lekcji 70: sudo netplan try, a jak wszystko gra, potwierdzasz.

Serwer jako skrzyżowanie: ip_forward

Drogowskaz na laptopie jest, a ping dalej nie przechodzi. Bo serwer domyślnie nie jest skrzyżowaniem, tylko ślepą uliczką. Dostaje paczkę adresowaną do kogoś innego i… nic. Jak listonosz, który dostał list do sąsiada i grzecznie go wyrzucił.

Przełącznik nazywa się net.ipv4.ip_forward:

sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0

Zero to „nie przekazuję”. Włączamy na chwilę:

sudo sysctl -w net.ipv4.ip_forward=1

I na stałe, plikiem w /etc/sysctl.d, ten sam sposób na Ubuntu i RHEL:

echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/90-router.conf
sudo sysctl --system

NAT, czyli recepcjonistka z jednym numerem telefonu

Ruch przechodzi, ale jest problem. Maszyna na zapleczu dostaje paczkę od 10.0.0.20 i chce odpowiedzieć. Tylko że nie ma drogowskazu do 10.0.0.20. W domu masz dokładnie ten problem z całym internetem: Twój laptop ma adres 192.168.1.x, a internet o takich adresach nie chce słyszeć.

Rozwiązanie to NAT, Network Address Translation, czyli tłumaczenie adresów. Wyobraź sobie firmę z jedną recepcją i jednym numerem telefonu. Pracownik dzwoni na zewnątrz, ale klient widzi numer recepcji. Kiedy klient oddzwania, recepcja wie, do którego biurka przełączyć. Twój domowy router robi to samo od lat, a Ty nawet nie musiałeś mu podziękować.

Odmiana, w której serwer podmienia adres nadawcy na swój, to maskarada, masquerade. Sprawdźmy na żywo. [na ekranie: tcpdump na maszynie z zaplecza, o tym narzędziu cały następna lekcja] Ping z laptopa 10.0.0.20, a zaplecze widzi:

16:37:32.847378 IP 10.1.0.1 > 10.1.0.2: ICMP echo request, id 4591, seq 1, length 64
16:37:32.847391 IP 10.1.0.2 > 10.1.0.1: ICMP echo reply, id 4591, seq 1, length 64

Nadawca to 10.1.0.1, czyli serwer. Laptop schował się za recepcją.

NAT i przekierowanie portu w firewalld [RHEL]

W firewalld karty przypisujemy do stref. Karta od strony biura do strefy internal, karta od strony świata do external. Strefa external ma maskaradę włączoną od razu:

sudo firewall-cmd --permanent --zone=internal --add-interface=vsrv
sudo firewall-cmd --permanent --zone=external --add-interface=vr2
sudo firewall-cmd --reload
sudo firewall-cmd --zone=external --query-masquerade
success
success
success
yes

W innej strefie włączasz ją ręcznie: sudo firewall-cmd --permanent --zone=public --add-masquerade.

Na nowym firewalld to jeszcze nie wszystko. Ruch między strefami pilnuje osobny ochroniarz na korytarzu, czyli polityka, policy. Mówimy mu: „z biura do świata przepuszczaj”:

sudo firewall-cmd --permanent --new-policy=lan-do-swiata
sudo firewall-cmd --permanent --policy=lan-do-swiata --add-ingress-zone=internal
sudo firewall-cmd --permanent --policy=lan-do-swiata --add-egress-zone=external
sudo firewall-cmd --permanent --policy=lan-do-swiata --set-target=ACCEPT
sudo firewall-cmd --reload

Bez tej polityki ping kończy się tak:

From 10.0.0.10 icmp_seq=1 Packet filtered

A z nią:

64 bytes from 10.1.0.2: icmp_seq=1 ttl=63 time=0.078 ms

ttl=63 zamiast 64: pakiet przeszedł przez jedno skrzyżowanie i stracił po drodze jeden punkt życia.

Teraz przekierowanie portu, port forwarding. Świat puka do serwera na port 8080, a serwer po cichu przełącza rozmowę na port 80 maszyny z zaplecza. Recepcjonistka: „Pan do działu WWW? Łączę z wewnętrznym”.

sudo firewall-cmd --permanent --zone=internal --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=10.1.0.2
sudo firewall-cmd --reload
curl http://10.0.0.10:8080/index.html
Witaj z zaplecza

Pukamy do serwera, odpowiada maszyna, której z laptopa w ogóle nie widać. Składnię warto zapamiętać jak numer PESEL: port= skąd, proto= jaki protokół, toport= dokąd, toaddr= do kogo. Bez toaddr przekierowanie zostaje na tym samym serwerze, na przykład z 8080 na 80.

NAT w nftables

Na Ubuntu i wszędzie tam, gdzie wolisz maszynownię od formularzy, to samo robisz w nftables. Osobna tabela nat z dwiema bramkami:

table ip nat {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oifname "vr2" masquerade
    }
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        iifname "vsrv" tcp dport 8080 dnat to 10.1.0.2:80
    }
}

postrouting, tuż przed wyjściem: wszystko, co wychodzi kartą vr2, dostaje adres serwera. To maskarada. prerouting, zaraz po wejściu: kto przyszedł kartą vsrv na port 8080, jedzie do 10.1.0.2:80. To DNAT, podmiana adresu docelowego.

sudo nft -c -f nat.nft && sudo nft -f nat.nft
curl http://10.0.0.10:8080/index.html
Witaj z zaplecza

Pamiętaj o ip_forward = 1. Bez niego reguły NAT są jak recepcjonistka bez telefonu: bardzo się stara, ale nikogo nie połączy.

Bonding: dwie karty, jedna droga

Serwer ma dwie karty, do każdej idzie kabel do innego przełącznika. Bond skleja je w jedną kartę logiczną bond0 z jednym adresem IP. Jak w samochodzie z dwoma kołami zapasowymi zamontowanymi od razu na osi: jedno pęknie, jedziesz dalej.

Najważniejsze tryby:

  • active-backup: jedna karta pracuje, druga czeka. Najprostszy, działa z każdym przełącznikiem.
  • 802.3ad, czyli LACP: obie pracują naraz, ale przełącznik musi to umieć i mieć to ustawione.
  • balance-rr: pakiety na zmianę, raz jedną, raz drugą kartą.

[RHEL] W nmcli najpierw sam bond, potem karty jako jego porty:

sudo nmcli connection add type bond con-name bond0 ifname bond0 bond.options "mode=active-backup,miimon=100" ipv4.method manual ipv4.addresses 192.168.60.10/24
sudo nmcli connection add type ethernet port-type bond con-name bond0-p1 ifname enp7s0 controller bond0
sudo nmcli connection add type ethernet port-type bond con-name bond0-p2 ifname enp8s0 controller bond0
sudo nmcli connection up bond0
cat /proc/net/bonding/bond0
Connection 'bond0' (89e42390-4401-45b3-a50a-32495a7cb7db) successfully added.
Connection 'bond0-p1' (01118b5b-476e-4825-8510-bb01970e6aab) successfully added.
Connection 'bond0-p2' (57724ff0-9aaf-4231-ad99-1cedd28ff6aa) successfully added.

miimon=100 znaczy: co 100 milisekund sprawdzaj, czy w karcie jest kabel. /proc/net/bonding/bond0 pokaże, która karta jest teraz aktywna. Test na VM: odłącz jedną kartę w ustawieniach wirtualizatora i patrz, jak ping nawet nie mrugnie. W starszych poradnikach zamiast port-type i controller zobaczysz slave-type i master. To te same ustawienia pod starymi nazwami.

[Ubuntu] W netplanie:

network:
  version: 2
  ethernets:
    enp7s0: {}
    enp8s0: {}
  bonds:
    bond0:
      interfaces: [enp7s0, enp8s0]
      parameters:
        mode: active-backup
        mii-monitor-interval: 100
      addresses: [192.0.2.10/24]

Mostek: przełącznik w środku serwera

Mostek, bridge, to wirtualny przełącznik sieciowy w środku serwera. Podpinasz do niego fizyczną kartę i karty maszyn wirtualnych, a wtedy każda VM-ka jest w sieci biurowej jak pełnoprawny komputer z własnym adresem. Listwa zasilająca, tylko na kable sieciowe.

sudo nmcli connection add type bridge con-name br0 ifname br0 ipv4.method manual ipv4.addresses 192.168.50.10/24 ipv4.gateway 192.168.50.1
sudo nmcli connection add type ethernet port-type bridge con-name br0-p1 ifname enp1s0 controller br0
sudo nmcli connection up br0
bridge link

Ważne: adres IP przenosisz z karty na mostek. Karta staje się tylko kablem wpiętym do listwy. A skoro zmieniasz adres karty, przez którą jesteś połączony, to robisz to z konsoli, nie przez SSH. Serio.

[Ubuntu] W netplanie sekcja bridges: z interfaces: [enp7s0] i adresem pod mostkiem.

Jak to działa pod spodem

Dla każdego pakietu jądro robi jedno: szuka w tablicy tras najdłuższego pasującego prefiksu. Trasa /24 wygrywa z /16, /16 z trasą domyślną 0.0.0.0/0. Bardziej szczegółowy drogowskaz zawsze wygrywa, jak w GPS-ie, który woli „ulica Floriańska 3” od „gdzieś w Krakowie”.

Jeśli adres docelowy nie jest adresem serwera, a ip_forward jest wyłączone, pakiet ląduje w koszu. Jeśli włączone, przechodzi przez bramkę forward w netfilterze, czyli tam, gdzie pilnuje zapora i polityki firewalld.

NAT opiera się na conntracku z poprzedniej lekcji. Przy pierwszym pakiecie połączenia jądro zapisuje w tabelce: „10.0.0.20:36658 wychodzi jako 10.1.0.1:36658”. Każdy kolejny pakiet i każda odpowiedź są tłumaczone według tej notatki, bez ponownego sprawdzania reguł. Tabelkę podejrzysz przez conntrack -L z pakietu conntrack [Ubuntu] albo conntrack-tools [RHEL].

Bond i mostek to sterowniki w jądrze: bonding i bridge. NetworkManager i netplan tylko je zamawiają i konfigurują.

Ściąga flag

KomendaFlagaCo robi
ip routeadd SIEĆ via BRAMAdodaje trasę do restartu
ip routedel SIEĆusuwa trasę
ip routeget ADRESmówi, którędy pojedzie pakiet
nmcli con mod+ipv4.routes "SIEĆ BRAMA"dodaje trasę na stałe
nmcli con mod-ipv4.routes "SIEĆ BRAMA"usuwa trasę z profilu
sysctl-w net.ipv4.ip_forward=1włącza przekazywanie pakietów
sysctl--systemwczytuje pliki z /etc/sysctl.d
firewall-cmd--add-masquerade / --query-masqueradewłącza / sprawdza maskaradę w strefie
firewall-cmd--add-forward-port=port=:proto=:toport=:toaddr=przekierowuje port
firewall-cmd--new-policy / --set-target=ACCEPTpolityka ruchu między strefami
firewall-cmd--add-interfaceprzypisuje kartę do strefy
nftmasquerade / dnat toNAT źródłowy / docelowy
nmcli con addtype bond bond.options "mode=..."tworzy bond
nmcli con addtype bridgetworzy mostek
nmcli con addport-type bond lub bridge, controller NAZWApodpina kartę pod bond lub mostek

⚠ Typowy błąd

Brama spoza sieci.

sudo ip route add 172.16.0.0/16 via 192.168.77.1
Error: Nexthop has invalid gateway.

„Następny przystanek ma niepoprawną bramę”. Brama musi być w sieci, do której jesteś bezpośrednio podłączony. Laptop zna tylko 10.0.0.0/24, więc brama 192.168.77.1 to jak drogowskaz „skręć w prawo przy sklepie, którego nie ma w tym mieście”. Popraw na adres z Twojej sieci, sprawdzając w ip -br a, jakie masz.

Drugi klasyk: wszystkie trasy dobre, NAT ustawiony, a ruch nie przechodzi, bo ip_forward jest dalej 0, albo jest 1, ale tylko do restartu, bo ktoś ustawił sysctl -w i nie zrobił pliku w /etc/sysctl.d. Działa do pierwszego restartu, a potem nikt nie pamięta, czemu przestało.

✎ Zadanie

Na dwóch maszynach wirtualnych: w pierwszej dodaj drugą kartę w sieci wewnętrznej wirtualizatora i zrób z niej router. Włącz ip_forward na stałe, włącz maskaradę (w firewalld albo w nftables) i przekieruj port 8080 routera na port 22 drugiej maszyny. Sprawdź, że ssh -p 8080 użytkownik@ADRES_ROUTERA ląduje na drugiej maszynie. Komendą hostname upewnij się, gdzie jesteś.

Pokaż rozwiązanie

Router: przekazywanie na stałe, karty w strefach, polityka z biura do świata (jak w lekcji 74) i przekierowanie portu 8080 na port 22 drugiej maszyny.

echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/90-router.conf
sudo sysctl --system
sudo firewall-cmd --permanent --zone=internal --add-forward-port=port=8080:proto=tcp:toport=22:toaddr=10.1.0.2
sudo firewall-cmd --reload
sudo firewall-cmd --zone=internal --list-forward-ports
port=8080:proto=tcp:toport=22:toaddr=10.1.0.2

[Ubuntu] To samo w nftables, w tabeli nat:

oifname "enp8s0" masquerade
iifname "enp1s0" tcp dport 8080 dnat to 10.1.0.2:22

A teraz test z laptopa:

ssh -p 8080 kuba@10.0.0.10 "hostname -I"
10.1.0.2

Pukasz do routera, a otwiera Ci zupełnie inna maszyna. Jak domofon, który po wciśnięciu „8080” łączy Cię z mieszkaniem w oficynie. Ciekawostka: SSH zapamięta klucz tej maszyny pod nazwą [10.0.0.10]:8080, osobno od klucza samego routera. I bardzo dobrze, bo to naprawdę inny komputer.

Co dalej

Ciągle zgadujemy, co się dzieje z pakietami: przeszedł, nie przeszedł, z jakim adresem. W następnej lekcji przestaniemy zgadywać i zaczniemy patrzeć: tcpdump podsłucha każdy pakiet, a Wireshark pokaże go w kolorach.