Remote monitoring at kontrol ng Lunix/OpenWrt/Lede based na device sa pamamagitan ng port 80…

Kumusta sa lahat, ito ang aking unang karanasan sa Habré. Gusto kong magsulat tungkol sa kung paano pamahalaan ang mga kagamitan sa network sa isang panlabas na network sa isang hindi karaniwang paraan. Ano ang ibig sabihin ng hindi pamantayan: sa karamihan ng mga kaso, upang pamahalaan ang kagamitan sa isang panlabas na network kailangan mo:

  • Pampublikong IP address. Well, o kung ang kagamitan ay nasa likod ng NAT ng isang tao, pagkatapos ay isang pampublikong IP at isang "ipinasa" na port.
  • Tunnel (PPTP/OpenVPN/L2TP+IPSec, atbp.) sa gitnang node kung saan ito maa-access.

Samakatuwid, kakailanganin mo ang "aking bisikleta" kapag ang mga karaniwang pamamaraan ay hindi angkop sa iyo, halimbawa:

  1. Ang kagamitan ay matatagpuan sa likod ng NAT at, maliban sa karaniwang http (port 80), lahat ay sarado. Ito ay isang ganap na normal na sitwasyon para sa malalaking pederal na corporate network. Maaari silang magrehistro ng mga port, ngunit hindi kaagad, hindi mabilis, at hindi para sa iyo.
  2. Hindi matatag at/o “makitid” na channel ng komunikasyon. Mababang bilis, pare-pareho ang pagkalugi. Sakit at pagkabigo kapag sinusubukang ayusin ang isang lagusan.
  3. Isang mamahaling channel ng komunikasyon, kung saan literal na binibilang ang bawat megabyte. Halimbawa, mga komunikasyon sa satellite. Dagdag pa ang mahabang pagkaantala at isang "makitid" na banda.
  4. Isang sitwasyon kung kailan kailangan mong "mag-juggle" ng isang malaking bilang ng mga maliliit na router, kung saan, sa isang banda, naka-install ang OpenWrt/Lede upang mapalawak ang mga kakayahan, at sa kabilang banda, ang mga mapagkukunan (memorya) ng router ay hindi sapat para sa lahat.

Tandaan ang bilang ng mga beses Ano ang pumipigil sa iyo na mag-install ng flash drive sa USB port ng router at palawakin ang memorya ng router?

Kadalasan, ang mga kinakailangan ay para sa halaga ng solusyon sa kabuuan, ngunit kung minsan ang form factor ay gumaganap din ng isang mahalagang papel. Halimbawa, mayroong isang TP-Link ML3020 sa site, ang tanging USB port nito ay ginagamit para sa isang 2G/3G modem, ang lahat ng ito ay nakabalot sa ilang uri ng maliit na plastic case at inilagay sa isang lugar na mataas, mataas (sa palo), malayo, malayo (sa field, 30 km mula sa pinakamalapit na mobile operator base station). Oo, maaari kang magsaksak ng USB hub at palawakin ang bilang ng mga port, ngunit ipinapakita ng karanasan na ito ay mahirap at hindi maaasahan.

Kaya, sinubukan kong ilarawan sa iyo ang aking karaniwang sitwasyon: "sa isang lugar na malayo, malayo, mayroong isang napakahalaga, malungkot at maliit na router na tumatakbo sa Linux. Mahalagang malaman kahit isang beses sa isang araw na siya ay "buhay" at, kung kinakailangan, ang mga utos ay ipinadala sa kanya, halimbawa, "honey, reboot!"

Lumipat tayo sa pagpapatupad:

1) Sa gilid ng router, sa pamamagitan ng cron, tuwing 5/10/1440 minuto, o kahit kailan mo gusto, kailangan mong magpadala ng http request sa server gamit ang wget, i-save ang resulta ng request sa isang file, gawin ang file executable , at isagawa ito.

Ang aking cron line ay ganito ang hitsura:

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

, kung saan:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai ang domain ng aking server. Hayaan akong tandaan kaagad: oo, maaari mong tukuyin ang isang tiyak na IP address ng server, dati naming ginagawa ito hanggang sa aming estado, sa isang matuwid na salpok ng pakikibaka, sasabihin ko, hindi ko alam, hinarangan ang pag-access sa leon. bahagi ng DigitalOcean at Amazon “clouds”. Kung gumagamit ka ng simbolikong domain, kung mangyari ang naturang insidente, madali mong maitataas ang isang backup na cloud, i-redirect ang domain dito at maibalik ang pagsubaybay sa device.

