[OpenBSD]

[Wstecz: Authpf: powłoka dla bramek uwierzytelniających] [Spis treści]

PF: Przykład 1: Firewall dla sieci domowej lub małego biura


Spis treści


Wstęp

W tym FAQ zostanie omówiony przykład wykorzystania maszyny z OpenBSD i działającym PF do zbudowania firewalla i bramki NAT dla niewielkiej sieci w domu lub biurze. Głównym celem jest udostępnienie połączenia z Internetem komputerom w sieci wewnętrznej, a także umożliwienie ograniczonego dostępu z Internetu do maszyny spełniającej rolę ściany ogniowej. Kompletny przykład będzie można znaleźć na końcu tego dokumentu.

Sieć

Topologia sieci wygląda następująco:
    
  [ KOMP1 ]    [ KOMP3 ]
      |            |                               ADSL
   ---+------+-----+------- fxp0 [ OpenBSD ] ep0 -------- ( Internet )
             |
         [ KOMP2 ]

Do sieci wewnętrznej przyłączonych jest kilka maszyn, co prawda na schemacie zaznaczone są trzy, ale w tym przypadku ich ilość nie ma żadnego znaczenia. Komputery te wykorzystywane są do codziennych zadań takich jak: przeglądanie stron www, wysyłanie poczty elektronicznej, rozmów, itd. Przestrzeń adresowa sieci wewnętrznej zawiera się w bloku 192.168.0.0 / 255.255.255.0.

Router zbudowany na bazie OpenBSD to komputer z procesorem Pentium 100 i dwiema kartami sieciowymi: 3Com 3c509B (ep0) i Intel EtherExpress Pro/100 (fxp0). Połączony jest on z Internetem łączem ADSL, a do udostępniania połączenia innym komputerom wykorzystywany jest NAT. Adres IP dla zewnętrzenego interfejsu uzyskiwany jest dynamicznie od Dostawcy Usług Internetowych.

Założenia

Założenia, którymi należy kierować się przy budowie regułek filtrowania:

Wymagania

Podczas pisania tego FAQ przyjęto, że OpenBSD został poprawnie skonfigurowany do przyszłej pracy jako router, włączając w to właściwe przygotowanie sieci, połączenia z Internetem, oraz ustawienia zmiennej sysctl net.inet.ip.forwarding na "1".

Budowanie zestawu reguł

Wykonanie poleceń zawartych w następujących podrozdziałach zaowocuje otrzymaniem kompletnego zestawu reguł spełniającego wszystkie warunki podane powyżej.

Makra

Poniższe makra mają na celu ułatwienie zrozumienia oraz usprawnienie zarządzania zestawem reguł:
int_if = "fxp0"
ext_if = "ep0"

tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"

priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"

Pierwsze dwie linie określają na jakich interfejsach będzie odbywać się filtrowanie. Trzecia linia zawiera liste portów TCP (SSH i ident/auth), do których ruch z Internetu ma być przepuszczany. W czwartej linii określone są typy komunikatów ICMP, które nie będą blokowane. W ostatniej linii wyszczególnione są adresy pęlti zwrotnej oraz zarezerwowane bloki sieci opisane w RFC 1918.

Uwaga: Jeśli połączenie ADSL odbywa się poprzez PPPoE, wtedy filtrowanie oraz translacja pakietów odbywać się będzie na interfejsie tun0 a nie na ep0.

Opcje

Dwie poniższe opcje włączają domyślne odpowiedzi na zablokowane pakiety dla reguły block, a także zbieranie różnego rodzaju statystyk dla zewnętrznego interfejsu sieciowego.
set block-policy return
set loginterface $ext_if

Normalizacja pakietów

Nie istnieje żaden ważny powód dla którego nadchodzące pakiety nie miały by zostać poddane normalizacji. Włączenie normalizowania pakietów odbywa się przez dodanie jednej, prostej linii:
scrub in all

Translacja adresów

Włączenie translacji adresów (NAT) dla hostów w sieci wewnętrznej uzyskuje się przez dodanie regułki nat:
nat on $ext_if from $int_if:network to any -> ($ext_if)

Jako że adres IP dla zewnętrznego interfejsu sieciowego jest uzyskiwany dynamicznie, nazwa interfejsu na którym odbywa się mapowanie adresów została wzięty w nawiasy, dzięki temu PF zostanie powiadomione o każdej zmianie adresu.

Przekierowanie

Jedyne przekierowanie konieczne w tym zestawie reguł jest dla ftp-proxy(8), aby klient FTP w sieci lokalnej mógł bez problemów połączyć się z serwerami FTP w Internecie.
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021

Proszę zauważyć, że regułka ta obsługuje jedynie połączenia FTP na porcie 21. Jeśli zajdzie potrzeba umożliwienia korzystania z innych numerów portów, konieczne będzie podanie ich w postaci listy, na przykład: from any to any port { 21, 2121}

Regułki filtra pakietów

Po ustawieniu NAT i przekierowań można przystąpić do konfiguracji filtra pakietów. Filtr będzie pracował zgodnie z zasadą "domyślnego blokowania":
block all

W tym miescu żaden ruch nie jest przepuszczany przez scianę ogniową, nawet ten pochodzący z sieci wewnętrznej. Kolejne regułki będą umożliwiały przejście datagramów zgodnie z wytycznymi podanymi wcześniej.

Każdy system UNIX posiada intefejs pętli zwrotnej nazywany "loopback". Jest to wirtualny interfejs sieciowy używany przez procesy do komunikacji z innymi aplikacjami uruchomionymi w lokalnym systemie. Cały ruch na tym interfejsie powinnien być przepuszczany bez żadnych ograniczeń. W OpenBSD interfejs "loopback" nazywa się: lo(4).

pass quick on lo0 all

Pakiety posiadające jako adres docelowy lub źródłowy, jeden z adresów opisanych w RFC 1918, przechodzące w dowolnym kierunku przez interfejs zewnętrzny zostaną zablokowane - te adresy nigdy nie powinny pojawić się w Internecie. Wprowadzenie tych regułek daje gwarancje, że żaden z zarezerwowanych adresów nie przedostanie się do Internetu, a także zapobiega przyjmowaniu pakietów ze świata posiadających jako adres źródłowy jeden z adresów z RFC 1918.

block drop in  quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets

Należy zwrócić uwagę, że block drop określa, że filtr PF nie ma wysyłać TCP RST lub ICMP Unreachable w odpowiedzi na zablokowane pakiety. Adresy z RFC 1918 nie istnieją w Internecie, żaden pakiet wysłany pod ten adres nie dotrze do miejsca przeznaczenia. Opcja quick mówi, że PF ma przerwać sprawdzanie dalszej części zestawu jeśli pakiet pasował do tej regułki. Pakiety pochodzące lub skierowane do sieci $priv_nets będą natychmiast odrzucone.

Następna regułka otwiera porty dla usług, które mają być udostępnione w Internecie:

pass in on $ext_if inet proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

Podanie portów w postaci makra $tcp_services sprawia, że łatwo dodać kolejne usługi, które mają zostać udostępnione. Wystarczy wyedytować makro i ponownie załadować zestaw reguł. Podobnie sprawa ma się z usługami bazującymi na protokole UDP, potrzeba tylko utworzyć makro $udp_services i dodać bardzo podobną regułkę, jak ta pokazana powyżej, z opcją proto udp.

Przepuszczenie pakietów ICMP:

pass in inet proto icmp all icmp-type $icmp_types keep state

Podobnie jak makro $tcp_services, makro $icmp_types może być w łatwy sposób zmienione by umożliwić przepuszczanie innych typów pakietów ICMP przez firewall. Proszę zwrócić uwagę, że regułka ta odnosi się do wszystkich interfejsów sieciowych.

Kolejne regułki przepuszczają ruch z lub do sieci wewnętrznej. Przykład zakłada, że użytkownicy na wewnętrznym interfejsie dokładnie wiedzą co robią i nie będą powodować problemów. To niekoniecznie prawidłowe założenie, mniejsza swoboda może być bardziej odpowiednia w niektórych przypadkach.

pass in on $int_if from $int_if:network to any keep state

Powyższa regułka zezwala hostom z sieci lokalnej na wysyłanie pakietów przez scianę ogniową, nie umożliwia natomiast na nawiązanie połączenia routera z komputerem z sieci wewnętrznej. Czy to dobre rozwiązanie? Odpowiedź uzależniona jest od kilku elementów konfiguracji sieci. Jeśli firewall jest jednocześnie serwerem DHCP, przed przydzieleniem adresu konieczne może być sprawdzenie czy nie jest on już przypisany do innego hosta. Jeśli firewall ma możliwość nawiązania połączenia z maszyną w sieci lokalnej, każdy kto zaloguje się do routera będzie miał dostęp do komputrów wewnątrz sieci lokalnej. Należy jednak pamiętać, że nie jest to właściwie żadna znacząca poprawa bezpieczeństwa - jeśli ktoś niepowołany uzyska dostęp do bramki, będzie też najprawdopodobniej mógł zmienić reguły filtra pakietów. Dodanie następnej regułki sprawi, że firewall będzie mógł bez przeszkód komunikować się z maszynami w sieci wewnętrznej:

pass out on $int_if from any to $int_if:network keep state

Ważne jest to, że jeśli obie powyższe linie będą umieszczone w pliku konfiguracyjnym, dyrektywa keep state nie jest konieczna - wszystkie pakiety będą mogły wyjść poprzez zewnętrzny interfejs bez konieczności śledzenia stanów. Jednakże, jeśli linia zaczynająca się od pass out nie będzie dodana, konieczne jest umieszczenie w linii rozpoczynającej się od pass in opcji keep state. Dzięki zastosowaniu śledzenia stanów można osiągnąć pewną poprawę wydajności - tablice stanów są sprawdzane zanim datagram zostanie sprawdzony poprzez reguły, ale poprawa wydajności dotyczyć będzie w głównej mierze bardzo obciążonych filtrów, a że ten przykładowy system jest bardzo prosty, raczej mało prawdopodobne aby można było zauważyć różnice.

Ostatnie regułki zezwalają na przepuszczenie ruchu wychodzącego przez zewnętrzny interfejs sieciowy.

pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

Ruch na protokołach TCP, UDP i ICMP jest przepuszczany do Internetu, a śledzenie stanów pozwala przepuścić pakiety, które są odpowiedzią na wysłane datagramy.

Kompletny zestaw reguł

# makra
int_if = "fxp0"
ext_if = "ep0"

tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"

priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
	  
# opcje
set block-policy return
set loginterface $ext_if

# normalizacja datagramów 
scrub in all

# nat/rdr
nat on $ext_if from $int_if:network to any -> ($ext_if)
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \
   port 8021

# regułki filtra pakietów
block all

pass quick on lo0 all

block drop in  quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets

pass in on $ext_if inet proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

pass in inet proto icmp all icmp-type $icmp_types keep state

pass in  on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state

pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

[Wstecz: Authpf: powłoka dla bramek uwierzytelniających] [Spis treści]


[wstecz] www@openbsd.org
Originally [OpenBSD: example1.html,v 1.12 ]
$Translation: example1.html,v 1.7 2004/01/12 17:37:45 pl-team Exp $
$OpenBSD: example1.html,v 1.6 2004/01/16 21:01:34 jufi Exp $