Даљинско праћење и контрола Луник/ОпенВрт/Леде уређаја преко порта 80…

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

  • Јавна ИП адреса. Па, или ако опрема стоји иза нечијег НАТ-а, онда јавни ИП и „прослеђени“ порт.
  • Тунел (ППТП/ОпенВПН/Л2ТП+ИПСец, итд.) до централног чвора кроз који би био доступан.

Стога ће вам требати "мој бицикл" када вам стандардне методе не одговарају, на пример:

  1. Опрема се налази иза НАТ-а и, осим уобичајеног хттп (порт 80), све је затворено. Ово је сасвим нормална ситуација за велике федералне корпоративне мреже. Они могу да региструју портове, али не одмах, не брзо и не за вас.
  2. Нестабилан и/или „узак“ канал комуникације. Мала брзина, стални губици. Бол и фрустрација када покушавате да организујете тунел.
  3. Скуп комуникациони канал, где се буквално сваки мегабајт рачуна. На пример, сателитске комуникације. Плус дуга кашњења и „уски” опсег.
  4. Ситуација када треба да "жонглирате" великим бројем малих рутера, на којима је, с једне стране, инсталиран ОпенВрт/Леде за проширење могућности, а са друге стране, ресурси (меморија) рутера нису довољни за све.

Напомена број пута Шта вас спречава да инсталирате флеш диск у УСБ порт рутера и проширите меморију рутера?

Најчешће су захтеви за цену решења у целини, али понекад фактор форме такође игра кључну улогу. На пример, на сајту постоји ТП-Линк МЛ3020, његов једини УСБ порт се користи за 2Г/3Г модем, све је то умотано у неку врсту мале пластичне кутије и постављено негде високо, високо (на јарбол), далеко, далеко (на терену, 30 км од базне станице најближег мобилног оператера). Да, можете прикључити УСБ чвориште и проширити број портова, али искуство показује да је то гломазно и непоуздано.

Дакле, покушао сам да вам опишем своју типичну ситуацију: „негде далеко, далеко, постоји веома важан, усамљен и мали рутер који покреће Линук. Важно је бар једном дневно знати да је "жив" и, ако је потребно, шаљу му се команде, на пример, "душо, поново покрени!"

Пређимо на имплементацију:

1) На страни рутера, преко црон-а, сваких 5/10/1440 минута, или кад год желите, потребно је да пошаљете хттп захтев серверу користећи вгет, сачувате резултат захтева у датотеци, учините датотеку извршном , и извршите га.

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

Фајл /етц/цронтабс/роот:

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

, где:
кн--80абгфбдванб2акугдрд3а2е5гсбј.кн--п1аи је домен мог сервера. Одмах да приметим: да, можете да наведете конкретну ИП адресу сервера, то смо радили све док наша држава, у праведном нагону борбе, рећи ћу, не знам, није блокирала приступ лавовском удео „облака” ДигиталОцеана и Амазона. Ако користите симболички домен, ако дође до таквог инцидента, можете лако да подигнете резервни облак, преусмерите домен на њега и вратите праћење уређаја.

а.пхп је име скрипте на страни сервера. Да, знам да је погрешно називати променљиве и називе фајлова истим словом... Предлажем да на овај начин сачувамо неколико бајтова приликом слања захтева :)
у - корисничко име, пријава на хардвер
п - лозинка
„-О /тмп/ва.сх“ је датотека на удаљеном рутеру у којој ће бити сачуван одговор сервера, на пример команда за поновно покретање.

Напомена број два: Аххх, зашто користимо вгет а не цурл, јер преко цурл-а можете слати хттпс захтеве не са ГЕТ-ом, већ са ПОСТ-ом? Аххх јер, као у старом вицу "НЕ се пење у теглу!" цурл укључује библиотеке за шифровање величине око 2МБ, и због тога је мало вероватно да ћете моћи да саставите слику за мали ТП-ЛИНК МЛ3020, на пример. А са вгет-ом - молим.

2) На страни сервера (имам Убунту) користићемо Заббик. Зашто: Желим да буде лепо (са графиконима) и згодно (шаљи команде преко контекстног менија). Заббик има тако дивну ствар као што је заббик агент. Преко агента ћемо на серверу позвати ПХП скрипту, која ће вратити информацију о томе да ли се наш рутер регистровао у потребном временском периоду. За чување информација о времену регистрације, командама за уређаје, користим МиСКЛ, посебну табелу корисника са приближно следећим пољима:

		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;

Сви извори се могу преузети из Гит спремишта на: https://github.com/BazDen/iotnet.online.git
Сада су ПХП скрипте постављене на страни сервера (ради погодности, могу се поставити у фасциклу /уср/схаре/заббик/):

а.пхп датотека:

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

Агент.пхп фајл (ово је скрипта заббик агента):

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

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

Ако још нисте инсталирали заббик агента, онда:

apt-get install zabbix-agent

Уредите датотеку /етц/заббик/заббик_агентд.цонф.

Додајте ред:

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

, где:
тест је име нашег агента
“пхп /уср/схаре/заббик/агент.пхп корисничка лозинка” - позвана скрипта која указује на податке о регистрацији уређаја.

Додавање графикона: отворите заббик веб интерфејс, изаберите из менија:
Подешавања -> Мрежни чворови -> Креирајте мрежни чвор. Овде је довољно да наведете име мрежног хоста, његову групу и подразумевани интерфејс агента:

Даљинско праћење и контрола Луник/ОпенВрт/Леде уређаја преко порта 80…

Сада морамо да додамо елемент података за овај мрежни чвор. Обратите пажњу на два поља: „кључ“ – то је управо параметар који смо написали у датотеку /етц/заббик/заббик_агентд.цонф (у нашем случају је тест), и „интервал ажурирања“ – поставио сам га на 5 минута , јер и опрема се такође региструје на серверу једном у пет минута.

Даљинско праћење и контрола Луник/ОпенВрт/Леде уређаја преко порта 80…

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

Даљинско праћење и контрола Луник/ОпенВрт/Леде уређаја преко порта 80…

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

Даљинско праћење и контрола Луник/ОпенВрт/Леде уређаја преко порта 80…

На разумно питање: "да ли је вредело?", одговорићу: па, наравно, погледајте "разлоге за стварање бицикла" на почетку чланка.

Ако моје прво графоманско искуство изазове интересовање читалаца, онда у следећим чланцима желим да опишем како да шаљем команде удаљеној опреми. Такође смо успели да имплементирамо целу шему за уређаје засноване на РоутерОС-у (Микротик).

Извор: ввв.хабр.цом

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