Monitoreo y control remoto de dispositivos basados ​​en Lunix/OpenWrt/Lede a través del puerto 80…

Hola a todos, esta es mi primera experiencia con Habré. Quiero escribir sobre cómo administrar equipos de red en una red externa de forma no estándar. Qué significa no estándar: en la mayoría de los casos, para administrar equipos en una red externa, necesita:

  • Dirección IP pública. Bueno, o si el equipo está detrás de la NAT de alguien, entonces una IP pública y un puerto “reenviado”.
  • Túnel (PPTP/OpenVPN/L2TP+IPSec, etc.) hasta el nodo central a través del cual sería accesible.

Por lo tanto, necesitarás “mi bicicleta” cuando los métodos estándar no te convengan, por ejemplo:

  1. El equipo está ubicado detrás de NAT y, salvo el habitual http (puerto 80), todo está cerrado. Esta es una situación completamente normal para las grandes redes corporativas federales. Pueden registrar puertos, pero no de inmediato, no rápidamente y no para usted.
  2. Canal de comunicación inestable y/o “estrecho”. Baja velocidad, pérdidas constantes. Dolor y frustración al intentar organizar un túnel.
  3. Un canal de comunicación caro, donde literalmente cada megabyte cuenta. Por ejemplo, las comunicaciones por satélite. Además de largos retrasos y una banda “estrecha”.
  4. Una situación en la que es necesario "hacer malabarismos" con una gran cantidad de enrutadores pequeños, en los que, por un lado, está instalado OpenWrt/Lede para ampliar las capacidades y, por otro lado, los recursos (memoria) del enrutador no son suficientes para todo.

Número de notas veces ¿Qué le impide instalar una unidad flash en el puerto USB del enrutador y ampliar la memoria del enrutador?

La mayoría de las veces, los requisitos se refieren al coste de la solución en su conjunto, pero a veces el factor de forma también juega un papel clave. Por ejemplo, en el sitio hay un TP-Link ML3020, su único puerto USB se usa para un módem 2G/3G, todo esto está envuelto en una especie de pequeña caja de plástico y colocado en algún lugar alto, alto (en el mástil), muy, muy lejos (en el campo, a 30 km de la estación base del operador de telefonía móvil más cercana). Sí, puede conectar un concentrador USB y ampliar la cantidad de puertos, pero la experiencia demuestra que esto es engorroso y poco confiable.

Entonces, traté de describirles mi situación típica: “en algún lugar muy, muy lejano, hay un enrutador pequeño, solitario y muy importante que ejecuta Linux. Es importante saber al menos una vez al día que está "vivo" y, si es necesario, se le envían comandos, por ejemplo, "¡cariño, reinicia!".

Pasemos a la implementación:

1) En el lado del enrutador, a través de cron, cada 5/10/1440 minutos, o cuando lo desee, debe enviar una solicitud http al servidor usando wget, guardar el resultado de la solicitud en un archivo y convertir el archivo en ejecutable. y ejecutarlo.

Mi línea cron se parece a esto:

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

, donde:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai es el dominio de mi servidor. Lo señalaré de inmediato: sí, puede especificar una dirección IP específica del servidor, solíamos hacer esto hasta que nuestro estado, en un justo impulso de lucha, no puedo decirlo, bloqueó el acceso a la mayor parte del Las “nubes” de DigitalOcean y Amazon. Si utiliza un dominio simbólico, si ocurre un incidente de este tipo, puede crear fácilmente una nube de respaldo, redirigir el dominio a ella y restaurar el monitoreo del dispositivo.

a.php es el nombre del script del lado del servidor. Sí, ya sé que está mal nombrar variables y nombres de archivos con la misma letra... Sugiero que de esta manera ahorremos unos cuantos bytes al enviar una solicitud :)
u - nombre de usuario, inicio de sesión de hardware
p-contraseña
“-O /tmp/wa.sh” es un archivo en el enrutador remoto donde se guardará la respuesta del servidor, por ejemplo el comando de reinicio.

Nota número dos: Ahhh, ¿por qué usamos wget y no curl, porque a través de curl puedes enviar solicitudes https no con GET, sino con POST? Ahhh porque, como dice el viejo chiste “¡NE se sube al frasco!” curl incluye bibliotecas de cifrado de aproximadamente 2 MB de tamaño y, debido a esto, es poco probable que pueda ensamblar una imagen para un TP-LINK ML3020 pequeño, por ejemplo. Y con wget, por favor.

2) Del lado del servidor (tengo Ubuntu) usaremos Zabbix. Por qué: quiero que sea hermoso (con gráficos) y conveniente (envíe comandos a través del menú contextual). Zabbix tiene algo tan maravilloso como agente zabbix. A través del agente, llamaremos a un script PHP en el servidor, que devolverá información sobre si nuestro enrutador se registró durante el período de tiempo requerido. Para almacenar información sobre el tiempo de registro, comandos para dispositivos, uso MySQL, una tabla de usuarios separada con aproximadamente los siguientes 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 las fuentes se pueden descargar desde el repositorio de Git en: https://github.com/BazDen/iotnet.online.git
Ahora los scripts PHP colocados en el lado del servidor (para mayor comodidad, se pueden colocar en la carpeta /usr/share/zabbix/):

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

Archivo Agent.php (este es el script del agente zabbix llamado):

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

Bueno, la etapa final: registrar un agente y agregar horarios.

Si aún no ha instalado el agente zabbix, entonces:

apt-get install zabbix-agent

Edite el archivo /etc/zabbix/zabbix_agentd.conf.

Añade la línea:

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

, donde:
prueba es el nombre de nuestro agente
“php /usr/share/zabbix/agent.php contraseña de usuario”: un script llamado que indica los datos de registro del dispositivo.

Agregar gráficos: abra la interfaz web de zabbix, seleccione en el menú:
Configuración -> Nodos de red -> Crear un nodo de red. Aquí basta con especificar el nombre del host de la red, su grupo y la interfaz del agente predeterminada:

Monitoreo y control remoto de dispositivos basados ​​en Lunix/OpenWrt/Lede a través del puerto 80…

Ahora necesitamos agregar un elemento de datos para este nodo de red. Preste atención a dos campos: "clave": este es exactamente el parámetro que escribimos en el archivo /etc/zabbix/zabbix_agentd.conf (en nuestro caso es prueba) y "intervalo de actualización": lo configuré en 5 minutos. , porque y el equipo también se registra en el servidor una vez cada cinco minutos.

Monitoreo y control remoto de dispositivos basados ​​en Lunix/OpenWrt/Lede a través del puerto 80…

Bueno, agreguemos un gráfico. Recomiendo elegir "Rellenar" como estilo de renderizado.

Monitoreo y control remoto de dispositivos basados ​​en Lunix/OpenWrt/Lede a través del puerto 80…

El resultado es algo muy lacónico, por ejemplo así:

Monitoreo y control remoto de dispositivos basados ​​en Lunix/OpenWrt/Lede a través del puerto 80…

A la pregunta razonable: "¿valió la pena?", Responderé: bueno, por supuesto, consulte "Razones para crear una bicicleta" al principio del artículo.

Si mi primera experiencia grafómana despierta el interés de los lectores, en los siguientes artículos quiero describir cómo enviar comandos a equipos remotos. También logramos implementar todo el esquema para dispositivos basados ​​en RouterOS (Mikrotik).

Fuente: habr.com

Añadir un comentario