Debian: Profilowanie sieci z guessnet, ifplugd i wpasupplicant

Spis treści

Kilka dni temu na forum dug.net.pl pojawił się ciekawy wątek dotyczący problemu skonfigurowania profilowanych sieci. Chodzi o to, że praktycznie każdy z nas jest po części w jakiś sposób mobilny i zabiera laptopa ze sobą w dziwne miejsca. Sieci w tych lokalizacjach mogą cechować się różnym poziomem bezpieczeństwa. Dlatego też zamiast korzystać z jednej konfiguracji sieci na linux'ie, można stworzyć szereg profili i w oparciu o nie dostosować sobie połączenie sieciowe. W tym artykule spróbujemy zaimplementować takie rozwiązanie na Debianie wyposażonym w menadżer okien Openbox. W skrócie stworzymy automat, który będzie nam działał w oparciu o pakiety guessnet, ifplugd oraz wpasupplicant. Cała konfiguracja zaś sprowadzać się będzie jedynie do edycji plików /etc/network/interfaces oraz /etc/wpa_supplicant/wpa_supplicant.conf .

Niniejszy artykuł został nieco przerobiony po fazach eksperymentów. Przede wszystkim, zrezygnowałem z zaprzęgania guessnet do rozpoznawania sieci WiFi i aplikowania roamingu. Zamiast tego zostały wykorzystane natywne rozwiązania roamingowe oferowane przez wpa_supplicant . Zaowocowało to uproszczeniem całej konfiguracji, co przełożyło się na wyeliminowanie pewnych błędów.

Potrzebne narzędzia: guessnet, ifplugd i wpasupplicant

Konfiguracja sieci musi zostać podzielona na interfejs przewodowy eth0 i bezprzewodowy wlan0 . Te dwa interfejsy będą ze sobą współpracować ale inne oprogramowanie się będzie nimi opiekować. Dlatego też każdy z tych interfejsów trzeba sobie osobno skonfigurować.

Przede wszystkim, musimy w systemie doinstalować pakiet guessnet . To za jego sprawą będzie się dokonywać profilowanie sieci przewodowej. Dzięki skryptom zawartym w tym pakiecie, nasz system będzie w stanie automatycznie wykryć środowisko w zależności od tego, gdzie się podepniemy do sieci.

Przyda się nam także pakiet ifplugd . Będzie on miał za zadanie monitorowania interfejsu przewodowego pod kątem podpięcia/odłączenia przewodu do/od portu ethernet. W taki sposób nie będziemy musieli ręcznie podnosić i kłaść interfejsu eth0 . Niemniej jednak, wymagana jest poprawna konfiguracja demona ifplugd.

Do ogarniania interfejsów bezprzewodowych w linux'ie służy pakiet wpasupplicant . Powinien być on już standardowo zainstalowany w naszym systemie. Jeśli nie jest, to koniecznie doinstalujmy ten pakiet. Za jego sprawą będziemy w stanie skonfigurować sobie roaming sieci bezprzewodowych.

Z instalacją tych powyższych narzędzi nie powinno być raczej większego problemu. Zatem przejdźmy od razu do konfiguracji wszystkich niezbędnych elementów naszego mechanizmu profilującego sieć.

Profilowanie interfejsu przewodowego w laptopie

Jak nadmieniłem we wstępie, spora część konfiguracji będzie sprowadzać się do edycji pliku /etc/network/interfaces . Musimy tylko umieścić w nim odpowiednie sekcje, które skonfigurują nam interfejs przewodowy eth0 . Poniżej jest przykład konfiguracji:

mapping eth0
    script guessnet-ifupdown
    map home-wire work-wire no_link no_network
    map default: no_network
    map timeout: 5
#   map verbose: true
#   map debug: true

iface home-wire inet dhcp
    test peer address 192.168.1.1 mac ec:08:6b:84:15:d5
    pre-up ifdown --force wlan1
    post-down ifup wlan1

iface work-wire inet dhcp
    test peer address 192.168.1.1 mac ec:08:6b:84:15:ff
    pre-up ifdown --force wlan1
    post-down ifup wlan1

iface no_link inet manual
    test missing-cable
    pre-up echo "There's no link present, please plug a cable in."
    pre-up false

iface no_network inet manual
    pre-up echo "There's no safe networks around, so I can't connect to one."
    pre-up false

