[Wstecz: Translacje adresów (NAT)] [Spis treści] [Dalej: Filtrowanie pakietów]
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
Regułka przekierowania:
rdr on tl0 proto tcp from 192.0.2.1 to 24.65.1.13 port 80 \
-> 192.168.1.5 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 przez regułkę rdr.
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 zabezpiecznia 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:
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
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 inetrfejsu 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 loaklnej. 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. Aby zapobiec generowaniu informacji o przekierowaniach ICMP przez stos (mówiących klientowi, że serwer jest dostępny lokalnie) należy włączyć przekierowania na bramce:
# sysctl -w net.inet.ip.redirect=0
# sysctl -w net.inet6.ip6.redirect=0 (w przypadku wykorzystywania IPv6)
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: Filtrowanie pakietów]