11 grudnia 2014

Tasker i OpenVPN czyli dbamy o bezpieczeństwo

Jako, że od zawsze staram się dbać o bezpieczeństwo swoich danych i prywatności (przynajmniej na ile to możliwe w dzisiejszych czasach) unikam łączenia telefonu z nieszyfrowanymi sieciami WiFi. Niestety zdarzają się sytuacje, w których, trzeba z takich sieci skorzystać. Nie ma wtedy pewności czy hasła i loginy nie wpadną w łapy jakiegoś domorosłego "hakiera" bawiącego się w podszywanie pod punkt dostępowy. Rozwiązaniem tego problemu jest zastosowanie wirtualnych połączeń prywatnych czyli VPN, które tworzą szyfrowany tunel do serwera VPN i dane, które urządzenie przesyła są bezpieczne. Aby zdobyć dostęp do serwera VPN można wykupić sobie taką usługę, znaleźć darmowego dostawcę lub zrobić wszystko samemu, którą to opcję polecam. Coraz więcej nowoczesnych routerów posiada możliwość uruchomienia serwera OpenVPN w oprogramowaniu firmowym. Osobiście preferuję alternatywne oprogramowania dla routerów i praktycznie każdy z dostępnych (DD-WRT/Tomato/ OpenWRT/Gargoyle) udostępnia taką funkcjonalność. O konfiguracji usługi na routerze bądź wgrywaniu alternatywnego oprogramowania nie będę się tu rozpisywał ale jakby było zapotrzebowanie to chętnie pomogę. Należy tylko pamiętać, że konfigurując serwer należy wybrać opcję przesyłania pełnego ruchu sieciowego przez serwer.

Wymagania

Zakładam więc, że masz skonfigurowany serwer OpenVPN w routerze i utworzony profil dla telefonu. Co teraz? Potrzebny Ci będzie klient usługi OpenVPN, plugin do Taskera umożliwiający sterowanie połączeniem VPN oraz mój profil, który automatycznie będzie uruchamiał szyfrowany tunel w momencie połączenia z nieszyfrowaną siecią WiFi.
Jako klienta usługi stosuję OpenVPN for Android, a OpenVPN Tasker Plugin zapewnia mi współpracę z Taskerem. Konfiguracja OpenVPN for Android polega na imporcie pliku z rozszerzeniem ovpn po naciśnięciu klawisza Wczytaj.

OpenVPN Tasker Plugin nie wymaga konfiguracji. Po uruchomieniu wtyczka wyświetla status Aplikacji OpenVPN for Android i Taskera.

Opis wykonania

Jako, że połączenie z serwerem OpenVPN ma następować w momencie połączenia z niezabezpieczoną siecią WiFi do realizacji tego zadania wykorzystam profil Tost z danymi sieci WiFi po połączeniu.
Mam więc profil aktywowany poprzez WiFi Connected. W jego tasku wejściowym wartość zmiennej %WIFII przekazywana jest do zmiennej lokalnej %wifiinfo, za pomocą akcji Variable Search Replace z warunkiem RegEx (?<=(\n)).* wpisanym w pole Search i odznaczoną opcją Replace Matches zawartość zmiennej zostaje podzielona na poszczególne linie, które zostają zachowane w zmiennej %wifiinfo tworząc macierz. Użyte wyrażenie regularne wyszukuje tekst, po którym występuje znak \n czyli znak końca linii. Po tej operacji dostęp do poszczególnych linii jest możliwy poprzez podanie w parametrze numeru elementu macierzy np. %wifiinfo(3) lub %wifiinfo3. Następnie, znów za pomocą akcji Variable Search Replace, tym razem z zaznaczoną opcję Replace Matches i pustą zawartością pola Replace With czyszczę poszczególne linie z niepotrzebnych znaków " i tekstów by za moment wyświetlić tost z danymi sieci WiFi jeśli ekran jest włączony.