Warto zaznaczyć, że nie korzystamy z opcji auto w przypadku interfejsu przewodowego. Odpowiadałaby ona co prawda za automatyczną konfigurację tego interfejsu na starcie komputera ale pamiętajmy, że w naszym przypadku to demon ifplugd monitoruje ten interfejs. Natomiast to czy interfejs sieciowy zostanie podniesiony zależy od podłączenia przewodu do portu ethernet.

Zwrotka z mapping eth0 odnosi się do guessnet , bo wykorzystywany jest skrypt guessnet-ifupdown . W niej zaś mamy szereg parametrów map , które konfigurują zachowanie skryptu. Przede wszystkim, mamy tam map home-wire work-wire no_link no_network . Wszystkie te nazwy odnoszą się do wirtualnych interfejsów, które są określone niżej w pliku /etc/network/interfaces . Nazwy oczywiście są dowolne ale muszą pasować do nazw wirtualnych interfejsów.

W map default określamy interfejs, który ma zostać użyty w przypadku niespełnienia polityki przy wykrywaniu środowiska sieci. Innymi słowy, chodzi o to co zrobić w przypadku podłączenia się do nieznanej/niezaufanej nam sieci. Powyższa konfiguracja wypisze jedynie komunikat o braku zaufanych sieci i interfejs eth0 nie zostanie skonfigurowany. Oczywiście można dowolnie sobie zaprogramować tę akcję i ogranicza nas chyba tylko nasza wyobraźnia.

Dalej mamy map timeout , który przyjmuje wartość liczbową wyrażoną w sekundach. Jest to czas, przez który skrypt guessnet-ifupdown będzie próbował ustalić czy sieć, do której się podłączyliśmy, jest nam znana. W przypadku przekroczenia tego czasu, zostanie wykonana akcja domyślna określona w map default .

Z kolei zaś map verbose oraz map debug są w stanie wypisać obszerny log w przypadku, gdy coś nie działa nam jak trzeba. Zwykle nie będziemy musieli używać tych opcji.

Dalej w pliku mamy szereg zwrotek iface , które konfigurują poszczególne interfejsy wirtualne. Może być ich dowolna ilość, z tym, że guessnet operować będzie jedynie na tych, które zostały określone w parametrze map .

Interfejsy wirtualne możemy konfigurować tak jak zwykłe interfejsy sieciowe. Interfejs home-wire i work-wire odnoszą się do dwóch znanych nam sieci, w domu i w firmie. W obu tych przypadkach konfiguracja ma być uzyskiwana za pośrednictwem protokołu DHCP. Niemniej jednak, zanim ta konfiguracja zostanie pobrana, połączenie jest testowane na obecność określonego hosta w sieci. Sprawdzany jest jego adres IP oraz MAC. W przypadku dopasowania takiego hosta, interfejs zostanie skonfigurowany. W każdym innym przypadku nie zostaniemy podłączeni do sieci. Tutaj testujemy tylko jednego hosta. Niemniej jednak, linijek z test peer może być dowolna ilość. W takiej sytuacji, by się podłączyć do sieci, wszystkie te hosty muszą być w niej obecne.

Interfejs no_link ma za zadanie wykryć obecność przewodu w porcie ethernet. W przypadku jego braku, interfejsu eth0 nie będzie podlegał konfiguracji, co zaoszczędzi czas.

Z kolei zaś interfejs no_network jest domyślnym i jego zadaniem jest niedopuszczenie do konfiguracji sieci w przypadku środowiska niezaufanego, tj. innego niż dom czy firma.

Profilowanie interfejsu bezprzewodowego w laptopie

Nasz system powinien już być w stanie dobrać profil sieciowy ale tylko w przypadku interfejsu przewodowego. Jeśli chodzi o laptopy, to raczej rzadko będziemy wykorzystywać ten interfejs. Musimy zatem jeszcze skonfigurować interfejs WiFi, tak by i on podlegał profilowaniu. Edytujemy jeszcze raz plik /etc/network/interfaces i dodajemy do niego poniższe zwrotki:

auto wlan0
iface wlan0 inet manual
    wpa-driver nl80211
    wpa-debug-level -1
    wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
    wpa-roam-default-iface default
    pre-up sh -c "sleep 1"

iface home-wifi inet dhcp
iface work-wifi inet dhcp

iface default inet dhcp

