Lunixi/OpenWrt/Lede-põhiste seadmete kaugseire ja juhtimine pordi 80 kaudu…

Tere kõigile, see on minu esimene Habré kogemus. Tahan kirjutada sellest, kuidas välisvõrgus olevaid võrguseadmeid mittestandardsel viisil hallata. Mida tähendab mittestandardne: enamikul juhtudel on välisvõrgu seadmete haldamiseks vaja:

  • Avalik IP-aadress. Noh, või kui seadmed on kellegi NAT-i taga, siis avalik IP ja "edasi suunatud" port.
  • Tunnel (PPTP/OpenVPN/L2TP+IPSec jne) kesksõlme, mille kaudu see oleks ligipääsetav.

Seetõttu vajate "minu jalgratast", kui standardmeetodid teile ei sobi, näiteks:

  1. Seadmed asuvad NAT-i taga ja peale tavalise http (port 80) on kõik suletud. See on suurte föderaalettevõtete võrkude jaoks täiesti tavaline olukord. Nad saavad porte registreerida, kuid mitte kohe, mitte kiiresti ja mitte teie jaoks.
  2. Ebastabiilne ja/või “kitsas” sidekanal. Madal kiirus, pidevad kaod. Valu ja frustratsioon tunneli korraldamisel.
  3. Kallis sidekanal, kus sõna otseses mõttes iga megabait loeb. Näiteks satelliitside. Lisaks pikad viivitused ja “kitsas” riba.
  4. Olukord, kus peate "žongleerima" suure hulga väikeste ruuteritega, millele ühelt poolt on võimaluste laiendamiseks installitud OpenWrt/Lede ja teisest küljest ei piisa ruuteri ressurssidest (mälu) kõige jaoks.

Märkige kordade arv Mis takistab teil ruuteri USB-porti mälupulka installimast ja ruuteri mälu laiendamast?

Enamasti esitatakse nõuded lahenduse kui terviku maksumusele, kuid mõnikord mängib võtmerolli ka vormifaktor. Näiteks on kohapeal TP-Link ML3020, selle ainsat USB-porti kasutatakse 2G/3G modemi jaoks, see kõik on pakitud mingisse väikesesse plastümbrisesse ja asetatud kuhugi kõrgele, kõrgele (mastile), kaugel, kaugel (põllul, 30 km lähimast mobiilsideoperaatori tugijaamast). Jah, saate ühendada USB-jaoturi ja laiendada portide arvu, kuid kogemus näitab, et see on tülikas ja ebausaldusväärne.

Niisiis, püüdsin teile kirjeldada oma tüüpilist olukorda: "kuskil kaugel-kaugel on väga oluline, üksildane ja väike ruuter, mis töötab Linuxiga. Oluline on vähemalt kord päevas teada, et ta on "elus" ja vajadusel saadetakse talle käsklusi, näiteks "kallis, taaskäivitage!"

Liigume edasi rakendamise juurde:

1) Ruuteri poolel, croni kaudu, iga 5/10/1440 minuti järel või millal iganes soovite, peate saatma wget abil serverile http-päringu, salvestama päringu tulemuse faili, muutma faili käivitatavaks , ja täitke see.

Minu cron line näeb välja umbes selline:

Fail /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

kus:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai on minu serveri domeen. Märgin kohe: jah, saate määrata serveri konkreetse IP-aadressi, me tegime seda seni, kuni meie riik, õiglase võitluse impulsina, ütlen, ma ei tea, blokeeris juurdepääsu lõviosa DigitalOceani ja Amazoni “pilvedest”. Kui kasutate sümboolset domeeni, saate sellise intsidendi korral hõlpsasti varupilve üles tõsta, domeeni sinna ümber suunata ja seadme jälgimise taastada.

a.php on serveripoolse skripti nimi. Jah, ma tean, et muutujaid ja failinimesid sama tähega nimetada on vale... Pakun, et nii hoiame päringu saatmisel paar baiti kokku :)
u - kasutajanimi, riistvara sisselogimine
p - parool
"-O /tmp/wa.sh" on kaugruuteri fail, kuhu salvestatakse serveri vastus, näiteks taaskäivituskäsk.