a.php ay ang pangalan ng server-side script. Oo, alam kong mali ang pangalanan ang mga variable at mga pangalan ng file na may parehong titik... Iminumungkahi ko na sa ganitong paraan mag-save tayo ng ilang byte kapag nagpapadala ng kahilingan :)
u - username, pag-login sa hardware
p - password
Ang “-O /tmp/wa.sh” ay isang file sa remote router kung saan ise-save ang tugon ng server, halimbawa ang reboot command.

Tandaan bilang dalawa: Ahhh, bakit wget ang ginagamit namin at hindi curl, dahil sa pamamagitan ng curl maaari kang magpadala ng mga kahilingan sa https hindi sa GET, ngunit sa POST? Ahhh kasi, as in the old joke “NE climbs into the jar!” Kasama sa curl ang mga aklatan ng pag-encrypt na humigit-kumulang 2MB ang laki at dahil dito ay malamang na hindi ka makakapag-ipon ng isang imahe para sa isang maliit na TP-LINK ML3020, halimbawa. At sa wget - pakiusap.

2) Sa server side (may Ubuntu ako) gagamitin namin ang Zabbix. Bakit: Gusto ko itong maging maganda (na may mga graph) at maginhawa (magpadala ng mga utos sa pamamagitan ng menu ng konteksto). Ang Zabbix ay may napakagandang bagay gaya ng ahente ng zabbix. Sa pamamagitan ng ahente, tatawag kami ng PHP script sa server, na magbabalik ng impormasyon tungkol sa kung nakarehistro ang aming router sa kinakailangang yugto ng panahon. Upang mag-imbak ng impormasyon tungkol sa oras ng pagpaparehistro, mga utos para sa mga device, gumagamit ako ng MySQL, isang hiwalay na mga user ng talahanayan na may humigit-kumulang sa mga sumusunod na field:

		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;

Ang lahat ng mga mapagkukunan ay maaaring ma-download mula sa Git repository sa: https://github.com/BazDen/iotnet.online.git
Ngayon ang mga script ng PHP ay inilagay sa gilid ng server (para sa kaginhawahan, maaari silang ilagay sa /usr/share/zabbix/ folder):

a.php file:

<?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 file (ito ang script ng zabbix agent na tinatawag):

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

Well, ang huling yugto: pagrehistro ng isang ahente at pagdaragdag ng mga iskedyul.

Kung hindi mo pa na-install ang zabbix agent, kung gayon:

apt-get install zabbix-agent

I-edit ang file /etc/zabbix/zabbix_agentd.conf.

Idagdag ang linya:

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

, kung saan:
pagsubok ang pangalan ng aming ahente
“php /usr/share/zabbix/agent.php user password” - isang tinatawag na script na nagsasaad ng data ng pagpaparehistro ng device.

Pagdaragdag ng mga chart: buksan ang zabbix web interface, pumili mula sa menu:
Mga Setting -> Network node -> Lumikha ng network node. Dito sapat na upang tukuyin ang pangalan ng host ng network, ang grupo nito, at ang default na interface ng ahente:

Remote monitoring at kontrol ng Lunix/OpenWrt/Lede based na device sa pamamagitan ng port 80…

Ngayon ay kailangan nating magdagdag ng elemento ng data para sa network node na ito. Bigyang-pansin ang dalawang field: "key" - ito mismo ang parameter na isinulat namin sa /etc/zabbix/zabbix_agentd.conf file (sa aming kaso ito ay pagsubok), at "update interval" - Itinakda ko ito sa 5 minuto , dahil at ang kagamitan ay nakarehistro din sa server isang beses bawat limang minuto.

Remote monitoring at kontrol ng Lunix/OpenWrt/Lede based na device sa pamamagitan ng port 80…

Well, magdagdag tayo ng isang graph. Inirerekomenda kong piliin ang "Punan" bilang istilo ng pag-render.

Remote monitoring at kontrol ng Lunix/OpenWrt/Lede based na device sa pamamagitan ng port 80…

Ang output ay isang bagay na napaka laconic, halimbawa tulad nito:

Remote monitoring at kontrol ng Lunix/OpenWrt/Lede based na device sa pamamagitan ng port 80…

Sa makatwirang tanong: "nagkakahalaga ba ito?", Sasagutin ko: well, siyempre, tingnan ang "mga dahilan para sa paglikha ng isang bisikleta" sa simula ng artikulo.

Kung ang aking unang karanasan sa graphomaniac ay pumukaw ng interes ng mga mambabasa, pagkatapos ay sa mga sumusunod na artikulo gusto kong ilarawan kung paano magpadala ng mga utos sa mga malalayong kagamitan. Nagawa rin naming ipatupad ang buong scheme para sa mga device batay sa RouterOS (Mikrotik).

Pinagmulan: www.habr.com

Magdagdag ng komento