Fjärrövervakning och kontroll av Lunix/OpenWrt/Lede-baserade enheter via port 80...

Hej alla, detta är min första upplevelse på Habré. Jag vill skriva om hur man hanterar nätverksutrustning på ett externt nätverk på ett icke-standardiserat sätt. Vad betyder icke-standard: i de flesta fall behöver du för att hantera utrustning på ett externt nätverk:

  • Offentlig IP-adress. Tja, eller om utrustningen ligger bakom någons NAT, då en offentlig IP och en "vidarebefordrad" port.
  • Tunnel (PPTP/OpenVPN/L2TP+IPSec, etc.) till den centrala noden genom vilken den skulle vara tillgänglig.

Därför behöver du "min cykel" när standardmetoder inte passar dig, till exempel:

  1. Utrustningen är placerad bakom NAT och, förutom den vanliga http (port 80), är allt stängt. Detta är en helt normal situation för stora federala företagsnätverk. De kan registrera portar, men inte direkt, inte snabbt och inte för dig.
  2. Instabil och/eller "smal" kommunikationskanal. Låg hastighet, konstanta förluster. Smärta och frustration när man försöker organisera en tunnel.
  3. En dyr kommunikationskanal, där bokstavligen varje megabyte räknas. Till exempel satellitkommunikation. Plus långa förseningar och ett "smalt" band.
  4. En situation när du behöver "jonglera" ett stort antal små routrar, på vilka å ena sidan OpenWrt/Lede är installerad för att utöka kapaciteten, och å andra sidan räcker inte routerns resurser (minne) till för allt.

Notera antal gånger Vad hindrar dig från att installera en flash-enhet i routerns USB-port och utöka routerns minne?

Oftast ställs kraven på kostnaden för lösningen som helhet, men ibland spelar även formfaktorn en nyckelroll. Till exempel finns det en TP-Link ML3020 på platsen, dess enda USB-port används för ett 2G/3G-modem, allt detta är insvept i något slags litet plastfodral och placerat någonstans högt, högt (på masten), långt, långt borta (på fältet, 30 km från närmaste mobiloperatörs basstation). Ja, du kan koppla in en USB-hubb och utöka antalet portar, men erfarenheten visar att detta är krångligt och opålitligt.

Så jag försökte beskriva min typiska situation för dig: "någonstans långt, långt borta finns det en mycket viktig, ensam och liten router som kör Linux. Det är viktigt att veta minst en gång om dagen att han "lever" och vid behov skickas kommandon till honom, till exempel "älskling, starta om!"

Låt oss gå vidare till implementeringen:

1) På routersidan, via cron, var 5/10/1440 minuter, eller när du vill, måste du skicka en http-förfrågan till servern med hjälp av wget, spara resultatet av begäran i en fil, göra filen körbar , och kör det.

Min cron-linje ser ut ungefär så här:

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

, Var:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai är domänen för min server. Låt mig notera direkt: ja, du kan ange en specifik IP-adress för servern, vi brukade göra detta tills vårt tillstånd, i en rättfärdig kampimpuls, jag kommer att säga, jag vet inte, blockerade åtkomsten till lejonets andel av DigitalOcean och Amazons "moln". Om du använder en symbolisk domän, om en sådan incident inträffar, kan du enkelt skapa ett backupmoln, omdirigera domänen till den och återställa enhetsövervakning.

a.php är namnet på skriptet på serversidan. Ja, jag vet att det är fel att namnge variabler och filnamn med samma bokstav... Jag föreslår att vi på så sätt sparar några byte när vi skickar en förfrågan :)
u - användarnamn, hårdvaruinloggning
p - lösenord
"-O /tmp/wa.sh" är en fil på fjärrroutern där serversvaret, till exempel reboot-kommandot, kommer att sparas.

Notera nummer två: Ahhh, varför använder vi wget och inte curl, för via curl kan du skicka https-förfrågningar inte med GET, utan med POST? Ahhh för, som i det gamla skämtet "NE klättrar in i burken!" curl innehåller krypteringsbibliotek på cirka 2MB i storlek och på grund av detta är det osannolikt att du kommer att kunna sätta ihop en bild för till exempel en liten TP-LINK ML3020. Och med wget - snälla.

2) På serversidan (jag har Ubuntu) kommer vi att använda Zabbix. Varför: Jag vill att det ska vara vackert (med grafer) och bekvämt (skicka kommandon via snabbmenyn). Zabbix har en så underbar sak som zabbix-agenten. Genom agenten kommer vi att anropa ett PHP-skript på servern, som kommer att returnera information om huruvida vår router har registrerats under den tidsperiod som krävs. För att lagra information om registreringstid, kommandon för enheter använder jag MySQL, en separat tabellanvändare med ungefär följande fält:

		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;

Alla källor kan laddas ner från Git-förvaret på: https://github.com/BazDen/iotnet.online.git
Nu placeras PHP-skript på serversidan (för enkelhetens skull kan de placeras 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 (detta är skriptet för 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();
?>		

Tja, det sista steget: registrera en agent och lägga till scheman.

Om du ännu inte har installerat zabbix-agenten:

apt-get install zabbix-agent

Redigera filen /etc/zabbix/zabbix_agentd.conf.

Lägg till raden:

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

, Var:
test är namnet på vår agent
"php /usr/share/zabbix/agent.php användarlösenord" - ett anropat skript som indikerar enhetsregistreringsdata.

Lägga till diagram: öppna zabbix webbgränssnitt, välj från menyn:
Inställningar -> Nätverksnoder -> Skapa en nätverksnod. Här räcker det med att ange namnet på nätverksvärden, dess grupp och standardagentgränssnittet:

Fjärrövervakning och kontroll av Lunix/OpenWrt/Lede-baserade enheter via port 80...

Nu måste vi lägga till ett dataelement för denna nätverksnod. Var uppmärksam på två fält: "nyckel" - det här är exakt den parameter som vi skrev i filen /etc/zabbix/zabbix_agentd.conf (i vårt fall är det test), och "uppdateringsintervall" - jag satte den till 5 minuter , eftersom och utrustningen registreras också på servern en gång var femte minut.

Fjärrövervakning och kontroll av Lunix/OpenWrt/Lede-baserade enheter via port 80...

Nåväl, låt oss lägga till en graf. Jag rekommenderar att du väljer "Fyll" som renderingsstil.

Fjärrövervakning och kontroll av Lunix/OpenWrt/Lede-baserade enheter via port 80...

Utgången är något väldigt lakonisk, till exempel så här:

Fjärrövervakning och kontroll av Lunix/OpenWrt/Lede-baserade enheter via port 80...

På den rimliga frågan: "var det värt det?", kommer jag att svara: ja, naturligtvis, se "skäl till att skapa en cykel" i början av artikeln.

Om min första grafomaniac upplevelse väcker läsarnas intresse, så vill jag i följande artiklar beskriva hur man skickar kommandon till fjärrutrustning. Vi lyckades också implementera hela schemat för enheter baserade på RouterOS (Mikrotik).

Källa: will.com

Lägg en kommentar