Zdalne monitorowanie i zarządzanie urządzeniami opartymi na Lunix/OpenWrt/Lede przez port 80...

Cześć wszystkim, to moje pierwsze doświadczenie na Habra. Chcę napisać o tym, jak nietypowo zarządzać urządzeniami sieciowymi w zewnętrznej sieci. Co oznacza nietypowo: w większości przypadków, do zarządzania urządzeniami w zewnętrznej sieci potrzebujesz:

  • Publicznego adresu IP. Lub jeśli urządzenie znajduje się za czyimś NAT-em, to publicznego IP i „przekierowanego” portu.
  • Tunelu (PPTP/OpenVPN/L2TP+IPSec itd.) do centralnego węzła, przez który byłaby dostępna.

Dlatego „mój rower” będzie potrzebny, gdy standardowe metody Ci nie odpowiadają, na przykład:

  1. Urządzenie znajduje się za NAT-em, a oprócz zwykłego http (port 80) – wszystko jest zamknięte. Całkiem normalna sytuacja w dużych ogólnokrajowych sieciach korporacyjnych. Mogą przepisać porty – ale nie od razu, nie szybko i nie dla Ciebie.
  2. Niestabilny i/lub „wąski” kanał komunikacyjny. Niska prędkość, ciągłe straty. Ból i rozczarowanie przy próbie zorganizowania tunelu.
  3. Drogi kanał komunikacyjny, gdzie dosłownie każdy megabajt jest na wagę złota. Na przykład komunikacja satelitarna. Dodatkowo duże opóźnienia i „wąska” przepustowość.
  4. Sytuacja, w której musisz „żonglować” dużą ilością małych routerów, na których z jednej strony zainstalowano OpenWrt/Lede w celu rozszerzenia możliwości, a z drugiej strony pamięci routera nie starcza na wszystko.

Notatka numer jeden A co przeszkadza w podłączeniu „pendrive'a” do portu USB routera i zwiększeniu pamięci routera?

Najczęściej wymagania dotyczące kosztów rozwiązania jako całości, ale czasami kluczową rolę odgrywa także forma. Na przykład w obiekcie znajduje się TP-Link ML3020, jego jedyny port USB jest używany do modemu 2G/3G, wszystko to jest owinięte w jakiś mały plastikowy korpus i umieszczone wysoko (na maszcie), daleko (na przykład w polu, 30 km od najbliższej stacji bazowej operatora komórkowego). Tak, można podłączyć hub USB i zwiększyć liczbę portów, ale doświadczenie pokazuje, że jest to nieporęczne i niewiarygodne.

Tak więc, starałem się opisać moją typową sytuację: „gdzieś daleko, stoi bardzo ważny, samotny i mały router zarządzany przez Linux. Ważne jest, aby przynajmniej raz dziennie wiedzieć, że jest „żywy” i w razie potrzeby wysłać mu polecenia, na przykład „słoneczko, zrestartuj się!”

Przejdźmy do realizacji:

1) Po stronie routera co 5/10/1440 minut, lub w dowolnym innym momencie, należy wysłać żądanie http do serwera przy użyciu wget, zapisać wynik żądania w pliku, nadać plikowi prawa do wykonania i wykonać go.

Moja linia w cron wygląda mniej więcej tak:

Plik /etc/crontabs/root:

  * /5 * * * * wget "http://xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai/a.php?u=user&p=password" -O /tmp/wa.sh && chmod 777 /tmp/wa.sh && /tmp/wa.sh

, gdzie:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai — domena mojego serwera. Od razu zaznaczam: tak, można podać również konkretny adres IP serwera, wcześniejsze tak robiliśmy, póki nasze państwo, w słusznym zapale walki z czymś, czego nie wiem — nie zablokowało dostępu do większości „chmur” DigitalOcean i Amazon. W przypadku użycia symbolicznej domeny, w przypadku zaistnienia takiego przypadku, spokojnie będzie można uruchomić zapasową chmurę, przekierować na nią domenę i przywrócić monitorowanie urządzeń.

