Далечинско следење и контрола на уреди базирани на Lunix/OpenWrt/Lede преку портата 80…

Здраво на сите, ова е моето прво искуство на Хабре. Сакам да пишувам за тоа како да управувам со мрежната опрема на надворешна мрежа на нестандарден начин. Што значи нестандардно: во повеќето случаи, за управување со опрема на надворешна мрежа ви треба:

  • Јавна IP адреса. Па, или ако опремата е зад нечиј NAT, тогаш јавна IP и „препратена“ порта.
  • Тунел (PPTP/OpenVPN/L2TP+IPSec, итн.) до централниот јазол преку кој би бил достапен.

Затоа, ќе ви треба „мојот велосипед“ кога стандардните методи не ви одговараат, на пример:

  1. Опремата се наоѓа зад NAT и, освен вообичаената http (порта 80), сè е затворено. Ова е сосема нормална ситуација за големите федерални корпоративни мрежи. Тие можат да регистрираат пристаништа, но не веднаш, не брзо и не за вас.
  2. Нестабилен и/или „тесен“ канал за комуникација. Мала брзина, постојани загуби. Болка и фрустрација кога се обидувате да организирате тунел.
  3. Скап комуникациски канал, каде буквално секој мегабајт е важен. На пример, сателитски комуникации. Плус долги одложувања и „тесен“ опсег.
  4. Ситуација кога треба да „жонглирате“ со голем број мали рутери, на кои, од една страна, е инсталиран OpenWrt/Lede за проширување на можностите, а од друга страна, ресурсите (меморијата) на рутерот не се доволни. за сè.

Забележете број пати Што ве спречува да инсталирате флеш-уред во USB-портата на рутерот и да ја проширите меморијата на рутерот?

Најчесто, барањата се за цената на решението како целина, но понекогаш и формалниот фактор игра клучна улога. На пример, на локацијата има TP-Link ML3020, неговата единствена USB порта се користи за 2G/3G модем, сето тоа е завиткано во некакво мало пластично куќиште и поставено некаде високо, високо (на јарболот). далеку, далеку (на терен, 30 km од најблиската базна станица на мобилен оператор). Да, можете да приклучите USB хаб и да го проширите бројот на порти, но искуството покажува дека ова е незгодно и несигурно.

Така, се обидов да ви ја опишам мојата типична ситуација: „некаде далеку, далеку, има многу важен, осамен и мал рутер кој работи на Linux. Важно е барем еднаш дневно да се знае дека е „жив“ и, доколку е потребно, му се испраќаат команди, на пример, „душо, рестартирај!“

Да преминеме на имплементација:

1) На страната на рутерот, преку cron, на секои 5/10/1440 минути, или кога сакате, треба да испратите http барање до серверот користејќи wget, да го зачувате резултатот од барањето во датотека, да ја направите датотеката извршна , и извршете го.

Мојата кронска линија изгледа вака:

Датотека /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

, каде што:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai е доменот на мојот сервер. Дозволете ми веднаш да забележам: да, можете да наведете одредена IP адреса на серверот, ние го правевме ова додека нашата држава, во праведен импулс на борба, ќе кажам, не знам, го блокираше пристапот до лавовскиот дел од „облаците“ на DigitalOcean и Amazon. Ако користите симболичен домен, доколку се случи таков инцидент, можете лесно да подигнете резервен облак, да го пренасочите доменот кон него и да го вратите следењето на уредот.

a.php е името на скриптата од страна на серверот. Да, знам дека не е во ред да се именуваат променливи и имиња на датотеки со иста буква... Предлагам вака да заштедиме неколку бајти при испраќање барање :)
u - корисничко име, најава за хардвер
стр - лозинка
„-O /tmp/wa.sh“ е датотека на оддалечениот рутер каде што ќе се зачува одговорот на серверот, на пример командата за рестартирање.

Белешка број два: Ааа, зошто користиме wget, а не curl, бидејќи преку curl можете да испраќате https барања не со GET, туку со POST? Ах, затоа што, како во старата шега „НЕ се качува во теглата!“ curl вклучува библиотеки за шифрирање со големина од околу 2 MB, и поради тоа е малку веројатно дека ќе можете да составите слика за мал TP-LINK ML3020, на пример. И со wget - ве молам.

2) На страната на серверот (имам Ubuntu) ќе користиме Zabbix. Зошто: сакам да биде убаво (со графикони) и погодно (испраќајте команди преку контекстното мени). Забикс има толку прекрасна работа како агентот забикс. Преку агентот, ќе повикаме PHP скрипта на серверот, која ќе врати информации за тоа дали нашиот рутер се регистрирал во потребниот временски период. За складирање информации за времето на регистрација, команди за уреди, користам MySQL, посебна табела за корисници со приближно следните полиња:

		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;

Сите извори може да се преземат од складиштето Git на: https://github.com/BazDen/iotnet.online.git
Сега PHP скриптите поставени на страната на серверот (за погодност, тие можат да се стават во папката /usr/share/zabbix/):

a.php датотека:

<?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 (ова е скриптата на агентот zabbix наречена):

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

Па, последната фаза: регистрирање агент и додавање распореди.

Ако сè уште не сте го инсталирале агентот zabbix, тогаш:

apt-get install zabbix-agent

Уредете ја датотеката /etc/zabbix/zabbix_agentd.conf.

Додадете ја линијата:

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

, каде што:
тест е името на нашиот агент
„php /usr/share/zabbix/agent.php корисничка лозинка“ - наречена скрипта што ги покажува податоците за регистрација на уредот.

Додавање графикони: отворете го веб-интерфејсот zabbix, изберете од менито:
Поставки -> Мрежни јазли -> Креирај мрежен јазол. Тука е доволно да го наведете името на мрежниот домаќин, неговата група и стандардниот интерфејс на агентот:

Далечинско следење и контрола на уреди базирани на Lunix/OpenWrt/Lede преку портата 80…

Сега треба да додадеме податочен елемент за овој мрежен јазол. Обрнете внимание на две полиња: „клуч“ - ова е токму параметарот што го напишавме во датотеката /etc/zabbix/zabbix_agentd.conf (во нашиот случај тоа е тест) и „интервал за ажурирање“ - го поставив на 5 минути , бидејќи и опремата исто така се регистрира на серверот еднаш на секои пет минути.

Далечинско следење и контрола на уреди базирани на Lunix/OpenWrt/Lede преку портата 80…

Па, ајде да додадеме графикон. Препорачувам да изберете „Пополни“ како стил на рендерирање.

Далечинско следење и контрола на уреди базирани на Lunix/OpenWrt/Lede преку портата 80…

Излезот е нешто многу лаконски, на пример вака:

Далечинско следење и контрола на уреди базирани на Lunix/OpenWrt/Lede преку портата 80…

На разумното прашање: „дали вредеше?“, ќе одговорам: добро, се разбира, видете „причини за создавање велосипед“ на почетокот на статијата.

Ако моето прво графоманско искуство го буди интересот на читателите, тогаш во следните написи сакам да опишам како да испраќам команди до далечинска опрема. Исто така, успеавме да ја имплементираме целата шема за уреди базирани на RouterOS (Mikrotik).

Извор: www.habr.com

Додадете коментар