Märkus number kaks: Ahhh, miks me kasutame wget ja mitte curli, sest curli kaudu saab https päringuid saata mitte GET-iga, vaid POST-iga? Ahhh, sest nagu vanas naljas “NE ronib purki!” curl sisaldab umbes 2 MB suuruseid krüpteerimisteeke ja seetõttu on ebatõenäoline, et saate näiteks väikese TP-LINK ML3020 jaoks pilti kokku panna. Ja wgetiga - palun.

2) Serveri poolel (mul on Ubuntu) kasutame Zabbixi. Miks: ma tahan, et see oleks ilus (graafikutega) ja mugav (käskude saatmine kontekstimenüü kaudu). Zabbixil on selline imeline asi nagu zabbixi agent. Agendi kaudu kutsume serverisse PHP-skripti, mis tagastab teabe selle kohta, kas meie ruuter registreerus vajaliku aja jooksul. Registreerimisaja, seadmete käskude kohta teabe salvestamiseks kasutan MySQL-i, eraldi tabelit kasutajate kohta, millel on ligikaudu järgmised väljad:

		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;

Kõiki allikaid saab alla laadida Giti hoidlast aadressil: https://github.com/BazDen/iotnet.online.git
Nüüd serveri poolele paigutatud PHP-skriptid (mugavuse huvides saab need paigutada kausta /usr/share/zabbix/):

a.php fail:

<?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();
	?>

Agent.php fail (see on zabbixi agendi skript):

<?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();
?>		

Noh, viimane etapp: agendi registreerimine ja ajakavade lisamine.

Kui te pole veel zabbixi agenti installinud, tehke järgmist.

apt-get install zabbix-agent

Redigeerige faili /etc/zabbix/zabbix_agentd.conf.

Lisa rida:

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

kus:
test on meie agendi nimi
"php /usr/share/zabbix/agent.php kasutaja parool" - kutsutud skript, mis näitab seadme registreerimisandmeid.

Diagrammide lisamine: avage zabbixi veebiliides, valige menüüst:
Seaded -> Võrgusõlmed -> Loo võrgusõlm. Siin piisab võrguhosti nime, selle rühma ja agendi vaikeliidese määramisest:

Lunixi/OpenWrt/Lede-põhiste seadmete kaugseire ja juhtimine pordi 80 kaudu…

Nüüd peame selle võrgusõlme jaoks lisama andmeelemendi. Pöörake tähelepanu kahele väljale: "võti" - see on täpselt see parameeter, mille kirjutasime faili /etc/zabbix/zabbix_agentd.conf (meie puhul on see test) ja "värskendusintervall" - määrasin selle 5 minutiks. , sest ja seadmed registreeritakse ka serveris kord iga viie minuti tagant.

Lunixi/OpenWrt/Lede-põhiste seadmete kaugseire ja juhtimine pordi 80 kaudu…

Noh, lisame graafiku. Soovitan valida renderdusstiiliks "Täida".

Lunixi/OpenWrt/Lede-põhiste seadmete kaugseire ja juhtimine pordi 80 kaudu…

Väljund on midagi väga lakoonilist, näiteks selline:

Lunixi/OpenWrt/Lede-põhiste seadmete kaugseire ja juhtimine pordi 80 kaudu…

Mõistlikule küsimusele: "kas see oli seda väärt?", vastan: noh, muidugi, vaadake artikli algusest "jalgratta loomise põhjused".

Kui minu esimene grafomaanikogemus äratab lugejates huvi, siis järgmistes artiklites tahan kirjeldada, kuidas kaugseadmetele käske saata. Samuti õnnestus meil rakendada kogu skeem RouterOS-il (Mikrotik) põhinevate seadmete jaoks.

Allikas: www.habr.com

Lisa kommentaar