a.php — nazwa skryptu po stronie serwera. Tak, wiem, że to błąd, nazywać zmienne i nazwy plików jedną literą… proponuję uznać, że w ten sposób oszczędzamy kilka bajtów przy wysyłaniu żądania 🙂
u — nazwa użytkownika, login urządzenia
p — hasło
„-O /tmp/wa.sh“ — plik na zdalnym routerze, gdzie będzie przechowywana odpowiedź serwera, na przykład polecenie reboot.

Uwagi numer dwa: Aaaa, dlaczego używamy wget, a nie curl, przecież przez curl można wysyłać żądania https i nie tylko GET, ale także POST? Aaaa dlatego, że jak w starym dowcipie „Nie wejdzie do wiadra!”. W skład curl wchodzą biblioteki szyfrujące o wielkości około 2 MB i z tego powodu prawdopodobnie nie uda się szybko zbudować obrazu dla małego TP-LINK ML3020, na przykład. A z wget — proszę bardzo.

2) Po stronie serwera (u mnie to Ubuntu) użyjemy Zabbixa. Dlaczego: chcę, aby to wyglądało ładnie (z wykresami) i wygodnie (wysyłać polecenia przez menu kontekstowe). Zabbix ma taką uroczą rzecz jak zabbix-agent. Poprzez agenta będziemy wywoływać skrypt php na serwerze, który będzie zwracał informacje o tym, czy nasz router zarejestrował się w wymaganym okresie czasu. Do przechowywania informacji o czasie rejestracji, poleceniach dla urządzeń, używam MySQL, oddzielnej tabeli users około takich pól:

		STWÓRZ TABELĘ `users` (
		  `id` varchar(25) NOT NULL,
		  `passwd` varchar(25) NOT NULL,
		  `description` varchar(150) NOT NULL,
		  `category` varchar(30) NOT NULL,
		  `status` varchar(10) NOT NULL,
		  `last_time` varchar(20) NOT NULL, 
		  `last_ip` varchar(20) NOT NULL, 
		  `last_port` int(11) NOT NULL, 
		  `task` text NOT NULL, 
		  `reg_task` varchar(150) NOT NULL, 
		  `last_task` text NOT NULL, 
		  `response` text NOT NULL, 
		  `seq` int(11) NOT NULL
		) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Wszystkie źródła można pobrać z repozytorium Git pod adresem: https://github.com/BazDen/iotnet.online.git
Teraz skrypty PHP umieszczane po stronie serwera (dla wygody można je umieścić w folderze /usr/share/zabbix/):

Plik a.php:

set_charset("utf8");
	// tutaj szukamy naszego routera w tabeli bazy danych
	$sql_users=$conn->prepare("SELECT task, reg_task, response, last_time FROM users WHERE id=? AND passwd=? AND status='active';");
	$sql_users->bind_param('ss', $user, $password);
	$sql_users->bind_result($task, $reg_task, $response, $last_time);
	$sql_users->execute();
	$sql_users->store_result();
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		// tutaj wysyłamy routerowi jego zadania
		echo $task;
		echo "n";
		echo $reg_task;
		// tutaj zapisujemy czas odpowiedzi i samą odpowiedź routera
		$response_history="[".date("Y-m-d H:i")."] ".$message;
		// zadanie zostało wysłane, teraz musimy je usunąć, a po usunięciu zaznaczyć w logach, że takie zadanie zostało wykonane
		$last_ip=$_SERVER["REMOTE_ADDR"];
		$last_port=$_SERVER["REMOTE_PORT"];
		$ts_last_conn_time=$last_time;
		$sql_users=$conn->prepare("UPDATE users SET task='', seq=1 WHERE (id=?);");
		$sql_users->bind_param('s', $user);
		$sql_users->execute();
		if (strlen($message)>1){
			$sql_users=$conn->prepare("UPDATE users SET response=?, seq=1 WHERE (id=?);");
			$sql_users->bind_param('ss', $response_history, $user);
			$sql_users->execute();
		}
		// teraz musimy zapisać czas rejestracji użytkownika, jego IP i wiadomość od niego. Na razie tylko wiadomość
		$ts_now=time();
		$sql_users=$conn->prepare("UPDATE users SET last_time=?, last_ip=?, last_port=? WHERE (id=?);");
		$sql_users->bind_param('ssss', $ts_now, $last_ip, $last_port, $user);
		$sql_users->execute();
	}
	// jeśli nie znaleźliśmy routera w naszej bazie danych lub jego status to "nieaktywny", to zostanie mu wysłana komenda reboot....
	// Dlaczego tak surowo? Ponieważ routery czasami znikają, a to mały sposób na ukaranie "nowych właścicieli".
	else
	{
	echo "reboot";
	}
	$sql_users->close();
	?>