W kolejnym kroku sprawdzane jest czy sieć WiFi, do której właśnie podłączyło się urządzenie jest siecią domową (lub inną, dla której nie chcesz włączać połączenia VPN). Oczywiście możesz podać nazwy kilku sieci oddzielone znakiem / oraz podać maskę co zapewni omijanie wszystkich sieci, do których masz zaufanie.
Nastepnie za pomocą komend powłoki systemu umieszczonych w akcji Run Shell kopiowany jest plik wpa_supplicant.conf do tymczasowego katalogu Taskera. W pliku tym system przechowuje dane wszystkich znanych mu sieci. Dla akcji tej konieczne jest zaznaczenie opcji Use Root, a więc właściciele urządzeń bez dostępu do root nie skorzystają z tego profilu. Po wczytaniu zawartości pliku do zmiennej %wpa_supplicant za pomocą akcji Read File plik jest kasowany z katalogu tymczasowego za pomocą akcji Delete File.
Następnym zadaniem jest wyłuskanie z pliku listy nazw zapamiętanych sieci oraz sposobu ich zabezpieczenia. Wykonywane jest to za pomocą akcji Variable Search Replace bez zaznaczonej opcji Replace Matches. W pierwszym przypadku użyto wyrażenia regularnego (?<=(ssid=").*(?=("\n)), które wyszukuje teksty znajdujące się pomiędzy ssid=", a "\n i przekazuje je w formie macierzy do zmiennej %lista_ssid. W drugim przypadku wyrażenie regularne (?<=(key_mgmt=)).*(?=(\n)) wyszukuje teksty znajdujące się pomiędzy key_mgmt=, a znakiem końca linii i przekazuje je w formie macierzy do zmiennej %typy_kluczy.
Teraz można już za pomocą akcji Variable Set ustalić jaką pozycję na liście ma sieć, do której podłączone jest urządzenie. Wykonywane to jest za pomocą zapisu %lista_ssid(#?%wifiinfo2), który zwraca z macierzy %lista_ssid numer wartości odpowiadający %wifiinfo2 czyli nazwy aktualnie podłączonej sieci. Wartość ta zapisywana jest do zmiennej %indeks.

W tym momencie dostępne są już wszystkie dane niezbędne do sprawdzenia czy obecne połączenie jest szyfrowane. Warunkiem if sprawdzane jest czy %typy_kluczy(%indeks) jest różne od WPA-PSK czyli oznaczenia szyfrowania połączenia kluczem WPA. Jeśli tak task uruchamia połączenie OpenVPN za pomocą wtyczki ze skonfigurowaną siecią (w moim przypadku nazywa się ona Dom) oraz nadaje zmiennej %OpenVPN wartość 1.
Profil wymaga jeszcze tasku wyjściowego, w którym jeśli wartość %OpenVPN jest równa 1 wtyczka rozłącza połączenie z serwerem i następnie czyszczona jest zmienna %OpenVPN.
Cały profil wygląda następująco:

Rozpisany profil

Profile: Połączone WiFi (177)
State: Wifi Connected [ SSID:* MAC:* IP:* ]
Enter: Anon (178)
A1: Variable Set [ Name:%wifiinfo To:%WIFII Do Maths:Off Append:Off ]
A2: Variable Search Replace [ Variable:%wifiinfo Search:(?<=(\n)).* Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo Replace Matches:Off Replace With: ]
A3: Variable Search Replace [ Variable:%wifiinfo2 Search:" Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo2 Replace Matches:On Replace With: ]
A4: If [ %SCREEN ~ on ]
A5: Variable Search Replace [ Variable:%wifiinfo5 Search:IP : Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo5 Replace Matches:On Replace With: ]
A6: Variable Search Replace [ Variable:%wifiinfo7 Search:Spd: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo7 Replace Matches:On Replace With: ]
A7: Flash [ Text:Połączono z siecią %wifiinfo2
Adres IP: %wifiinfo5
Prędkość: %wifiinfo7 Long:On ]
A8: End If
A9: If [ %wifiinfo2 !~ Siec_domowa ]
A10: Run Shell [ Command:mkdir -p /sdcard/Tasker/tmp
cp /data/misc/wifi/wpa_supplicant.conf /sdcard/Tasker/tmp Timeout (Seconds):0 Use Root:On Store Output In: Store Errors In: Store Result In: Continue Task After Error:On ]
A11: Read File [ File:/sdcard/Tasker/tmp/wpa_supplicant.conf To Var:%wpa_supplicant ]
A12: Delete File [ File:/sdcard/Tasker/tmp/wpa_supplicant.conf Shred Level:0 Use Root:Off ]
A13: Variable Search Replace [ Variable:%wpa_supplicant Search:(?<=(ssid=")).*(?=("\n)) Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%lista_ssid Replace Matches:Off Replace With: ]
A14: Variable Search Replace [ Variable:%wpa_supplicant Search:(?<=(key_mgmt=)).*(?=(\n)) Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%typy_kluczy Replace Matches:Off Replace With: ]
A15: Variable Set [ Name:%indeks To:%lista_ssid(#?%wifiinfo2) Do Maths:Off Append:Off ]
A16: If [ %typy_kluczy(%indeks) !~ WPA-PSK ]
A17: OpenVPN [ Configuration:Connect (Dom) Package:com.ffrog8.openVpnTaskerPlugin Name:OpenVPN Timeout (Seconds):0 ]
A18: Variable Set [ Name:%OpenVPN To:1 Do Maths:Off Append:Off ]

Exit: Anon (258)
A1: If [ %OpenVPN = 1 ]
A2: OpenVPN [ Configuration:Disconnect Package:com.ffrog8.openVpnTaskerPlugin Name:OpenVPN Timeout (Seconds):0 ]
A3: Variable Clear [ Name:%OpenVPN Pattern Matching:Off ]

Pobieranie profilu

WiFi połączone / OpenVPN [Tasker 4.6b7]

Podziękowania

Dziękuję Mariuszowi "mrtur" Turkowi za pomoc przy testowaniu wykrywania przez Taskera niezabezpieczonych sieci WiFi.