Monitorizarea și controlul de la distanță al dispozitivelor bazate pe Lunix/OpenWrt/Lede prin portul 80...

Salutare tuturor, aceasta este prima mea experiență pe Habré. Vreau să scriu despre cum să gestionezi echipamentele de rețea într-o rețea externă într-un mod nestandard. Ce înseamnă non-standard: în majoritatea cazurilor, pentru a gestiona echipamente pe o rețea externă aveți nevoie de:

  • Adresă IP publică. Ei bine, sau dacă echipamentul se află în spatele NAT-ului cuiva, atunci un IP public și un port „redirecționat”.
  • Tunel (PPTP/OpenVPN/L2TP+IPSec etc.) către nodul central prin care ar fi accesibil.

Prin urmare, veți avea nevoie de „bicicleta mea” atunci când metodele standard nu vi se potrivesc, de exemplu:

  1. Echipamentul este situat în spatele NAT și, cu excepția http obișnuit (portul 80), totul este închis. Aceasta este o situație complet normală pentru rețelele corporative federale mari. Ei pot înregistra porturi, dar nu imediat, nu rapid și nu pentru tine.
  2. Canal de comunicare instabil și/sau „îngust”. Viteză mică, pierderi constante. Durere și frustrare atunci când încercați să organizați un tunel.
  3. Un canal de comunicare costisitor, unde literalmente fiecare megaoctet contează. De exemplu, comunicațiile prin satelit. Plus întârzieri lungi și o bandă „îngustă”.
  4. O situație în care trebuie să „jonglați” cu un număr mare de routere mici, pe care, pe de o parte, este instalat OpenWrt/Lede pentru a extinde capacitățile, iar pe de altă parte, resursele (memoria) routerului nu sunt suficiente pentru tot.

Notați numărul de ori Ce vă împiedică să instalați o unitate flash în portul USB al routerului și să extindeți memoria routerului?

Cel mai adesea, cerințele sunt pentru costul soluției în ansamblu, dar uneori și factorul de formă joacă un rol cheie. De exemplu, există un TP-Link ML3020 pe site, singurul său port USB este folosit pentru un modem 2G/3G, toate acestea sunt ambalate într-un fel de carcasă mică de plastic și plasate undeva sus, sus (pe catarg), departe, departe (în câmp, la 30 km de cea mai apropiată stație de bază a operatorului de telefonie mobilă). Da, puteți conecta un hub USB și puteți extinde numărul de porturi, dar experiența arată că acest lucru este greoi și nesigur.

Așadar, am încercat să vă descriu situația mea tipică: „undeva departe, departe, există un router foarte important, singuratic și mic, care rulează Linux. Este important să știți cel puțin o dată pe zi că este „în viață” și, dacă este necesar, îi sunt trimise comenzi, de exemplu, „iubito, reporniți!”

Să trecem la implementare:

1) Pe partea routerului, prin cron, la fiecare 5/10/1440 de minute sau oricând doriți, trebuie să trimiteți o solicitare http către server folosind wget, să salvați rezultatul solicitării într-un fișier, să faceți fișierul executabil , și executați-l.

Linia mea cron arată cam așa:

Fișier /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

, unde:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai este domeniul serverului meu. Permiteți-mi să notez imediat: da, puteți specifica o anumită adresă IP a serverului, obișnuiam să facem asta până când starea noastră, într-un impuls drept de luptă, voi spune, nu știu, a blocat accesul la leul. cota din „norii” DigitalOcean și Amazon. Dacă utilizați un domeniu simbolic, dacă apare un astfel de incident, puteți crea cu ușurință un cloud de rezervă, puteți redirecționa domeniul către acesta și puteți restabili monitorizarea dispozitivului.

a.php este numele scriptului de pe server. Da, știu că este greșit să denumim variabile și nume de fișiere cu aceeași literă... Sugerez ca astfel să salvăm câțiva octeți la trimiterea unei cereri :)
u - nume de utilizator, autentificare hardware
p - parola
„-O /tmp/wa.sh” este un fișier de pe routerul de la distanță unde răspunsul serverului, de exemplu comanda de repornire, va fi salvat.

Nota numarul doi: Ahhh, de ce folosim wget și nu curl, pentru că prin curl poți trimite cereri https nu cu GET, ci cu POST? Ahhh pentru că, ca în vechea glumă „NE se urcă în borcan!” curl include biblioteci de criptare de aproximativ 2 MB și din această cauză este puțin probabil să puteți asambla o imagine pentru un mic TP-LINK ML3020, de exemplu. Și cu wget - vă rog.

2) Pe partea de server (am Ubuntu) vom folosi Zabbix. De ce: vreau să fie frumos (cu grafice) și convenabil (trimiteți comenzi prin meniul contextual). Zabbix are un lucru atât de minunat ca agentul zabbix. Prin intermediul agentului, vom apela un script PHP pe server, care va returna informații despre dacă routerul nostru s-a înregistrat în perioada de timp necesară. Pentru a stoca informații despre timpul de înregistrare, comenzi pentru dispozitive, folosesc MySQL, un tabel separat pentru utilizatori cu aproximativ următoarele câmpuri:

		CREATE TABLE `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, // IP последнего соединения 
		  `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;

