Fjernovervåking og kontroll av Lunix/OpenWrt/Lede-baserte enheter via port 80...

Hei alle sammen, dette er min første opplevelse på Habré. Jeg vil skrive om hvordan man administrerer nettverksutstyr på et eksternt nettverk på en ikke-standard måte. Hva betyr ikke-standard: i de fleste tilfeller trenger du for å administrere utstyr på et eksternt nettverk:

  • Offentlig IP-adresse. Vel, eller hvis utstyret er bak noens NAT, så en offentlig IP og en "videresendt" port.
  • Tunnel (PPTP/OpenVPN/L2TP+IPSec, etc.) til den sentrale noden som den ville være tilgjengelig gjennom.

Derfor vil du trenge "min sykkel" når standardmetoder ikke passer deg, for eksempel:

  1. Utstyret er plassert bak NAT, og bortsett fra den vanlige http (port 80) er alt stengt. Dette er en helt normal situasjon for store føderale bedriftsnettverk. De kan registrere porter, men ikke med en gang, ikke raskt, og ikke for deg.
  2. Ustabil og/eller «smal» kommunikasjonskanal. Lav hastighet, konstante tap. Smerte og frustrasjon når du prøver å organisere en tunnel.
  3. En kostbar kommunikasjonskanal, der bokstavelig talt hver megabyte teller. For eksempel satellittkommunikasjon. Pluss lange forsinkelser og et "smalt" bånd.
  4. En situasjon når du trenger å "jonglere" et stort antall små rutere, der på den ene siden OpenWrt/Lede er installert for å utvide mulighetene, og på den andre siden er ressursene (minnet) til ruteren ikke nok for alt.

Merk antall ganger Hva hindrer deg i å installere en flash-stasjon i ruterens USB-port og utvide ruterens minne?

Oftest er kravene til kostnaden for løsningen som helhet, men noen ganger spiller også formfaktoren en nøkkelrolle. For eksempel er det en TP-Link ML3020 på stedet, den eneste USB-porten brukes til et 2G/3G-modem, alt dette er pakket inn i en slags liten plastkasse og plassert et sted høyt, høyt (på masten), langt, langt unna (i felt, 30 km fra nærmeste mobiloperatørbasestasjon). Ja, du kan koble til en USB-hub og utvide antallet porter, men erfaring viser at dette er tungvint og upålitelig.

Så jeg prøvde å beskrive min typiske situasjon for deg: "et sted langt, langt unna, er det en veldig viktig, ensom og liten ruter som kjører Linux. Det er viktig å vite minst en gang om dagen at han er "i live", og om nødvendig sendes kommandoer til ham, for eksempel "kjære, start på nytt!"

La oss gå videre til implementeringen:

1) På rutersiden, via cron, hvert 5/10/1440 minutt, eller når du vil, må du sende en http-forespørsel til serveren ved å bruke wget, lagre resultatet av forespørselen til en fil, gjøre filen kjørbar , og utfør den.

Cron-linjen min ser omtrent slik ut:

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

, hvor:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai er domenet til serveren min. La meg merke med en gang: ja, du kan spesifisere en spesifikk IP-adresse til serveren, vi pleide å gjøre dette til staten vår, i en rettferdig kampimpuls, vil si, jeg vet ikke, blokkerte tilgangen til løvens andel av DigitalOcean og Amazons "skyer". Hvis du bruker et symbolsk domene, hvis en slik hendelse inntreffer, kan du enkelt heve en backup-sky, omdirigere domenet til det og gjenopprette enhetsovervåking.

a.php er navnet på skriptet på serversiden. Ja, jeg vet at det er feil å navngi variabler og filnavn med samme bokstav... Jeg foreslår at vi på denne måten sparer noen byte når vi sender en forespørsel :)
u - brukernavn, maskinvarepålogging
p - passord
"-O /tmp/wa.sh" er en fil på den eksterne ruteren der serversvaret, for eksempel reboot-kommandoen, vil bli lagret.

Merknad nummer to: Ahhh, hvorfor bruker vi wget og ikke curl, for via curl kan du sende https-forespørsler ikke med GET, men med POST? Ahhh fordi, som i den gamle vitsen "NE klatrer inn i krukken!" curl inkluderer krypteringsbiblioteker på omtrent 2MB i størrelse, og på grunn av dette er det usannsynlig at du vil være i stand til å sette sammen et bilde for en liten TP-LINK ML3020, for eksempel. Og med wget - vær så snill.

2) På serversiden (jeg har Ubuntu) vil vi bruke Zabbix. Hvorfor: Jeg vil at den skal være vakker (med grafer) og praktisk (send kommandoer via kontekstmenyen). Zabbix har en så fantastisk ting som zabbix-agenten. Gjennom agenten vil vi kalle et PHP-skript på serveren, som vil returnere informasjon om hvorvidt ruteren vår har registrert seg i løpet av den nødvendige tidsperioden. For å lagre informasjon om registreringstid, kommandoer for enheter, bruker jeg MySQL, en egen tabellbrukere med omtrent følgende felt:

		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;

Alle kilder kan lastes ned fra Git-depotet på: https://github.com/BazDen/iotnet.online.git
Nå er PHP-skript plassert på serversiden (for enkelhets skyld kan de plasseres i mappen /usr/share/zabbix/):

a.php-fil:

<?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-fil (dette er skriptet til zabbix-agenten som heter):

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

Vel, den siste fasen: registrere en agent og legge til tidsplaner.

Hvis du ennå ikke har installert zabbix-agenten, så:

apt-get install zabbix-agent

Rediger filen /etc/zabbix/zabbix_agentd.conf.

Legg til linjen:

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

, hvor:
test er navnet på agenten vår
"php /usr/share/zabbix/agent.php brukerpassord" - et kalt skript som indikerer enhetsregistreringsdata.

Legge til diagrammer: åpne zabbix nettgrensesnitt, velg fra menyen:
Innstillinger -> Nettverksnoder -> Opprett en nettverksnode. Her er det nok å spesifisere navnet på nettverksverten, dens gruppe og standard agentgrensesnitt:

Fjernovervåking og kontroll av Lunix/OpenWrt/Lede-baserte enheter via port 80...

Nå må vi legge til et dataelement for denne nettverksnoden. Vær oppmerksom på to felt: "nøkkel" - dette er akkurat parameteren vi skrev i filen /etc/zabbix/zabbix_agentd.conf (i vårt tilfelle er det test), og "oppdateringsintervall" - jeg satte den til 5 minutter , fordi og utstyret registreres også på serveren en gang hvert femte minutt.

Fjernovervåking og kontroll av Lunix/OpenWrt/Lede-baserte enheter via port 80...

Vel, la oss legge til en graf. Jeg anbefaler å velge "Fyll" som gjengivelsesstil.

Fjernovervåking og kontroll av Lunix/OpenWrt/Lede-baserte enheter via port 80...

Utgangen er noe veldig lakonisk, for eksempel slik:

Fjernovervåking og kontroll av Lunix/OpenWrt/Lede-baserte enheter via port 80...

På det rimelige spørsmålet: "var det verdt det?", vil jeg svare: vel, selvfølgelig, se "grunner til å lage en sykkel" i begynnelsen av artikkelen.

Hvis min første grafomaniac-opplevelse vekker lesernes interesse, vil jeg i de følgende artiklene beskrive hvordan man sender kommandoer til eksternt utstyr. Vi klarte også å implementere hele ordningen for enheter basert på RouterOS (Mikrotik).

Kilde: www.habr.com

Legg til en kommentar