Ogólne

Radio-rebooter do SR6NWR

Zacznijmy od początku, czyli od parsowania ramki APRS. A właściwie to od tego, jak wykonałem kawał dobrej, nikomu niepotrzebnej roboty.

VPN do digipeatera SR6NWR coś nie chce pracować stabilnie. Jeszcze nie wiem, co jest przyczyną, ale podejrzewam, że pada w momencie zmiany IP po stronie klienta. Pomaga restart. Wpadłem na pomysł, żeby radiowo dało się wykonać polecenie systemowe, np reboot. Direwolf, który obsługuje cały proces digipeatingu wystawia interfejs KISS, do którego można się podłączyć klientem KISS. Postanowiłem, że znajdę bibliotekę Pythona i szybko będę w stanie to obsłużyć. Bibliotekę znalazłem, ale się (początkowo) okazało, że nie działa tak jak się spodziewałem.

Surowa ramka APRS przez KISS wygląda na pierwszy rzut oka dziwnie. Dekodując ją jako string widzi się tylko czytelny payload, a część nagłówkowa, która zawiera adres (znak) nadawcy, adres przeznaczenia oraz ścieżkę jest na pierwszy rzut oka nieczytelna. Parser z biblioteki KISS / APRS wydaje się sobie nie radzić. Byłem zaskoczony, ponieważ łącząc się telnetem do serwerów aprs dostawałem czytelny ciąg znaków całej ramki. Podejrzewałem nawet Direwolfa o błąd. Dziwiło mnie jednak, że APRSIS32 podłączony do tego samego Direwolfa przez KISS nie ma żadnego problemu z odczytem. Wyeliminowałem tym hipotetyczny błąd Direwolfa.

Zacząłem dociekać w jaki sposób część nagłówka jest kodowana. Próbowałem odwracać połówki bajtów, czytać to od tyłu, przesuwać o pół bajta – bezskutecznie. Wpadłem na pomysł prześledzenia kodu samego Direwolfa, aby zobaczyć w jaki sposób jest to kodowane. To, wraz z przejrzeniem jakiejś dokumentacji i przejrzenia jeszcze innej biblioteki w innym języku nasunęło mi, że przesunięcie tam jest, ale o 1 bit w prawo. Na piechotę zacząłem konwertować bajty w hex do bin za pomocą kalkulatora. Zapisywałem to w notatniku, przesuwałem i konwertowałem z powrotem do hex. Wtedy ujrzałem już pojedyncze znaki ASCII, które odpowiadały wartościom bajtów. Byłem prawie w domu. Później jeszcze sposób kodowania SSID oraz H-bit opisany w tej dokumentacji.

To wszystko doprowadziło mnie do odkrycia metody kodowania nagłówka ramki APRS, a właściwie ramki AX.25, bo z takiego protokołu korzysta APRS. Ów dokumentacja nie do końca odzwierciedlała stan faktyczny jaki odbierałem z ciągu bajtów z biblioteki KISS, wiec uzupełniłem to o metodę wstecznej inżynierii. Udało się. Zrobiłem parser ramki APRS z protokołu KISS / AX.25.

Teraz tylko zintegrować go z biblioteką KISS / APRS i zrobić pull requesta do oficjalnego repozytorium. Ale chwila… Plik, który chciałem zmodyfikować kompletnie różnił się od tego w repozytorium. Zacząłem się bliżej przyglądać i jest. Mój IDE pobrał sobie bibliotekę KISS oraz APRS w wersji 6.5.0, natomiast najnowsza w tej chwili to 7.0.0. Zacząłem analizować kod najnowszej wersji no i jest: Pełna obsługa parsowania ramki APRS przez KISS. Można było się poddenerwować ile to zmarnowanych godzin i nerwów straciłem, ale przynajmniej dowiedziałem się coś więcej o historycznym protokole, którego już chyba nikt poza krótkofalowcami nie używa.

No to skoro mamy już możliwość odczytywania ramek, które są odbierane przez digi, przyszła pora na znalezienie sposobu jak zabezpieczyć to, żeby nie każdy mógł wykonać reboot. Pomyślałem, że mechanizm OTP (One Time Password), do którego obsługi jest prosta biblioteka w Pythonie nada się idealnie. Każda ramka z poleceniem systemowym będzie zawierać kod OTP generowany na podstawie tajnego klucza i bieżącego znacznika czasu. Metoda znana i popularna. Wykorzystywana jako drugi składnik uwierzytelnienia w Internecie. Przechwycony kod będzie działał jeszcze przez jakiś czas, ale jeśli ma to być używane do reboota, to zanim ten się wykona, to kod straci ważność. Zabezpieczenie nie jest idealne, ale wystarczające.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *