Bewaking en bediening op afstand van op Lunix/OpenWrt/Lede gebaseerde apparaten via poort 80...

Hallo allemaal, dit is mijn eerste ervaring met Habré. Ik wil schrijven over hoe je netwerkapparatuur op een extern netwerk op een niet-standaard manier kunt beheren. Wat betekent niet-standaard: voor het beheren van apparatuur op een extern netwerk heeft u in de meeste gevallen het volgende nodig:

  • Openbaar IP-adres. Nou ja, of als de apparatuur zich achter iemands NAT bevindt, dan een openbaar IP-adres en een “doorgestuurde” poort.
  • Tunnel (PPTP/OpenVPN/L2TP+IPSec, enz.) naar het centrale knooppunt waarlangs het toegankelijk zou zijn.

Daarom heb je ‘mijn fiets’ nodig als de standaardmethoden niet bij je passen, bijvoorbeeld:

  1. De apparatuur bevindt zich achter NAT en behalve de gebruikelijke http (poort 80) is alles gesloten. Dit is een volkomen normale situatie voor grote federale bedrijfsnetwerken. Ze kunnen poorten registreren, maar niet meteen, niet snel, en niet voor jou.
  2. Onstabiel en/of ‘smal’ communicatiekanaal. Lage snelheid, constante verliezen. Pijn en frustratie bij het organiseren van een tunnel.
  3. Een duur communicatiekanaal, waarbij letterlijk elke megabyte telt. Bijvoorbeeld satellietcommunicatie. Plus lange vertragingen en een “smalle” band.
  4. Een situatie waarin u een groot aantal kleine routers moet 'jongleren', waarop enerzijds OpenWrt/Lede is geïnstalleerd om de mogelijkheden uit te breiden, en aan de andere kant zijn de bronnen (geheugen) van de router niet voldoende voor alles.

Noteer het aantal keren Wat weerhoudt u ervan een flashdrive in de USB-poort van de router te installeren en het geheugen van de router uit te breiden?

Meestal betreffen de eisen de kosten van de oplossing als geheel, maar soms speelt de vormfactor ook een sleutelrol. Er staat bijvoorbeeld een TP-Link ML3020 op de locatie, de enige USB-poort wordt gebruikt voor een 2G/3G-modem, dit alles is verpakt in een soort klein plastic hoesje en ergens hoog, hoog (op de mast) geplaatst, ver, ver weg (in het veld, 30 km van het dichtstbijzijnde basisstation van de mobiele operator). Ja, je kunt een USB-hub aansluiten en het aantal poorten uitbreiden, maar de ervaring leert dat dit omslachtig en onbetrouwbaar is.

Dus probeerde ik je mijn typische situatie te beschrijven: “ergens ver, ver weg is er een heel belangrijke, eenzame en kleine router waarop Linux draait. Het is belangrijk om minstens één keer per dag te weten dat hij “leeft” en indien nodig worden er opdrachten naar hem gestuurd, bijvoorbeeld “schat, start opnieuw op!”

Laten we verder gaan met de implementatie:

1) Aan de routerkant, via cron, elke 5/10/1440 minuten, of wanneer je maar wilt, moet je een http-verzoek naar de server sturen met behulp van wget, het resultaat van het verzoek opslaan in een bestand, het bestand uitvoerbaar maken , en voer deze uit.

Mijn cron-lijn ziet er ongeveer zo uit:

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

, Waar:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai is het domein van mijn server. Laat me meteen opmerken: ja, je kunt een specifiek IP-adres van de server opgeven, we deden dit totdat onze staat, in een rechtvaardige impuls van strijd, ik zal zeggen, ik weet het niet, de toegang tot de leeuwen blokkeerde aandeel van de ‘wolken’ van DigitalOcean en Amazon. Als u een symbolisch domein gebruikt en een dergelijk incident zich voordoet, kunt u eenvoudig een back-upcloud opzetten, het domein ernaar omleiden en de apparaatbewaking herstellen.

