[OpenBSD]

[[Wstecz: Authpf: powłoka dla bramek uwierzytelniających] [Spis treści] [Dalej: Zapora ogniowa dla domu i małego biura]

PF: Redundantny firewall z CARP i pfsync


Spis treści


Wprowadzenie do CARP

CARP to Common Address Redundancy Protocol. Jego podstawowym zadaniem jest dopuszczenie by wiele hostów w tym samym segmencie sieci mogło dzielić jeden adres IP. CARP jest bezpieczną i wolną alternatywą dla Virtual Router Redundancy Protocol (VRRP)oraz Hot Standby Router Protocol (HSRP).

CARP pracuje pozwalając grupie hostów, w tym samym segmencie sieci, na dzielenie adresu IP. Taka grupa hostów nazywana jest "redundancy group". Taka nadmiarowa grupa posiada przypisany adres IP, który jest dzielony pomiędzy członkami grupy. Wewnątrz grupy jeden host jest przeznaczany jako "główny" (ang. master) natomiast pozostałe jako "zapasowe" (ang. backups). Host główny jest tym który bieżąco "trzyma" dzielony adres IP; odpowiada na każdy ruch i zapytania ARP nadchodzące na ten adres. Każdy host może należeć jednocześnie do więcej niż jednej grupy nadmiarowej.

Jednym z powszechnych zastosowań CARP jest tworzenie grupy nadmiarowych zapór ogniowych. Wirtualny adres IP dedykowany takiej grupie jest ustawiony na maszynach klienckich jako brama domyślna. W przypadku gdy główny firewall ulednie awarii lub zostanie wyłączona, adres IP zostanie przeniesiony na jedną z zapasowych zapór i obsługa będzie kontynuowana niezauważalnie.

CARP wspiera zarówno IPv4 jak i IPv6.

Działanie CARP

Główny host w grupie regularnie wysyła rozgłoszenia do lokalnej sieci, tak że hosty zapasowe wiedzą, że jest wciąż "żywy". Jeżeli hosty zapasowe przestaną otrzymywać rozgłoszenia z hosta głównego w ustalonym okresie czasu, jeden z nich przejmuje obowiązki hosta głównego (jakikolwiek z najniższą skonfigurowaną wartością parametrów advbase i advskew).

Istnieje możliwość by istniało wiele grup CARP w tym samym segmencie sieci. Rozgłoszenia CARP zawierają Virtual Host ID, które pozwala członkom grup określić do jakiej grupy nadmiarowej dane rozgłoszenie należy.

Aby uniemożliwić złośliwemu użytkownikowi w segmencie sieci podszywanie się pod rozgłoszenia CARP, każda grupa może być skonfigurowana z hasłem. Każdy pakiet CARP wysyłany do grupy jest wtedy chroniony przy użyciu SHA1 HMAC.

Odkąd CARP jest osobnym protokołem powinien mieć sprecyzowaną regułę przepuszczającą w filtrze:

pass out on $carp_dev proto carp keep state

$carp_dev powinien być fizycznym interfejsem przez który komunikuje się CARP.

konfiguracja CARP

Każda redundantna grupa jest reprezentowana przez wirtualny interfejs carp(4). Jak dotąd CARP jest konfigurowany korzystając z ifconfig(8).
ifconfig carpN create

ifconfig carpN vhid vhid [pass password] [carpdev carpdev] \
   [advbase advbase] [advskew advskew] [state state] ipaddress \
   netmask mask
carpN
Nazwa wirtualnego interfejsu cart(4), gdzie N jest liczbą całkowitą reprezentującą numer interfejsu (np. carp10).
vhid
Virtual Host ID. Jest to unikalny numer służący do identyfikacji grupy redundantnej od innych węzłów w sieci. Dopuszczalnymi wartościami są liczby od 1 do 255.
password
Hasło autoryzacyjne wykorzystywane do komunikacji z pozostałymi hostami CARP w danej grupie.
carpdev
Opcjonalny parametr określający fizyczny interfejs który należy do danej grupy. Domyślnie CARP stara się określić jaki interfejs wykorzystać sprawdzając który fizyczny interfejs znajduje się w tej samej podsieci co podane w carp(4) parametry ipaddress i mask
advbase
Jest to opcjonalny parametr określający jak często (w sekundach), rozgłaszać że należymy do grupy. Wartością domyślną jest 1 sekunda. Dopuszczalnymi wartościami są liczby od 1 do 255.
advskew
Opcjonalny parametr określający jak bardzo zniekształcić advbase przy wysyłaniu rozgłoszenia CARP. Poprzez manipulację parametrem advskew możemy wybierać główny host CARP. Im wyższa jest jego wartość, tym mniej będzie dany host preferowany przy wyborze następnego hosta głównego. Wartość domyślna to 0. Dopuszczalne wartości: od 0 do 254.
state
Wymusza określony stan na interfejsie cart(4). Poprawne stany to init, backup, i master.
ipaddress
Jest to współdzielony adres IP przeznaczony dla grupy redundantnej. Adres ten nie musi należeć do tej samej podsieci co adres IP na fizycznym interfejsie (jeżeli jest podany)
mask
Netmaska podsieci współdzielonego IP.

Poniższe zachowania CARP są ustawiane przez sysctl(8).

net.inet.carp.allow
Akceptuj lub nie nadchodzące pakiety CARP. Domyślnie jest 1 (tak).
net.inet.carp.preempt
Zezwala hostom wewnątrz grupy by posiadały lepsze advbase oraz advskew by przyśpieszyć wybór hosta głównego. Dodatkowo opcja ta włącza automatyczne awaryjne przełączenie dla wszystkich interfejsów na wypadek awarii jednego z nich. Jeżeli fizyczny interfejs na którym włączony jest CARP padnie, CARP zmieni advskew na 240 na wszystkich pozostałych interfejsach, w istocie, sam siebie przełącza awaryjnie. Opcja ta domyślnie ustawiona jest na 0 (wyłączona).
net.inet.carp.log
Loguje złe pakiety CARP. Domyślnie jest 0 (wyłączone).
net.inet.carp.arpbalance
Rozkłada obciążenie ruchu poprzez wiele hostów w grupie. Domyślnie jest 0 (wyłączone). Więcej informacji znajdziesz w carp(4).

Przykład CARP

Przykład konfiguracji CARP-a:
# sysctl -w net.inet.carp.allow=1
# ifconfig carp1 create
# ifconfig carp1 vhid 1 pass mekmitasdigoat carpdev em0 \
    advskew 100 10.0.0.1 netmask 255.255.255.0

Ustawienia te powodują:

Uruchomienie ifconfig dla carp1 pokaże status tego interfejsu.

# ifconfig carp1
carp1: flags=8802<UP,BROADCAST,SIMPLEX,MULTICAST> mtu 1500
     carp: BACKUP carpdev em0 vhid 1 advbase 1 advskew 100
     groups: carp
     inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255

Wprowadzenie do pfsync

Interfejs sieciowy pfsync(4) ujawnia pewne zmiany wykonane w tabeli stanów pd(4). Monitorując to urządzenie przy pomocy tcpdump(8), możemy w czasie rzeczywistym obserwować zmiany w tabeli stanów. Ponadto interfejs pfsync(4) pozwala wysyłać wiadomości ze zmiany stanów, w ten sposób pozostałe stacje z pracującym PF mogą włączać te zmiany do własnych tablic stanów. Podobnie pfsync(4) może nasłuchiwać w sieci na nadchodzące wiadomości.

Działanie pfsync

Domyślnie pfsync(4) nie wysyła i nie odbiera z sieci uaktualnień tablicy stanów; jednakże, uaktualnienia mogą być wciąż monitorowane przy pomocy tcpdump(8) lub innego narzędzia uruchomionego na lokalnej maszynie.

Gdy pfsunc(4) jest ustawiony na wysyłanie i odbieranie uaktualnień, domyślnym zachowaniem jest wysyłanie mutlicastowe uaktualnień. Wszystkie uaktualnienia wysyłane są bez uwierzytelniania. Najlepszymi powszechnymi praktykami są:

  1. Połączenie dwóch stacji tak by wymieniały aktualizacje back-to-back korzystając z kabla krosowanego i wykorzystanie tego interfejsu jako syncdev (zobacz poniżej).
  2. Wykorzystanie opcji syncpeer w ifconfig(8) (zobacz poniżej) tak że aktualizacje są kierowane bezpośrednio do peera, następnie skonfigurowanie ipsec(4) pomiędzy hostami do zabezpieczenia ruchu z pfsync(4).

Kiedy aktualizacje są wysyłane i odbierane, pakiety pfsync powinny być przepuszczane przez reguły filtra:

pass on $sync_if proto pfsync

$sync_if powinien być fizycznym interfejsem przez który komunikuje się pfsync(4).

Konfiguracja pfsync

Ponieważ pfsync(4) jest interfejsem wirtualnym, jest konfigurowany przy pomocy polecenia ifconfig(8).
ifconfig pfsyncN syncdev syncdev [syncpeer syncpeer]
pfsyncN
Nazwa interfejsu pfsync(4). Interfejs pfsync0 jest dostępny domyślnie w jądrze standardowym GENERIC.
syncdev
Nazwa fizycznego interfejsu wykorzystywanego do wysyłania uaktualnień pfsync.
syncpeer
Dodatkowy parametr określający adres IP hosta z którym wymieniane są uaktualnienia pfsync. Domyślnie aktualizacje pfsync wysyłane są multicastem do sieci lokalnej. Opcja ta nadpisuje domyślne zachowanie w zamian wysyłając uaktualnienia do określonego hosta: syncpeer.

Przykład pfsync

Przykładowa konfiguracja pfsync:
# ifconfig pfsync0 syncdev em1
Następuje włączenie pfsync na interfejsie em1. Wychodzące uaktualnienia będą wysyłane mutlicastem do sieci zezwalając by każdy host mógł je odebrać.

Połączenie CARP i pfsync (failover oraz redundancja)

Łącząc właściwości CARP i pfsync, oraz grupę dwóch lub więcej zapór ogniowych, można stworzyć wysoce niezawodny, w pełni redundantny klaster zapór ogniowych.
CARP:
Utrzymuję automatyczne failover z jednej zapory na inną.
pfsync:
Synchronizuje tablice stanów pomiędzy wszystkimi zaporami. W przypadku konieczności automatycznego przełączenia na inną maszynę, ruch będzie mógł następować nieprzerwanie przez nową główną zaporę.

Przykładowy scenariusz. Dwie zapory, fw1 i fw2.

	     +----| WAN/Internet |----+ 
	     |                        |
	  em2|                        |em2   
	  +-----+                  +-----+
	  | fw1 |-em1----------em1-| fw2 |
	  +-----+                  +-----+
	  em0|                        |em0
	     |                        | 
          ---+-------Shared LAN-------+---

Zapory połączone są back-to-back kablem krosowany, na interfejsach em1 Oba połączone są do sieci LAN poprzez interfejsy em0 oraz z siecią WAN/Internet poprzez interfejsy em1. Poniżej znajdują się wykorzystywane adresy IP:

Polityka sieci zakłada że fw1 będzie preferowaną zaporą główną.

Konfigurujemy fw1:
! enable preemption and group interface failover
# sysctl -w net.inet.carp.preempt=1

! configure pfsync
# ifconfig em1 10.10.10.1 netmask 255.255.255.0
# ifconfig pfsync0 syncdev em1
# ifconfig pfsync0 up

! configure CARP on the LAN side
# ifconfig carp1 create
# ifconfig carp1 vhid 1 carpdev em0 pass lanpasswd \
    172.16.0.100 netmask 255.255.255.0
     
! configure CARP on the WAN/Internet side
# ifconfig carp2 create
# ifconfig carp2 vhid 2 carpdev em2 pass netpasswd \
    192.0.2.100 netmask 255.255.255.0

Konfigurujemy fw2:
! enable preemption and group interface failover
# sysctl -w net.inet.carp.preempt=1

! configure pfsync
# ifconfig em1 10.10.10.2 netmask 255.255.255.0
# ifconfig pfsync0 syncdev em1
# ifconfig pfsync0 up

! configure CARP on the LAN side
# ifconfig carp1 create
# ifconfig carp1 vhid 1 carpdev em0 pass lanpasswd \
    advskew 128 172.16.0.100 netmask 255.255.255.0

! configure CARP on the WAN/Internet side
# ifconfig carp2 create
# ifconfig carp2 vhid 2 carpdev em2 pass netpasswd \
    advskew 128 192.0.2.100 netmask 255.255.255.0

Zagadnienia związane z działaniem CARP/pfsync

Niektóre napotkane zagadnienia związane z działaniem CARP/pfsync.

Konfiguracja CARP oraz pfsync podczas startu

Ponieważ carp(4) oraz pfsync(4) są typami interfejsów sieciowych, mogą być konfigurowane podczas startu poprzez utworzenie właściwych plików hostname.if(5). Skrypt startowy netstart zadba o utworzenie interfejsu oraz jego skonfigurowanie.

Przykład:

/etc/hostname.carp1
inet 172.16.0.100 255.255.255.0 172.16.0.255 vhid 1 carpdev em0 \
    pass lanpasswd

/etc/hostname.pfsync0
up syncdev em1

Wymuszenie przekazania na głównej maszynie.

Mogą wystąpić sytuacje w których konieczne będzie wyłączenie lub zdegradowanie hosta głównego w jakimś celu. Przykład poniżej rozpatruje konieczność wyłączenia głównej zapory ze względu na konserwację lub wykrycie problemu. Przedmiotem tutaj jest wdzięczne przekazanie ruchu na jeden z zapasowych hostów tak by nie miało to wpływu na użytkowników.

By przekazać ruch dla określonej grupy CARP, wyłącz interfejs carp(4) na głównej zaporze ogniowej. Spowoduje to wysłanie z niej rozgłoszenia z "nieskończonymi" wartościami advbase oraz advskew Host(y) zapasowe zauważą taką informację i natychmiast przejmą zadania głównego.

# ifconfig carp1 down

Alternatywą jest zwiększenie advskew do wartości większej niż wartość advskew na hostach zapasowych. Spowoduje to awaryjne przełączenie, jednak pozwoli hostowi głównemu na przynależność do grupy CARP.

Inna metodą awaryjnego przełączania jest dostrojenie licznika degradacji CARP'a. Licznik degradacji jest odmierza "kiedy" host staje się hostem głównym w grupie CARP. Przykładowo, złym pomysłem jest by startujący właśnie host stał się głównym w grupie CARP, aż do czasu skonfigurowania wszystkich interfejsów, uruchomienia wszystkich daemonów, itp. Hosty rozgłaszające wysoką wartość degradacji będą znacznie mniej preferowanie w elekcji głównego.

Licznik degradacji przechowywany jest w każdym interfejsie grupy do której należy dany interfejs. Domyślnie, wszyskie interfejsy CARP należą do grupy interfejsów "carp". Aktualną wartość licznika degradacji można sprawdzić korzystając z polecenia ifconfig(8):

# ifconfig -g carp
carp: carp demote count 0

W tym przykładzie pokazana została zawartość licznika powiązanego z grupą interfejsów "carp". Gdy host CARP rozgłasza się w sieci, bierze sumę liczników degradacji dla każdej grupy interfejsów carp(4) do których on należy i rozgłasza tą wartość jako wartość degradacji.

Rozważmy poniższy przykład. Dwie zaporty sieciowe działające z CARP z poniższymi interfejsami CARP:

Celem jest zapewnienie przełączenia tylko grup carp1 i carp2 na drugą zaporę.

Najpierw, przydzielmy każdy z nich do nowej grupy, w tym przypadku nazywanej "internal":

# ifconfig carp1 group internal
# ifconfig carp2 group internal
# ifconfig internal
carp1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
     carp: MASTER carpdev em0 vhid 1 advbase 1 advskew 100
     groups: carp internal
     inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255
carp2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
     carp: MASTER carpdev em1 vhid 2 advbase 1 advskew 100
     groups: carp internal
     inet 10.0.1.1 netmask 0xffffff00 broadcast 10.0.1.255

Zwiększymy teraz wartość licznika degradacji dla grupy "internal" przy pomocy ifconfig(8):

# ifconfig -g internal
internal: carp demote count 0
# ifconfig -g internal carpdemote 50
# ifconfig -g internal
internal: carp demote count 50

Teraz nasz firewall przełączy się gładko z grupami carp1 i carp2 na drugą maszynę w klastrze wciąż pozostając hostem głównym dla carp3 i cart4. Gdyby drugi firewall zaczął się rozgłaszać z degradacją większą niż 50, lub gdy gdy drugi firewall przestał się rozgłaszać, wowczas obecna maszyna stała by się ponownie rolę głównej dla carp1 i carp2.

Aby powrócić do pierwotnego firewall'a, odwracamy zmiany:

# ifconfig -g internal -carpdemote 50
# ifconfig -g internal
internal: carp demote count 0

Daemony sieciowe jak OpenBGPD czy sasyncd(8) korzystają z licznika degradacji aby się upewnić, że firewall nie stanie się masterem aż do czasu nawiązania sesji BGP i synchronizacji IPsec SA.

Sztuczki z zestawami reguł

Filtrowanie fizycznego interfejsu. Tak daleko jak PF jest rozpatrywany, ruch sieciowy nadchodzi z fizycznego interfejsu, a nie z wirtualnego interfejsu CARP (tj. carp0). Zatem, pisz swoje reguły stosownie do tego. Nie zapominaj że nazwa interfejsu w PF może być zarówno nazwą fizycznego interfejsu jak i adresu związanego z tym interfejsem. Przykładowo, poniższa reguła może być poprawna:
pass in on fxp0 inet proto tcp from any to carp0 port 22
lecz zastąpienie fxp0 carp0 może działać nie tak jak to zaplanowałeś.

NIE zapominaj zezwalać na proto carp and proto pfsync!

Pozostałe źródła

Prosimy zapoznaj się z innymi źródłami po więcej informacji:

[Wstecz: Authpf: powłoka dla bramek uwierzytelniających] [Spis treści] [Dalej: Zapora ogniowa dla domu lub małego biura]


[back] www@openbsd.org
$OpenBSD$