Fjernovervågning og kontrol af Lunix/OpenWrt/Lede-baserede enheder via port 80...

Hej alle sammen, dette er min første oplevelse på Habré. Jeg vil skrive om, hvordan man administrerer netværksudstyr på et eksternt netværk på en ikke-standard måde. Hvad betyder ikke-standard: i de fleste tilfælde har du brug for: for at administrere udstyr på et eksternt netværk:

  • Offentlig IP-adresse. Nå, eller hvis udstyret er bag nogens NAT, så en offentlig IP og en "videresendt" port.
  • Tunnel (PPTP/OpenVPN/L2TP+IPSec osv.) til den centrale node, hvorigennem den ville være tilgængelig.

Derfor skal du bruge "min cykel", når standardmetoder ikke passer dig, f.eks.

  1. Udstyret er placeret bag NAT, og bortset fra den sædvanlige http (port 80) er alt lukket. Dette er en helt normal situation for store føderale virksomhedsnetværk. De kan registrere porte, men ikke med det samme, ikke hurtigt og ikke for dig.
  2. Ustabil og/eller "smal" kommunikationskanal. Lav hastighed, konstante tab. Smerte og frustration, når du prøver at organisere en tunnel.
  3. En dyr kommunikationskanal, hvor bogstaveligt talt hver megabyte tæller. For eksempel satellitkommunikation. Plus lange forsinkelser og et "smalt" bånd.
  4. En situation, hvor du skal "jonglere" et stort antal små routere, hvorpå på den ene side OpenWrt/Lede er installeret for at udvide mulighederne, og på den anden side er ressourcerne (hukommelsen) i routeren ikke nok for alt.

Bemærk antal gange Hvad forhindrer dig i at installere et flashdrev i routerens USB-port og udvide routerens hukommelse?

Oftest er kravene til prisen for løsningen som helhed, men nogle gange spiller formfaktoren også en central rolle. For eksempel er der en TP-Link ML3020 på stedet, dens eneste USB-port bruges til et 2G/3G-modem, alt dette er pakket ind i en slags lille plastiketui og placeret et sted højt, højt (på masten), langt, langt væk (i marken, 30 km fra den nærmeste mobiloperatørs basestation). Ja, du kan tilslutte en USB-hub og udvide antallet af porte, men erfaringen viser, at dette er besværligt og upålideligt.

Så jeg prøvede at beskrive min typiske situation for dig: "et sted langt, langt væk, er der en meget vigtig, ensom og lille router, der kører Linux. Det er vigtigt at vide mindst en gang om dagen, at han er "i live", og om nødvendigt sendes kommandoer til ham, for eksempel "skat, genstart!"

Lad os gå videre til implementeringen:

1) På routersiden, via cron, hvert 5/10/1440 minutter, eller når du vil, skal du sende en http-anmodning til serveren ved hjælp af wget, gemme resultatet af anmodningen i en fil, gøre filen eksekverbar , og udføre det.

Min cron linje ser sådan ud:

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 domænet for min server. Lad mig bemærke med det samme: ja, du kan angive en specifik IP-adresse på serveren, vi plejede at gøre dette, indtil vores stat, i en retfærdig impuls af kamp, ​​vil sige, jeg ved det ikke, blokerede adgangen til løvens andel af DigitalOcean og Amazons "skyer". Hvis du bruger et symbolsk domæne, hvis en sådan hændelse opstår, kan du nemt rejse en backup-sky, omdirigere domænet til det og gendanne enhedsovervågning.

a.php er navnet på server-side scriptet. Ja, jeg ved godt, at det er forkert at navngive variabler og filnavne med samme bogstav... Jeg foreslår, at vi på denne måde sparer et par bytes, når vi sender en anmodning :)
u - brugernavn, hardware login
p - adgangskode
"-O /tmp/wa.sh" er en fil på fjernrouteren, hvor serversvaret, for eksempel genstartskommandoen, vil blive gemt.

Bemærk nummer to: Ahhh, hvorfor bruger vi wget og ikke curl, for via curl kan du sende https-forespørgsler ikke med GET, men med POST? Ahhh fordi, som i den gamle joke "NE klatrer ind i krukken!" curl inkluderer krypteringsbiblioteker på omkring 2MB i størrelse, og på grund af dette er det usandsynligt, at du for eksempel vil være i stand til at samle et billede til en lille TP-LINK ML3020. Og med wget - tak.

2) På serversiden (jeg har Ubuntu) vil vi bruge Zabbix. Hvorfor: Jeg ønsker, at det skal være smukt (med grafer) og praktisk (send kommandoer via kontekstmenuen). Zabbix har sådan en vidunderlig ting som zabbix-agenten. Gennem agenten vil vi kalde et PHP-script på serveren, som vil returnere information om, hvorvidt vores router er registreret i det påkrævede tidsrum. For at gemme information om registreringstid, kommandoer til enheder, bruger jeg MySQL, en separat tabelbrugere med cirka følgende felter:

		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 downloades fra Git-lageret på: https://github.com/BazDen/iotnet.online.git
Nu placeres PHP-scripts på serversiden (for nemheds skyld kan de placeres 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 scriptet for zabbix-agenten kaldet):

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

Nå, den sidste fase: registrering af en agent og tilføjelse af tidsplaner.

Hvis du endnu ikke har installeret zabbix-agenten, så:

apt-get install zabbix-agent

Rediger filen /etc/zabbix/zabbix_agentd.conf.

Tilføj linjen:

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

, Hvor:
test er navnet på vores agent
"php /usr/share/zabbix/agent.php brugeradgangskode" - et kaldt script, der angiver enhedsregistreringsdata.

Tilføjelse af diagrammer: Åbn zabbix-webgrænsefladen, vælg fra menuen:
Indstillinger -> Netværksknudepunkter -> Opret en netværksknude. Her er det nok at angive navnet på netværksværten, dens gruppe og standardagentgrænsefladen:

Fjernovervågning og kontrol af Lunix/OpenWrt/Lede-baserede enheder via port 80...

Nu skal vi tilføje et dataelement til denne netværksknude. Vær opmærksom på to felter: "nøgle" - det er præcis den parameter, vi skrev i filen /etc/zabbix/zabbix_agentd.conf (i vores tilfælde er det test), og "opdateringsinterval" - jeg indstillede det til 5 minutter , fordi og udstyret bliver også registreret på serveren en gang hvert femte minut.

Fjernovervågning og kontrol af Lunix/OpenWrt/Lede-baserede enheder via port 80...

Nå, lad os tilføje en graf. Jeg anbefaler at vælge "Fyld" som gengivelsesstil.

Fjernovervågning og kontrol af Lunix/OpenWrt/Lede-baserede enheder via port 80...

Outputtet er noget meget lakonisk, for eksempel som dette:

Fjernovervågning og kontrol af Lunix/OpenWrt/Lede-baserede enheder via port 80...

Til det rimelige spørgsmål: "var det det værd?", vil jeg svare: ja, selvfølgelig, se "grunde til at oprette en cykel" i begyndelsen af ​​artiklen.

Hvis min første grafomiske oplevelse vækker læsernes interesse, så vil jeg i de følgende artikler beskrive, hvordan man sender kommandoer til fjernudstyr. Det lykkedes også at implementere hele ordningen for enheder baseret på RouterOS (Mikrotik).

Kilde: www.habr.com

Tilføj en kommentar