a.php is de naam van het serverscript. Ja, ik weet dat het verkeerd is om variabelen en bestandsnamen met dezelfde letter te noemen... Ik stel voor dat we op deze manier een paar bytes besparen bij het verzenden van een verzoek :)
u - gebruikersnaam, hardware-aanmelding
p - wachtwoord
“-O /tmp/wa.sh” is een bestand op de externe router waarin het serverantwoord, bijvoorbeeld de reboot-opdracht, wordt opgeslagen.

Opmerking nummer twee: Ahhh, waarom gebruiken we wget en niet curl, omdat je via curl https-verzoeken niet met GET, maar met POST kunt verzenden? Ahhh omdat, zoals in de oude grap “NE klimt in de pot!” curl bevat encryptiebibliotheken van ongeveer 2 MB groot en daarom is het onwaarschijnlijk dat u bijvoorbeeld een afbeelding voor een kleine TP-LINK ML3020 kunt samenstellen. En met wget - alsjeblieft.

2) Aan de serverkant (ik heb Ubuntu) zullen we Zabbix gebruiken. Waarom: ik wil dat het mooi is (met grafieken) en handig (opdrachten verzenden via het contextmenu). Zabbix heeft zoiets geweldigs als de zabbix-agent. Via de agent roepen we een PHP-script op de server aan, dat informatie teruggeeft over de vraag of onze router zich gedurende de vereiste periode heeft geregistreerd. Om informatie over registratietijd en opdrachten voor apparaten op te slaan, gebruik ik MySQL, een aparte gebruikerstabel met ongeveer de volgende velden:

		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 bronnen kunnen worden gedownload van de Git-repository op: https://github.com/BazDen/iotnet.online.git
Nu worden PHP-scripts aan de serverzijde geplaatst (voor het gemak kunnen ze in de map /usr/share/zabbix/ worden geplaatst):

een.php-bestand:

<?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-bestand (dit is het script van de zabbix-agent genaamd):

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

Welnu, de laatste fase: een agent registreren en planningen toevoegen.

Als u de zabbix-agent nog niet hebt geïnstalleerd, dan:

apt-get install zabbix-agent

Bewerk het bestand /etc/zabbix/zabbix_agentd.conf.

Voeg de regel toe:

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

, Waar:
test is de naam van onze agent
“php /usr/share/zabbix/agent.php gebruikerswachtwoord” - een aangeroepen script dat de apparaatregistratiegegevens aangeeft.

Grafieken toevoegen: open de zabbix-webinterface, selecteer uit het menu:
Instellingen -> Netwerkknooppunten -> Maak een netwerkknooppunt. Hier volstaat het om de naam van de netwerkhost, zijn groep en de standaard agentinterface op te geven:

Bewaking en bediening op afstand van op Lunix/OpenWrt/Lede gebaseerde apparaten via poort 80...

Nu moeten we een data-element toevoegen voor dit netwerkknooppunt. Let op twee velden: "sleutel" - dit is precies de parameter die we in het bestand /etc/zabbix/zabbix_agentd.conf hebben geschreven (in ons geval is het test) en "update-interval" - ik heb het ingesteld op 5 minuten , want en de apparatuur wordt ook eens in de vijf minuten op de server geregistreerd.

Bewaking en bediening op afstand van op Lunix/OpenWrt/Lede gebaseerde apparaten via poort 80...

Laten we een grafiek toevoegen. Ik raad aan om “Vulling” als weergavestijl te kiezen.

Bewaking en bediening op afstand van op Lunix/OpenWrt/Lede gebaseerde apparaten via poort 80...

De uitvoer is iets heel laconieks, bijvoorbeeld als volgt:

Bewaking en bediening op afstand van op Lunix/OpenWrt/Lede gebaseerde apparaten via poort 80...

Op de redelijke vraag: "was het het waard?", Zal ik antwoorden: zie natuurlijk "redenen voor het maken van een fiets" aan het begin van het artikel.

Als mijn eerste grafomane-ervaring de interesse van lezers wekt, wil ik in de volgende artikelen beschrijven hoe je opdrachten naar externe apparatuur kunt sturen. We zijn er ook in geslaagd om het hele schema te implementeren voor apparaten op basis van RouterOS (Mikrotik).

Bron: www.habr.com

Voeg een reactie