Tryb auto w przypadku tego interfejsu musimy ustawić, by wyeliminować problem z brakiem połączenia po starcie systemu w przypadku, gdy przewód ethernet nie jest podłączony do karty sieciowej laptopa. Opcję wpa-driver dostosowujemy sobie w zależności od posiadanej karty WiFi. Spora część nowszych kart korzysta z nl80211 . W przypadku starszych kart trzeba ustawić wext . Parametr wpa-roam określa plik konfiguracyjny z parametrami sieci bezprzewodowych dla narzędzia wpa_supplicant . Ostatnia rzecz to linijka z pre-up . Ma ona za zadanie poprawić problem z niemożliwością uzyskania adresacji podczas fazy boot systemu.

Przechodzimy teraz do konfiguracji roamingu WiFi. Jak widzimy wyżej, mamy skonfigurowane trzy wirtualne interfejsy: home-wifi , work-wifi oraz default . Ten ostatni został określony jako domyślny w wpa-roam-default-iface . Mamy także osobny wirtualny interfejs dla sieci domowej i firmowej.

W tym przypadku nie korzystamy z guessnet , bo nie ma to większego sensu. Parametry sieci WiFi jednoznacznie identyfikują daną sieć i w oparciu o ESSID, BSSID oraz hasło możemy bez problemu stwierdzić czy zostaliśmy podłączeni do tej sieci, do której powinniśmy. Niemniej jednak, jeśli ktoś jest ciekaw rozwiązania roamingowego opartego o guessnet, to może je znaleźć tutaj.

Edytujemy teraz plik /etc/wpa_supplicant/wpa_supplicant.conf . Tutaj z kolei możemy nadać priorytet sieciom lub też włączyć lub wyłączyć łączenie się do określonych sieci bezprzewodowych. By powiązać interfejsy wirtualne z pliku /etc/network/interfaces z konkretnymi sieciami WiFi, musimy posłużyć się parametrem id_str , poniżej przykład:

ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
eapol_version=2
ap_scan=1
fast_reauth=1
country=PL

network={
    id_str="home-wifi"
    priority=20
    ssid="Home"
    bssid=ec:08:6b:8d:36:f2
    psk=12345678
    disabled=0
}

network={
    id_str="work-wifi"
    priority=89
    ssid="Work"
    bssid=e8:94:f6:c4:00:2b
    psk="87654321"
    disabled=0
}

Zakładając, że siedzibę firmy mamy gdzieś w pobliżu naszego domu, to powyższa konfiguracja będzie preferować firmową sieć bezprzewodową. Oba bloki są włączone i nasz laptop przy próbie podłączenia będzie szukał obu tych sieci. Hasło i nazwa sieci identyfikują konkretne sieci WiFi, a przy określeniu bssid możemy także precyzować z jakim AP mamy zamiar się połączyć. Kluczowa sprawa to poprawne ustawienie id_str .

Konfiguracja akcji po podłączeniu do profilowanej sieci

Mając tak wyprofilowane interfejsy sieciowe w laptopie, możemy teraz w pliku /etc/network/interfaces w zwrotkach iface dodać sobie specyficzne akcje w zależności od sieci, do której laptop zostanie podłączony. Robimy to przez określenie opcji pre-up , pre-down , post-up oraz post-down . Poniżej przykład dla interfejsu przewodowego:

iface home-wire inet dhcp
    test peer address 192.168.1.1 mac C4:6E:1F:95:EF:FE
    post-up /bin/systemctl stop firewall.service

iface work-wire inet dhcp
    test peer address 192.168.0.1 mac E8:94:F6:C4:00:2C
    post-up /bin/systemctl start firewall.service

Jak widać, nie jest to nic zaawansowanego. Tutaj firewall jest aktywowany po podłączeniu do sieci firmowej i dezaktywowany w warunkach domowych. W przypadku sieci WiFi postępujemy podobnie, tylko nie musimy określać już linijek z test peer .

Test profilowanego połączenia sieciowego

Wypadałoby także na sam koniec przetestować jak działa taki automat profilująco-przełączający interfejsy sieciowe. Wystarczy wpiąć się do sieci i zobaczyć co zostanie nam zwrócone w logu systemowym. W moim przypadku, po podłączeniu do jednej sieci z wykorzystaniem przewodu mam poniższy log:

kernel: r8169 0000:02:00.0 eth0: link up
ifplugd(eth0)[1730]: Link beat detected.
ifplugd(eth0)[1730]: Executing '/etc/ifplugd/ifplugd.action eth0 up'.
...
kernel: wlan1: deauthenticating from ec:08:6b:84:15:d5 by local choice (Reason: 3=DEAUTH_LEAVING)
ifplugd(eth0)[1730]: client: OK
wpa_action[28380]: WPA_IFACE=wlan1 WPA_ACTION=DISCONNECTED
wpa_action[28383]: WPA_ID=0 WPA_ID_STR=home-wifi WPA_CTRL_DIR=/run/wpa_supplicant
wpa_action[28386]: ifdown wlan1
...
ifplugd(eth0)[1730]: client: guessnet: Will test for link beat.  If absent, will return no_link
...
ifplugd(eth0)[1730]: client: guessnet: Got ARP reply from 192.168.1.1 ec:08:6b:84:15:d5
ifplugd(eth0)[1730]: client: guessnet: ARP reply from 192.168.1.1 ec:08:6b:84:15:d5 matches
...
ifplugd(eth0)[1730]: client: guessnet: Keeping candidate home-wire
...
ifplugd(eth0)[1730]: client: bound to 192.168.1.150 -- renewal in 32872 seconds.
systemd[1]: Stopping firewall...
systemd[1]: Stopped firewall.

Log nieco skrócony dla czytelności. W każdym razie widzimy, że przewód został podłączony do portu ethernet. Po chwili interfejs wlan0 został położony i guessnet wysłał zapytanie ARP, na które otrzymał odpowiedź. Pasuje ona do jednego ze zdefiniowanych hostów w pliku /etc/network/interfaces . System rozpoznał, że jest to sieć domowa i skonfigurował połączenie z wykorzystaniem protokołu DHCP. Po otrzymaniu adresacji zostały także dostosowane reguły firewall'a.

No to odłączmy teraz przewód od portu ethernet i zobaczmy co nam system w logu wypisze:

kernel: r8169 0000:02:00.0 eth0: link down
ifplugd(eth0)[1730]: Link beat lost.
ifplugd(eth0)[1730]: Executing '/etc/ifplugd/ifplugd.action eth0 down'.
...
kernel: wlan1: authenticated
kernel: wlan1: associated
...
wpa_action[32385]: ifup wlan1=work-wifi
...
dhclient[32404]: bound to 192.168.2.146 -- renewal in 37710 seconds.
...
systemd[1]: Starting firewall...
systemd[1]: Started firewall.
..
wpa_action[32489]: bssid=ec:08:6b:84:15:d5
wpa_action[32489]: freq=2462
wpa_action[32489]: ssid=Ever_Vigilant
wpa_action[32489]: id=0
wpa_action[32489]: id_str=work-wifi
wpa_action[32489]: mode=station
wpa_action[32489]: pairwise_cipher=CCMP
wpa_action[32489]: group_cipher=CCMP
wpa_action[32489]: key_mgmt=WPA2-PSK
wpa_action[32489]: wpa_state=COMPLETED
wpa_action[32489]: ip_address=192.168.2.146
wpa_action[32489]: p2p_device_address=e8:94:f6:1e:15:e9
wpa_action[32489]: address=e8:94:f6:1e:15:e9
wpa_action[32489]: uuid=91269bbc-a5ed-4106-8f3d-a2489399b950

Widzimy, że system wykrył odłączenie przewodu i położył interfejs eth0 . Następnie wpa_supplicant przeskanował eter w poszukiwaniu zdefiniowanych w pliku /etc/wpa_supplicant/wpa_supplicant.conf sieci WiFi. Nastąpiło uwierzytelnienie i powiązanie do jednej z sieci. Widzimy, że sieć, do której zostaliśmy podłączeni korzysta z wirtualnego interfejsu wlan1=work-wifi , zatem zostaliśmy podłączeni do sieci firmowej. Po chwili została pobrana adresacja i założony firewall. Ostatnie komunikaty dotyczą konfiguracji sieci, do której zostaliśmy podłączeni.

Ten sam adres MAC

Adresy MAC interfejsu przewodowego i bezprzewodowego różnią się. W efekcie przy podłączaniu do sieci będziemy otrzymywać dwa różne adresy IP. Próbowałem jakoś ogarnąć tę kwestię ale wygląda na to, że przy roamingu nie można zmieniać adresu MAC na interfejsie sieciowym. Nie wiem dlaczego próba ustawiania MAC zapętla demona roamingowego, który po podłączeniu się do sieci za chwilę się rozłącza i tak w nieskończoność.

W warunkach domowych, gdzie zwykle mamy dostęp do konfiguracji głównego routera, możemy powiązać ten sam adres IP z kilkoma adresami MAC, co wyeliminuje problem z różnymi adresami IP. W warunkach firmowych trzeba będzie raczej korzystać z różnych adresów, chyba, że jakoś uda mi się rozwiązać problem z zapętlaniem demona roamingowego.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.