Alpine Linux jako bramka sieciowa
Ostatnio budowaliśmy bramkę w oparciu o system OpenBSD, nie było to jakoś trudne zdanie. Teraz zajemiemy się tym samym zagadniem co poprzednio, tylko że z systemem GNU/Linux. Do tego celu wybrałem kolejną dystrybucje, która jest nieco bardzie podrasowana jeśli chodzi o bezpieczeństwo, prosto z Norwegii, Alpine Linux. Ciekawą rzeczą w tej dystrybucji jest to że możemy zainstalać usługę, która umożliwi nam kontrolowanie naszego systemu z poziomu przeglądarki. Nie ma się co napalać, jak szczerbaty na suchary, ale to zawsze coś. Może pojawi się tutaj jakiś materiał odnośnie ACF, bo tak to się dokładnie nazywa. Pozwole sobie tutaj na nawiązania do materiału o robieniu bramki z OpenBSD, pozowoli to ograniczyć wypełniacz merytoryczny, przez co ten artykuł będzie znacznie krótszy.
Uwaga! Wszystkie znajdujące się tu polecenia wykonujemy z poziomu użytkownika root.
- Instalacja systemu
Instalacja Alpine Linux została już tutaj przedstawiona jednym z umieszczonych tutaj materiałów. Podobnie jak na OpenBSD jeśli czytamy to jeszcze przed rozpoczęciem jakich kolwiek prac, to ustawienia interfejsów sieciowych możemy skonfigurować już na poziomie instalatora.
- Instalacja niezbędnego oprogramowania
Menedżerem pakietów w Alpine jest program APK, jak rozszerzenie paczek oprogramowania na Androidzie. Dystrybucja po instalacji pozostaje natywnie pusta, aby dać użytkownikowi jak największe pole do manewru. Do zainstalowania mamy aż trzy pakiety: ISC DHCPD - dhcp, dnsmasq, iptables. Aby użyć polecenia
apk
do instalacji pakietów należy użyć opcjiadd
następnie po niej podać nazwę interesującego nas pakietu.# apk add dhcp dnsmasq iptables
Po zainstalowaniu potrzebnych usług oraz programów, możemy przejść do ich konfiguracji. Na początek, tak samo jak przy OpenBSD skupimy się na DHCP.
- Konfiguracja DHCP
Aby daemon DHCP mógł odczytać nasz plik konfiguracji musimy nazwać dhcpd.conf i umieścić w katalogu /etc/dhcpd. Konfiguracja tutaj jest identyczna do tej jaką tworzliśmy na dla OpenBSD, ponieważ jest to ten sam program. Dla leniwych, którym nie chce się przejrzeć tamtego artykułu i dla samej zapachajdziury, opisze linia po linii konfiguracje DHCP.
subnet 192.168.0.0 netmask 255.255.255.0 { range 192.168.0.100 192.168.0.199; option routers 192.168.0.1; option domain-name "morketsmerke.net"; option domain-name-servers 192.168.0.1; }
Pierwsza linia otwiera nam deklaracje pod sieci, po słowie
subnet
występuje adres sieci, z kolei po słowienetmask
maska sieciowa. W następnej linii deklarowany jest zakres adresów przeznaczonych dla hostów w naszej sieci.option routers
będzie przekazywać taki parametr adres bramy domyślnej,option domain-name
zawiera sufiks DNS dla naszych hostów a ostatnia liniaoption domain-name-servers
zawiera adresy serwerów DNS, może być ich wiele, jednak nie wszystkie systemu obsługują więcej niż dwa adresy. W przykłdzie znajduje się tylko jedna sieć jeśli nasza bramka ma obsługiwać więcej sieci to deklaracje można powtórzyć oczywiście dostosowując ją do adresacji zastosowanej w owej sieci.Jako ciekawostkę albo nieco bardzie zaawansowaną konfiguracje podam że rezerwacje adresów, które wyglądają o tak:
host admin-komputer { hardware ethernet 00:de:ad:be:ef:00; fixed-address 192.168.0.10; option host-name "admtop"; }
Rezerwacje mogą zupełnie wybiegać poza zakres, a daemon i tak nada zarezerwowane adresy tym komputerom.
- Konfiguracja daemona DHCP
Do uruchomienia daemona w Alpine Linux wykorzystywany jest jeszcze jeden plik /etc/conf.d/dhcpd. W tym pliku musimy ustawić dwie zmienne
DHCPD_CONF
orazDHCPD_IFACE
, aby je ustawić nadajemy im wartość i usuwamy poprzedzający je znak komentarza. Jakie wartości należy im nadać? Otóż zmiennaDHCPD_CONF
przechowuje ścieżkę to pliku konfiguracyjnego. Wartość tej zmiennej może już wskazywać na nasz pliki, jeśli nie to należy to skorygować. ZmiennaDHCPD_IFACE
, przechowuje interfejsy na jakich nasłuchiwać ma nasze DHCPD.DHCPD_CONF="/etc/dhcpd/dhcpd.conf"; DHCPD_IFACE="eth0 eth1";
- Ustawienie interfejsu dla dnsmasq
Podobnie do konfiguracji zastosowanej w OpenBSD i w tym przypadku jeśli dnsmasq ma nam służyć tylko i wyłącznie jako maskarada DNS lub przekaźnik (bo taką rolę pełni) to nie potrzeba w zasadzie nic konfigurować, jedne co należy zrobić to wskazać odpowiednie interfejsy. W pliku konfiguracyjnym odnajdujemy opcje
#interface
jest ujęta w komentarz aby ją włączyć musimy usunąć znak komentarza, a po znaku równości (=) wpisać nazwę interfejsu.interface=eth1
Następnie zapisujemy oraz restartujemy usługę, tutaj warto wspomnieć, że Alpine Linux jest dystrybucją opartą na OpenRC, a więc restart usługi odbywa się jak w starych systemach GNU/Linux.
# /etc/init.d/dnsmasq restart
Identycznie jak przy OpenBSD, jeśli chcemy wymusić nasłuchiwanie na konkretnym interfejsie, musimy odblokować opcję
bind-interfaces
.bind-interfaces
- Ewentualne wpisy do /etc/hosts*
Wykorzystując plik /etc/hosts na naszej bramce możemy zdefiniować nazwy domenowe dla naszych serwerów w sieci lokalnej. Przeważnie w konfiguracji odpytywania UNIX-y skonstrułowane są w taki sposób że na początku sprawdzają zawartość tego pliku, i jeśli nie znajdą odpowiedniego dla zapytania rekordu, kierują zapytanie do swoich adresów DNS. Format wpisu jest taki sam dla wszystkich UNIX-ów, składa się on z trzech części: adresu IP, FQDN (pełnej nazwy domenowej), hostname (nazwy hosta). Nazw hosta możemy używać tylko jeśli na naszym komputerze został został zdefiniowany sufiks DNS. Przykładowy wpis znajduje się poniżej:
192.168.0.10 serwer.morketsmerke.net serwer
- NAT
Podbnie jak w przypadku PF (pakiet firewalla na OpenBSD) NAT to jedna reguła. Reguła, która do poprawnego działania wymaga przestawienia opcji jądra, opcji przekazywania pakietów z jednego interfejsu na drugi wewnątrz systemu. Poniżej znajdują się polecenia jakie należy wykonać aby uruchomić NAT.
# iptables -t NAT -A POSTROUTING -o eth0 -j MASQUERADE # echo 1 > /proc/sys/net/ipv4/ip_forward
Pierwsze polecenie jest ustawieniem reguły pakietu zapory sieciowej na GNU/Linux, którą jest iptables. Przy iptables reguły dodawane są na bieżąco, a co za tym idzie będą tak długo załadowane jak długo uruchomiony jest system. To jest jedna z różnic pomiędzy PF a iptables. Do trwałego zapisania reguł będzie potrzebny nam zewnętrzny pakiet. Tym zajmiemy się na koniec. Teraz przejdźmy samej reguły. Przełącznik
-t
wskazuje nam tablice - zbióry reguł stosowane na podstawie przeznaczenia pakietów. Na przykład reguły podejmujące działania pakietach wygenerowanych przez bramkę lub do niej zaadresowane zostaną zdefiniowane w innej tablicy niż te które mają działać na pakietach, które przez tą bramkę przechodzą. Nas będą interesować tylko tablicefilter
(tablica domyślna), która zajmuje się pakietami z i do bramki oraz tablicanat
, zajmująca się pakietami przecodzącymi przez bramkę. W iptables są jeszcze dwie tablice, jednak na nie są nam one potrzebne także ich opis pominę. Opcja-A
spowoduje dopisanie naszej reguły na końcu łańcucha. Łańcuchy są to podzbiory reguł, których cechą charkterystyczną jest konkretny moment podróży pakietu za nim dotrze do aplikacji, której dane przenosi lub zostanie przesłany dalej w głąb innych sieci. Najproście zobrazować to sobie w ten sposób, że do kiedy pakiet dociera do systemu zawsze na początku trafia do łańcuchaPREROUTING
tablicynat
w tym łańcuchu dokonywane są wszelkie zmiany (akcje) dla pakietu, kiedy tylko się pojawi, może zostać przekierowany albo do łańcuchaINPUT
albo do łańcuchaFORWARD
tablicyfilter
łańcuchINPUT
przeznaczony jest dla pakietów kierowanych dla tego komputera, z kolei łańcuchFORWARD
dla tych pakietów, które przechodzą przez ten komputer. Jeśli pakiet trafił doINPUT
, wtedy trafia lokalnego procesu. Proces może odpowiedzieć, wygerowany przez proces pakiet trafia najpierw do odpowiedniego łańcucha tj.OUTPUT
tablicyfilter
następnie do łańcuchaOUTPUT
tablicynat
, gdzie mogą być dokonywane zmiany dla wygenerowaych pakietów. Tutaj obydwie ścieżki łączą się ponieważ pakiety opuszaczające łańcuchFORWARD
oraz łańcuchOUTPUT
tablicynat
są przetwarzane ostatecznie w łańcuchuPOSTROUTING
tablicynat
, czyli momencie gdy mają opuścić ten komputer. Tutaj właśnie wykorzystywana jest akcjaMASQUERADE
, która zapisaliśmy w pierwszym poleceniu, po łańcuchu umieszczony jest przełącznik-o
określający interfejs wyjściowy (nasz interfejs podłączony do internetu). Ostatnią składową jest reguły jest cel/akcja (po przełączniku-j
) podejmowana na pakiecie, kiedy zostaje dopasowany do reguły. Podsumowując pakiety przechodzą z tablicy do tablicy z łańcucha do łańcucha w poszukiwaniu pasujących reguł, kiedy reguła zostanie dopasowana wtedy podejmowany jest dla pakietu cel/akcja, może być onaACCEPT
lubDROP
lub specjalna jakMASQUERADE
.Odnośnie zamiany adresów czyli właśnie NAT-u to istnieją dwa sposoby. Jeśli nasz adres na interfejsie podłączonym do sieci rozległej/Internetu jest przydzielany dynamicznie powinniśmy użyć własnie
MASQUERADE
jeśli nasz adres jest stały, to wtenczas należało by użyćSNAT
a następnie podać za pomocą dodatkowej opcji--to-source
adres jakie należy użyć podczas NAT-u.# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 10.20.40.34
Drugie polecnie nie jest już tak skomplikowane, uruchamia ono przekazywanie pakietów wewnątrz systemu.
- Zapisanie reguł do pliku
Niestety reguły iptables są przechowywane w łańcuchach do momentu kolejnego uruchomienia komputera. W Alpine Linux wraz z iptables otrzymujemy polecenie
iptables-save
, którego uruchomienie spowoduje wyświetlenie nam tablic z łańcuchami w formacie, który poźniej pozwoli na ich automatyczne przywrócenie, aby całość zadziałała po ustawieniu NAT-u należy przekierować wyjście tego właśnie polecenia do pliku /etc/iptables/rules-save. Przy zapisie reguł warto pamiętać o tym że włączenie przekazywania pakietów w systemie też powinno się odbywać automatycznie. Możemy zrobić to na dwa sposoby. Pierwszy z nich to dopisanie opcjinet.ipv4.ip_forward = 1
do pliku /etc/sysctl.d/00-alpine.conf lub skorzystać z konfiguracji iptables w /etc/conf.d/iptables, gdzie powinniśmy znaleźć opcjeIPFORWARD
, która należy przestawić nayes
. - Ustawienie autostartu usług
Alpine Linux jest dystrybucją, która została nieco inaczej zbudowana niż te powszechnie nam znane, w których programem typu init jest moloch systemd, który automatycznie załącza znane usługi do startu wraz z systemem, najwyżej usługa nie wystartuje z powodu braku konfiguracji. Tutaj programem typu init jest OpenRC, gdzie sytuacja nie jest już tak kolorowa. Nie ma jednak tragedii - "Not great, not terrible". Aby włączyć uruchamie konkretnych usług przy użyciu OpenRC jako programu init, wystarczy wydać konkretne polecenie jak te przedstawione poniżej:
# rc-update add dnsmasq default # rc-update add dhcpd default # rc-update add iptables default
Jak widać na powyższej liście stworzenie prostej bramki opartej dobry system GNU/Linux, nie jest jakoś bardzo skomplikowane, wymaga wydania kilku poleceń oraz wyedytowania kilku plików. Dla mnie, gdzie mam trochę wprawy dużo rzeczy wydaje się banalnych, ale jeśli spojrzał bym kilka lat wstecz to już samo zagadnienie budowania bramki na GNU/Linux było by sporą abstrakcją, co dopiero na systemie, który trochę odbiega nurtu głównych dystrybucji takich jak GNU/Linux Debian czy CentOS. Serio, dla mnie łatwiejsze było nauczenie się zupełnie innego systemu operacyjnego oraz zupełnie innego pakietu zapory niż zabranie się za iptables, i mimochodem znając nieco bardziej iptables niż wtedy to pozostał bym wierny OpenBSD oraz PF.
~xf0r3m