O ile "internet" nie jest pierwszym o czym myślimy słysząc o embedded, to dziś, w czasach Internet of Things, takie skojarzenie jest jak najbardziej na miejscu. Co raz więcej urządzeń łączy się obecnie z siecią, przesyłając dane na serwery i wymieniając je z innymi urządzeniami. Z tego względu wiedza na temat działania sieci komputerowych jest jest w tej branży bardzo przydatna.
Praca z urządzeniami łączącymi się z siecią, często bezprzewodowo poprzez GSM, wiąże się z dodatkowymi utrudnieniami w testowaniu takich urządzeń. W tym artykule skupimy się na konkretnym problemie, który możemy napotkać przy pracy z takimi urządzeniami.
Problem
Załóżmy że pracujemy nad oprogramowaniem urządzenia X. W trakcie pracy nasze urządzenie łączy się z urządzeniem Y po TCP/IP np. aby przesyłać dane pomiarowe, albo odbierać zdalne komendy.
Sytuację przedstawia poniższy rysunek:
Server Y dostępny jest publicznie pod adresem a.b.c.d:e, jednakże my chcielibyśmy mieć możliwość przetestowania komunikacji na naszym komputerze. W takich warunkach jesteśmy w stanie łatwo podejrzeć przebieg komunikacji i naprawić ewentualne błędy. Jeśli mamy dostęp do oprogramowania serwera Y moglibyśmy wystartować go lokalnie na naszym komputerze, jeśli nie - napisać uproszczoną wersję serwera Y, która pozwoli przetestować konkretne scenariusze komunikacji. W obydwu przypadkach pojawia się ten sam problem - jak połączyć nasze urządzenie X z naszym komputerem?
Proxy
Nasze urządzenie X potrafi połączyć się jedynie z adresami IP dostępnymi publicznie. Nasz komputer jednak (zazwyczaj) takiego nie posiada - najprawdopodobniej znajduje się za jednym (lub więcej) routerem który podmienia adresy pakietów (NAT - Network Address Translation). W takiej sytuacji aby móc połączyć urządzenie X z naszym komputerem musimy posłużyć się jakimś serwerem posiadającym publiczny adres IP. Być może posiadamy takowy (my lub nasz pracodawca), jeśli nie to możemy np. względnie tanio wykupić tzw. wirtualny serwer prywatny (VPS - Virtual Private Server).
W dalszej części artykułu zakładamy że, posiadamy dostęp SSH do takiego serwera z systemem Linux.
Zarys rozwiązania
Terminologia:
- DEVICE - nasze urządzenie które chce się połączyć do aplikacji serwera, my nie możemy się połączyć do niego (nie znamy adresu IP);
- PC - nasz komputer, nie znamy jego adresu IP, lecz chcemy aby DEVICE się do niego połączyło;
- PROXY - serwer z publicznym IP do którego mamy dostęp;
Aby umożliwić połączenie musimy wykorzystać PROXY jako pośrednika pomiędzy DEVICE a PC, co ilustruje poniższy rysunek:
Na urządzeniu PROXY będziemy nasłuchiwać na połączenia ze strony DEVICE. Gdy DEVICE się połączy, całość komunikacji przekierujemy na nasz komputer PC. Aby umożliwić takie przekierowanie będziemy musieli przygotować tzw. "reverse proxy" z naszego PC. Całość możemy wykonać przy pomocy kilku standardowych programów dostępnych w systemie Linux.
Zanim przejdziemy do ostatecznego rozwiązania musimy przedstawić dostępne narzędzia i zarysować kilka problemów.
Netcat
Żeby zobaczyć jak można wykorzystać to narzędzie możemy wykonać następujące czynności:
Zakładając że plik README.md
istnieje w obecnym katalogu terminala 2, zostanie on przesłany do serwera i wyświetlony w Terminalu 1.
Reverse proxy
Wracając do naszego oryginalnego problemu, brakuje nam wciąż sposobu na połączenie z PROXY do naszego PC - możemy jedynie nawiązywać połączenia z PC do PROXY (ponieważ tylko PROXY ma publicznie widoczny adres IP). Aby umożliwić połączenia z PROXY do PC musimy utworzyć tzw. "reverse proxy". Polega to na połączeniu się z PC do PROXY (to umiemy), po czym przekierowywanie połączeń z PROXY do PC "wewnątrz" wcześniej utworzonego połączenia (tzw. tunelowanie).
Przykład wywołania:
Składnia na początku może być trudna do rozczytania, więc przeanalizujmy po kolei argumenty wywołania:
Sytuację tą ilustruje poniższy rysunek:
W naszym przypadku, gdy nasz lokalny serwer startowany jest na naszym PC, tunelowanie możemy wykonywać do localhosta (127.0.0.1), czyli np. gdy lokalny serwer startujemy na porcie 8300:
Przekierowanie lokalne na PROXY
Zakładając że nasze reverse proxy nasłuchuje na PROXY lokalnych połączeń na porcie 8200, możemy utworzyć lokalne przekierowanie (już na urządzeniu PROXY) z portu 8100 na port 8200, przy czym na porcie 8100 będziemy nasłuchiwać również połączeń zdalnych (spoza urządzenia PROXY). Aby to zrobić możemy skorzystać z Netcata w następujący sposób:
Gdzie:
Socat
Firewal
Zanim przedstawimy ostateczne rozwiązanie, warto wspomnieć o ustawieniach naszego PROXY. Możliwe że domyślnie nasz serwer posiada skonfigurowaną "zaporę ogniową" uniemożliwiającą połączenia na większości portów. Jeśli tak jest musimy dodać odpowiednie wyjątki do konfiguracji zapory.
Konfiguracja firewall może być różna zależnie od konfiguracji naszego serwera PROXY i ciężko jest tu przedstawić konkretne rozwiązanie.
Ostateczna komenda
Posiadamy już wszystkie potrzebne elementy układanki:
Teraz każdorazowo gdy DEVICE połączy się z PROXY na porcie 8100, połączenie zostanie przekierowane do naszego lokalnego serwera testowego na PC na porcie 8300, a my możemy testować komunikację. Poniższy rysunek ilustruje ostateczną konfigurację:
Wszystko to możemy zawrzeć w jednej komendzie, aby łatwiej startować nasze przekierowanie DEVICE->PROXY->PC:
Gdzie:
Tak ustanowione przekierowanie możemy przetestować na PC, bez udziału DEVICE i bez startowania naszego lokalnego serwera testowego, za pomocą Netcata:
Tak wysłane dane z pliku README.md
przejdą całą drogę z Netcata na PC do PROXY:8100, poprzez lokalne przekierowanie na PROXY:8200, i poprzez SSH reverse proxy na PC:8300 do nasłuchującego tam Netcata z hexdumpem.
Referencje: