Выдалены маніторынг і кіраванне прылад на базе 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 км ад бліжэйшай базавай станцыі мабільнага аператара). Так, можна ўторкнуць USB-hub і пашырыць лік партоў, але досвед паказвае што гэта грувастка і ненадзейна.

Такім чынам, я пастараўся апісаць Вам маю тыпавую сітуацыю: «дзесьці далёка-далёка, стаіць вельмі важны, самотны і маленькі роўтэр пад кіраваннем Linux. Важна ведаць хоць бы раз у дзень, што ён „жывы“ і пры неабходнасці адсылаецца яму каманды, напрыклад „сонейка, перазагрузіся!“

Пяройдзем да рэалізацыі:

1) На баку роўтара па cron-у кожныя 5/10/1440 хвілін, ці калі заўгодна неабходна адсылаць http-запыт на сервер з дапамогай wget, вынік запыту захоўваць у файл, файл рабіць выкананым, і выконваць яго.

У мяне радок у cron-е выглядае прыкладна так:

Файл /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 - імя карыстальніка, лагін жалязякі
p - пароль
"-O /tmp/wa.sh" — файл на выдаленым роўтары, куды будзе захаваюцца адказ сервера, напрыклад каманда reboot.

Заўвага нумар два: Аааа, чаму мы выкарыстоўваем wget, а не curl, бо праз curl можна адпраўляць https запыты і не GET-ым, а POST-ым? Аааа таму, што як у старым анекдоце "У гладышу нЭ лезе!". У склад curl уваходзяць бібліятэкі шыфравання памерам каля 2МБ і ў сілу гэтага вярнулі Вам атрымаецца сабраць выяву для маленькага TP-LINK ML3020 да прыкладу. А з wget - калі ласка.

2) На баку сервера (у мяне гэта Ubuntu) мы будзем выкарыстоўваць Zabbix. Чаму: хачу каб было прыгожа (з графікамі) і зручна (адпраўляць каманды праз кантэкстнае меню). У Забікса ёсць такая цудоўная рэч, як zabbix-агент. Праз агента мы будзем выклікаць php-скрыпт на серверы, які будзе вяртаць інфармацыю аб тым, ці рэгістраваўся наш роўтар у патрэбны перыяд часу. Для захоўвання інфармацыі аб часе рэгістрацыі, камандах для прылад, я выкарыстоўваю MySQL, асобную табліцу users прыкладна з такімі палямі:

		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

, дзе:
test - імя нашага агента
„php /usr/share/zabbix/agent.php user password“ — выкліканы скрыпт з указаннем рэгістрацыйных дадзеных прылады.

Даданне графікаў: адчыняны web-інтэрфейс zabbix, у меню выбіраемы:
Настройка -> Вузлы сеткі -> Стварыць вузел сеткі. Тут дастаткова пазначыць імя вузла сеткі, яго групу, інтэрфейс агента па змаўчанні:

Выдалены маніторынг і кіраванне прылад на базе Lunix/OpenWrt/Lede праз 80-ты порт…

Цяпер нам для дадзенага вузла сеткі трэба дадаць элемент даных. Звярніце ўвагу на два палі: „ключ“ — гэта якраз той параметр, што мы прапісвалі ў файле /etc/zabbix/zabbix_agentd.conf (у нашым выпадку гэта test), і „інтэрвал абнаўлення“ — я стаўлю 5 хвілін, бо і абсталяванне рэгіструецца на серверы таксама адзін раз у пяць хвілін.

Выдалены маніторынг і кіраванне прылад на базе Lunix/OpenWrt/Lede праз 80-ты порт…

Ну і дадаем графік. Рэкамендую ў якасці стылю адмалёўкі абраць „Запаўненне“.

Выдалены маніторынг і кіраванне прылад на базе Lunix/OpenWrt/Lede праз 80-ты порт…

На выхадзе атрымліваецца нешта вельмі лаканічнае, напрыклад вось так:

Выдалены маніторынг і кіраванне прылад на базе Lunix/OpenWrt/Lede праз 80-ты порт…

На слушнае пытанне: „і гэта таго каштавала?“, адкажу: ну вядома, гледзіце „прычыны стварэння ровара“ у пачатку артыкула.

Калі мой першы графаманскі досвед выкліча цікавасць чытачоў, то ў наступных артыкулах я жадаю апісаць як адпраўляць каманды на выдаленае абсталяванне. Таксама атрымалася рэалізаваць усю схему і для прылад на базе RouterOS (Mikrotik-ов).

Крыніца: habr.com

Дадаць каментар