Monitorización e control remoto de dispositivos baseados en Lunix/OpenWrt/Lede a través do porto 80...

Ola a todos, esta é a miña primeira experiencia en Habré. Quero escribir sobre como xestionar os equipos de rede nunha rede externa dun xeito non estándar. Que significa non estándar: na maioría dos casos, para xestionar equipos nunha rede externa necesitas:

  • Enderezo IP público. Ben, ou se o equipo está detrás do NAT de alguén, entón unha IP pública e un porto "reenviado".
  • Túnel (PPTP/OpenVPN/L2TP+IPSec, etc.) ata o nodo central a través do cal sería accesible.

Polo tanto, necesitarás "a miña bicicleta" cando os métodos estándar non che conveñan, por exemplo:

  1. O equipo está situado detrás de NAT e, salvo o habitual http (porto 80), todo está pechado. Esta é unha situación completamente normal para as grandes redes corporativas federais. Poden rexistrar portos, pero non de inmediato, non rapidamente e non para ti.
  2. Canle de comunicación inestable e/ou “estreita”. Baixa velocidade, perdas constantes. Dor e frustración ao tentar organizar un túnel.
  3. Unha canle de comunicación cara, onde literalmente cada megabyte conta. Por exemplo, as comunicacións por satélite. Ademais de longos atrasos e unha banda "estreita".
  4. Unha situación na que cómpre "malabarizar" un gran número de pequenos enrutadores, nos que, por unha banda, está instalado OpenWrt/Lede para ampliar as capacidades e, por outra banda, os recursos (memoria) do enrutador non son suficientes. para todo.

Anota o número de veces Que lle impide instalar unha unidade flash no porto USB do router e ampliar a memoria do router?

Na maioría das veces, os requisitos son para o custo da solución no seu conxunto, pero ás veces o factor de forma tamén xoga un papel fundamental. Por exemplo, hai un TP-Link ML3020 no sitio, o seu único porto USB utilízase para un módem 2G/3G, todo isto está envolto nunha pequena caixa de plástico e colocado nalgún lugar alto, alto (no mástil), lonxe, moi lonxe (en campo, a 30 km da estación base de operador móbil máis próxima). Si, podes conectar un concentrador USB e ampliar o número de portos, pero a experiencia demostra que é complicado e pouco fiable.

Entón, tentei describirche a miña típica situación: “nalgún lugar moi, moi lonxe, hai un enrutador moi importante, solitario e pequeno que executa Linux. É importante saber polo menos unha vez ao día que está "vivo" e, se é necesario, envíanlle ordes, por exemplo, "cariño, reinicia!"

Pasemos á implementación:

1) No lado do enrutador, a través de cron, cada 5/10/1440 minutos, ou sempre que queiras, cómpre enviar unha solicitude http ao servidor mediante wget, gardar o resultado da solicitude nun ficheiro, facer que o ficheiro sexa executable , e executalo.

A miña liña cron parece algo así:

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

onde:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai é o dominio do meu servidor. Notarei de inmediato: si, podes especificar un enderezo IP específico do servidor, facíamos isto ata que o noso estado, nun xusto impulso de loita, digo, non sei, bloqueou o acceso a a parte do león das "nubes" de DigitalOcean e Amazon. Se usas un dominio simbólico, se ocorre un incidente deste tipo, podes crear facilmente unha nube de copia de seguridade, redirixir o dominio a el e restaurar a monitorización do dispositivo.

a.php é o nome do script do servidor. Si, sei que é incorrecto nomear variables e nomes de ficheiro coa mesma letra... Suxiro que deste xeito gardemos uns bytes ao enviar unha solicitude :)
u - nome de usuario, inicio de sesión de hardware
p - contrasinal
"-O /tmp/wa.sh" é un ficheiro do enrutador remoto onde se gardará a resposta do servidor, por exemplo o comando de reinicio.

Nota número dous: Ahhh, por que usamos wget e non curl, porque mediante curl podes enviar solicitudes https non con GET, senón con POST? Ahhh porque, como na vella broma "NE sobe ao frasco!" curl inclúe bibliotecas de cifrado duns 2 MB de tamaño e, por iso, é pouco probable que poidas montar unha imaxe para un pequeno TP-LINK ML3020, por exemplo. E con wget - por favor.

2) No lado do servidor (teño Ubuntu) usaremos Zabbix. Por que: quero que sexa bonito (con gráficos) e cómodo (enviar comandos a través do menú contextual). Zabbix ten unha cousa tan marabillosa como o axente zabbix. A través do axente, chamaremos un script PHP no servidor, que devolverá información sobre se o noso enrutador rexistrouse durante o período de tempo necesario. Para almacenar información sobre o tempo de rexistro, comandos para dispositivos, uso MySQL, unha táboa separada de usuarios con aproximadamente os seguintes campos:

		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;

Todas as fontes pódense descargar desde o repositorio de Git en: https://github.com/BazDen/iotnet.online.git
Agora os scripts PHP colócanse no lado do servidor (por comodidade, pódense colocar no cartafol /usr/share/zabbix/):

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

Ficheiro Agent.php (este é o script do axente zabbix chamado):

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

Ben, a fase final: rexistrar un axente e engadir horarios.

Se aínda non instalou o axente zabbix, entón:

apt-get install zabbix-agent

Edite o ficheiro /etc/zabbix/zabbix_agentd.conf.

Engade a liña:

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

onde:
test é o nome do noso axente
"php /usr/share/zabbix/agent.php contrasinal de usuario" - un script chamado que indica os datos de rexistro do dispositivo.

Engadindo gráficos: abra a interface web de zabbix, seleccione no menú:
Configuración -> Nodos de rede -> Crear un nodo de rede. Aquí basta con especificar o nome do servidor de rede, o seu grupo e a interface de axente predeterminada:

Monitorización e control remoto de dispositivos baseados en Lunix/OpenWrt/Lede a través do porto 80...

Agora necesitamos engadir un elemento de datos para este nodo de rede. Preste atención a dous campos: "clave" - ​​este é exactamente o parámetro que escribimos no ficheiro /etc/zabbix/zabbix_agentd.conf (no noso caso é proba) e "intervalo de actualización": axusteino a 5 minutos , porque e o equipo tamén se rexistra no servidor unha vez cada cinco minutos.

Monitorización e control remoto de dispositivos baseados en Lunix/OpenWrt/Lede a través do porto 80...

Ben, imos engadir unha gráfica. Recomendo escoller "Encher" como estilo de renderizado.

Monitorización e control remoto de dispositivos baseados en Lunix/OpenWrt/Lede a través do porto 80...

A saída é algo moi lacónico, por exemplo:

Monitorización e control remoto de dispositivos baseados en Lunix/OpenWrt/Lede a través do porto 80...

Á pregunta razoable: "paceu a pena?", responderei: ben, por suposto, consulte "motivos para crear unha bicicleta" ao comezo do artigo.

Se a miña primeira experiencia de grafomanía esperta o interese dos lectores, nos seguintes artigos quero describir como enviar comandos a equipos remotos. Tamén conseguimos implementar todo o esquema para dispositivos baseados en RouterOS (Mikrotik).

Fonte: www.habr.com

Engadir un comentario