[Wstecz: Translacje adresów (NAT)] [Spis treści] [Dalej: Skracanie zestawów reguł]
Oto bardzo prosty przykład:
rdr on tl0 proto tcp from any to any port 80 -> 192.168.1.20
Powyższa linijka przekierowuje ruch przeznaczony do portu 80 TCP (serwer www) do maszyny o adresie 192.168.1.20 wewnątrz sieci lokalnej. Pomimo tego, że adres 192.168.1.20 jest adresem wewnętrznym, można uzyskać do niego dostęp z Internetu.
Fragment from any to any w regułce rdr można dodatkowo zmodyfikować - jeśli wiadome jest które sieci powinny mieć dostęp do komputera wewnątrz sieci lokalnej na porcie 80, można to zastrzec w tej regułce:
rdr on tl0 proto tcp from 27.146.49.0/24 to any port 80 -> \
192.168.1.20
Pozwoli to na korzystanie z przekierowań tylko wyselekcjonowanym podsieciom. Jak można się domyśleć, można przekierowywać ruch do różnych miejsc docelowych w zależności od jego źródła. W niektórych przypadkach może to być naprawdę użyteczne. Dla przykładu, można mieć użytkowników, którzy posiadać będą dostęp do innej maszyny w sieci w zależności od adresu z pod którego się łączą:
rdr on tl0 proto tcp from 27.146.49.14 to any port 80 -> \
192.168.1.20
rdr on tl0 proto tcp from 16.114.4.89 to any port 80 -> \
192.168.1.22
rdr on tl0 proto tcp from 24.2.74.178 to any port 80 -> \
192.168.1.23
Poprzez taką samą regułę możliwe jest przekierowanie zakresu portów:
rdr on tl0 proto tcp from any to any port 5000:5500 -> \
192.168.1.20
rdr on tl0 proto tcp from any to any port 5000:5500 -> \
192.168.1.20 port 6000
rdr on tl0 proto tcp from any to any port 5000:5500 -> \
192.168.1.20 port 7000:*
Przykłady te pokazują przekierowanie portów od 5000 do 5500 (włącznie) do 192.168.1.20. W regule #1, port 5000 jest przekierowywany do 5000, 5001 do 5001, itd. W regule #2, pełny zakres portów jest przekierowywany do portu 6000. Oraz w regule #3, port 5000 jest przekierowywany do 7000, 5001 do 7001, itd.
Jedynym wyjątkiem jest sytuacja, gdy w regule rdr użyte jest słowo kluczowe pass. W tym przypadku, przekierowane pakiety będą przepuszczane "stanowo" (statefully) przez filtr: reguły filtra nie będą uwzględniane przeciw tym pakietom. Jest to pomocny skrót pozwalający uniknąć umieszczania reguł pass dla każdej przekierowującej reguły. Pomyśl o tym jako o normalnej regule rdr (bez klucza pass) skojarzonej z regułą pass z kluczem keep state. Jednak jeżeli chcesz użyć bardziej specyficznych opcji filtrowania, takich jak synproxy, modulate state, itd., wciąż będziesz musiał użyć dedykowanej reguły pass gdy opcje te nie pasują do reguł przekierowujących.
Pamiętaj, że ponieważ translacje mają miejsce przed filtrowaniem, filtr będzie widział przekierowane pakiety po zamianie ich docelowych adresów IP/portów zgodnie z daną regułą rdr. Aby lepiej to zrozumieć proszę przyjrzeć się temu przykładowi:
Regułka przekierowania:
rdr on tl0 proto tcp from 192.0.2.1 to 24.65.1.13 port 80 \
-> 192.168.1.5 port 8000
Pakiet przed przejściem przez regułkę rdr:
Pakiet po przejściu przez regułkę rdr:
Zanim datagramy trafią do filtra pakietów, będą już miały zmieniony adres docelowy zgodnie z regułą przekierowującą.
Takie ryzyko może zostać zmniejszone poprzez wydzielenie systemów dostępnych z zewnątrz i umieszczenie ich w wydzielonej sieci. Często tego typu sieć nazywa się Strefą Zdemilitaryzowaną (Demilitarized Zone - DMZ) lub siecią prywatną (Private Service Network - PSN). W tej sytuacji, jeśli zabezpieczenia serwera www zostaną przełamane, konsekwencje z tym związane ograniczą się jedynie do sieci DMZ/PSN, oczywiście jeśli będziemy ostrożnie filtrować ruch wchodzący i wychodzący sieci DMZ/PSN.
server = 192.168.1.40
rdr on $ext_if proto tcp from any to $ext_if port 80 -> $server \
port 80
Sprawdzając poprawność działania takiej regułki z komputera umieszczonego w sieci lokalnej okaże się, że wydaje się ona nie działać. Przyczyną jest to, że regułka przekierowująca określa interfejs wejściowy dla pakietów ($ext_if - zewnętrzny interfejs). Połączenie z zewnętrznym adresem komputera z firewallem z komputera w sieci lokalnej wcale nie oznacza, że pakiety muszą wędrować przez zewnętrzny interfejs. Stos TCP/IP firewalla porównuje adres przeznaczenia przychodzących pakietów z własnymi adresami oraz ich aliasami, wykrywając w ten sposób połączenia do siebie samego w momencie, gdy przeszły tylko przez wewnętrzny interfejs. Takie pakiety fizycznie nie wędrują przez zewnętrzny interfejs, a stos TCP/IP nie symuluje w żaden sposób takiej sytuacji. PF nigdy nie widział tych pakietów na zewnętrznym interfejsie i dlatego właśnie regułka przekierowująca, wyłapująca pakiety wędrujące do zewnętrznego interfejsu nie akceptuje połączeń pochodzących z sieci LAN.
Dodanie drugiej regułki przekierowującej nie rozwiąże w tym przypadku problemu. Gdy klient z sieci lokalnej łączy się z zewnętrznym adresem IP firewalla pakiet inicjujący połączenie TCP dochodzi do maszyny z firewallem przez wewnętrzny interfejs. Nowa regułka przekierowująca akceptuje ten pakiet i adres docelowy zostaje zastąpiony adresem lokalnego serwera. Pakiet zostaje przekierowany ponownie na wewnętrzny interfejs i dociera do serwera. Jednak nie został przetłumaczony adres źródłowy i zawiera on adres klienta, więc serwer odeśle odpowiedź bezpośrednio do niego. Firewall nigdy nie dostanie odpowiedzi od serwera, którą mógłby poprawnie przesłać z powrotem do klienta, co spowoduje, że klient otrzyma pakiet TCP ze źródła, którego się nie spodziewał i go odrzuci, nawiązywanie połączenia nie powiedzie się.
Często wymaga się, aby hosty w sieci LAN mogły łączyć się z tym samym serwerem lokalnym tak jak hosty z zewnątrz, transparentnie (bez dodatkowej wiedzy o faktycznym adresie oraz położeniu serwera). Oto kilka pomysłów, które mogą pomóc w rozwiązaniu problemu:
Możliwe jest skonfigurowanie serwera DNS tak, aby odpowiadał na zapytania z sieci lokalnej inaczej niż na zapytania z zewnątrz, tak więc klient w sieci lokalnej może otrzymać od serwera nazw adres lokalny serwera. Połączy się wtedy z nim bezpośrednio, bez zaangażowania w tę operację firewalla. Zredukuje to ruch, ponieważ pakiety nie będą niepotrzebnie wędrowały przez firewall.
Dołączenie dodatkowego interfejsu sieciowego do komputera z firewallem i przeniesienie serwera do takiej sieci dedykowanej (DMZ) pozwoli na przekierowywanie połączeń od lokalnych klientów w taki sam sposób jak klientom z zewnątrz. Wykorzystanie odseparowanej sieci ma kilka innych zalet, włączając zwiększenie bezpieczeństwa poprzez odseparowanie serwera także od klientów lokalnych. Jednakże należy pamiętać o tym, że w takim przypadku nasz serwer nie będzie miał bezpośredniego dostępu do hostów lokalnych - wszystkie połączenia będą musiały przejść przez firewall.
TCP proxy może być skonfigurowany na hoście, na którym pracuje firewall, nasłuchując na porcie który ma zostać przekierowany oraz przechwytując połączenia z interfejsu lokalnego i przekierowywać je do portu, na którym nasłuchuje. Gdy lokalny klient łączy się z firewallem, proxy akceptuje połączenie otwierając drugie połączenie z serwerem i przekierowując ruch pomiędzy ustanowionymi połączeniami.
Proste proxy można zrobić korzystając z inetd(8) oraz nc(1). Poniższy wpis w /etc/inetd.conf tworzy gniazdo nasłuchujące przypisane do adresu loopback (127.0.0.1) oraz portu 5000. Połączenia przekierowywane są do portu 80 serwera o adresie 192.168.1.10.
127.0.0.1:5000 stream tcp nowait nobody /usr/bin/nc nc -w \
20 192.168.1.10 80
Poniższa regułka PF przekierowuje ruch portu 80 na wewnętrznym interfejsie do proxy:
rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
127.0.0.1 port 5000
Można również uzyskać translację adresu źródłowego poprzez wprowadzenie dodatkowej regułki NAT dotyczącej wewnętrznego interfejsu.
rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
$server
no nat on $int_if proto tcp from $int_if to $int_net
nat on $int_if proto tcp from $int_net to $server port 80 -> \
$int_if
Spowoduje to, że inicjalizujący połączenie pakiet pochodzący od klienta, zostanie ponownie poddany NAT w chwili, gdy zostanie przekierowany na zewnętrzny interfejs, adres źródłowy klienta zostanie zamieniony na adres interfejsu wewnętrznego serwera. Serwer prześle swoją odpowiedź do firewalla, który potrafi zamienić regułkę RDR na NAT gdy klientem jest host w sieci lokalnej. Taka konstrukcja jest dość złożona dzięki temu, że tworzy dwa oddzielne stany dla każdego połączenia. Trzeba zwrócić uwagę na odpowiednią konfigurację NAT w taki sposób, aby regułki nie akceptowały innych pakietów niż te, które dopuszczasz, dla przykładu, połączenia pochodzące od hostów z poza naszej sieci lub samego firewalla. Zauważ, że regułka rdr powyżej, spowoduje, że stos TCP/IP będzie widział pakiety przychodzące do wewnętrznego interfejsu z adresem docelowym naszej sieci lokalnej.
Dla większości przypadków, rozwiązania omawiane powyżej są w zupełności wystarczające.
[Wstecz: Translacja adresów (NAT)] [Spis treści] [Dalej: Skracanie zestawów reguł]