Toate sursele pot fi descărcate din depozitul Git la: https://github.com/BazDen/iotnet.online.git
Acum scripturile PHP sunt plasate pe partea serverului (pentru comoditate, pot fi plasate în folderul /usr/share/zabbix/):

un fișier php:

<?php
// Получаем входные параметры: имя пользователя, пароль и сообщение от удаленного роутера
// Зачем нужен message ? Это способ ответа роутера, например если вы захотите посмотреть содержимое файла роутера
	$user=$_REQUEST['u'];
	$password=$_REQUEST['p'];
	$message=$_REQUEST['m'];
	
	// Подключаемся к нашей базе данных (MySQL)
	$conn=new mysqli("localhost","db_login","db_password","DB_name");
	if (mysqli_connect_errno()) {
		exit();
	}
	$conn->set_charset("utf8");
	// здесь ищем наш роутер в таблице базы данных
	$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();
		// здесь мы роутеру отправляем его задачи
		echo $task;
		echo "n";
		echo $reg_task;
		// вот здесь мы пишем время ответа и сам ответ роутера
		$response_history="[".date("Y-m-d H:i")."] ".$message;
		// задачу отправили, теперь надо ее удалить,а после удаления отметить в логах, что такая-то задача выполнена
		$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();
		}
		// теперь надо сохранить время регистрации пользователя, его айпи и сообщение от него. Пока только сообщение
		$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();
	}
	// если мы не нашли роутер в нашей базе данных, или его статус "неактивный", то ему ... будет отправлена команда reboot....
	// Почему так жестоко ? Потому что роутеры иногда пропадают, а это маленький способ проучить "новых владельцев". 
	else
	{
	echo "reboot";
	}
	$sql_users->close();
	?>

Fișier Agent.php (acesta este scriptul agentului zabbix numit):

<?php
	// файл агента Zabbix. Данный скрипт обращается к таблице users и получает "1" если устройство регистрировалось с момента последнего обращения
	// user и password - учетные данные оборудования
	$user = $argv[1];
	$password = $argv[2];
	
	// подключаемся к нашей базе данных
	$conn=new mysqli("localhost","db_user","db_password","db_name");
	if (mysqli_connect_errno()) {
		exit();
		}
	$conn->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();
	// обмен данными происходит через поле seq. При регистрации железка ставит данное поле в "1"
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		echo $seq;
	}
		
	// обнуляем $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();
?>		

Ei bine, etapa finală: înregistrarea unui agent și adăugarea programelor.

Dacă nu ați instalat încă agentul zabbix, atunci:

apt-get install zabbix-agent

Editați fișierul /etc/zabbix/zabbix_agentd.conf.

Adăugați linia:

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

, unde:
test este numele agentului nostru
„php /usr/share/zabbix/agent.php user password” - un script numit care indică datele de înregistrare a dispozitivului.

Adăugarea diagramelor: deschideți interfața web zabbix, selectați din meniu:
Setări -> Noduri de rețea -> Creați un nod de rețea. Aici este suficient să specificați numele gazdei rețelei, grupul său și interfața implicită a agentului:

Monitorizarea și controlul de la distanță al dispozitivelor bazate pe Lunix/OpenWrt/Lede prin portul 80...

Acum trebuie să adăugăm un element de date pentru acest nod de rețea. Atenție la două câmpuri: „cheie” - acesta este exact parametrul pe care l-am scris în fișierul /etc/zabbix/zabbix_agentd.conf (în cazul nostru este test) și „interval de actualizare” - l-am setat la 5 minute , deoarece și echipamentul este de asemenea înregistrat pe server o dată la cinci minute.

Monitorizarea și controlul de la distanță al dispozitivelor bazate pe Lunix/OpenWrt/Lede prin portul 80...

Ei bine, să adăugăm un grafic. Recomand să alegeți „Fill” ca stil de randare.

Monitorizarea și controlul de la distanță al dispozitivelor bazate pe Lunix/OpenWrt/Lede prin portul 80...

Ieșirea este ceva foarte laconic, de exemplu, ca acesta:

Monitorizarea și controlul de la distanță al dispozitivelor bazate pe Lunix/OpenWrt/Lede prin portul 80...

La întrebarea rezonabilă: „a meritat?”, voi răspunde: bine, desigur, vedeți „motivele pentru a crea o bicicletă” la începutul articolului.

Dacă prima mea experiență de grafoman trezește interesul cititorilor, atunci în articolele următoare vreau să descriu cum să trimit comenzi către echipamentele de la distanță. De asemenea, am reușit să implementăm întreaga schemă pentru dispozitivele bazate pe RouterOS (Mikrotik).

Sursa: www.habr.com

Adauga un comentariu