Plik agent.php (to skrypt wywoływanego agenta zabbix):

set_charset("utf8");
	$sql_users=$conn->prepare("SELECT seq FROM users WHERE id=? AND passwd=? AND status='active';");
	$sql_users->bind_param('ss', $user, $password);
	$sql_users->bind_result($seq);
	$sql_users->execute();
	$sql_users->store_result();
	// Wymiana danych odbywa się przez pole seq. Podczas rejestracji urządzenie ustawia to pole na "1"
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		echo $seq;
	}
		
	// Zresetuj $seq.
	$sql_users=$conn->prepare("UPDATE users SET seq=0 WHERE id=? AND passwd=? AND status='active';");
	$sql_users->bind_param('ss', $user, $password);
	$sql_users->execute();
	$sql_users->close();
?>		

No i ostatni etap: zarejestrowanie agenta i dodanie wykresów.

Jeśli jeszcze nie masz zainstalowanego agenta zabbix, to:

apt-get install zabbix-agent

Edytujemy plik /etc/zabbix/zabbix_agentd.conf.

Dodajemy linijkę:

UserParameter=test,php /usr/share/zabbix/agent.php user password

, gdzie:
test — nazwa naszego agenta
„php /usr/share/zabbix/agent.php user password“ — wywoływany skrypt z danymi logowania urządzenia.

Dodawanie wykresów: otwieramy interfejs webowy zabbix, w menu wybieramy:
Konfiguracja -> Węzły sieci -> Utwórz węzeł sieci. Tutaj wystarczy podać nazwę węzła sieci, jego grupę, interfejs agenta domyślnie:

Zdalne monitorowanie i zarządzanie urządzeniami opartymi na Lunix/OpenWrt/Lede przez port 80...

Teraz dla tego węzła sieci musimy dodać element danych. Zwróć uwagę na dwa pola: „klucz“ — to właśnie ten parametr, który wpisaliśmy w pliku /etc/zabbix/zabbix_agentd.conf (w naszym przypadku to test), oraz „interwał aktualizacji“ — ustalam go na 5 minut, ponieważ sprzęt rejestruje się na serwerze również raz na pięć minut.

Zdalne monitorowanie i zarządzanie urządzeniami opartymi na Lunix/OpenWrt/Lede przez port 80...

A teraz dodajemy wykres. Polecam wybrać styl rysowania „Wypełnienie“.

Zdalne monitorowanie i zarządzanie urządzeniami opartymi na Lunix/OpenWrt/Lede przez port 80...

Na wyjściu otrzymujemy coś bardzo zwięzłego, na przykład tak:

Zdalne monitorowanie i zarządzanie urządzeniami opartymi na Lunix/OpenWrt/Lede przez port 80...

Na zasadne pytanie: „czy to się opłacało?“, odpowiem: oczywiście, zobacz „powody stworzenia roweru“ na początku artykułu.

Jeśli moje pierwsze grafomańskie doświadczenie wzbudzi zainteresowanie czytelników, to w kolejnych artykułach chcę opisać, jak wysyłać polecenia na zdalne urządzenia. Udało mi się zrealizować całą schemę również dla urządzeń opartych na RouterOS (Mikrotik).

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster