Monitoreo y administración remotos de dispositivos basados ​​en Linux / OpenWrt / Lede a través del puerto 80 ...

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

  • La dirección IP pública. Bueno, o si el equipo está ubicado detrás del NAT de alguien, entonces la IP pública y el puerto "reenviado".
  • El túnel (PPTP / OpenVPN / L2TP + IPSec, etc.) al nodo central a través del cual sería accesible.

Por lo tanto, necesitará mi bicicleta cuando los métodos estándar no sean adecuados para usted, por ejemplo:
  1. El equipo está ubicado detrás del NAT y, aparte del http habitual (puerto 80), todo está cerrado. La situación es bastante normal para las grandes redes corporativas federales. Registre puertos: pueden, pero no de forma inmediata, no rápida y no para usted.
  2. Canal de comunicación inestable y / o "estrecho". Baja velocidad, pérdida constante. Dolor y frustración al intentar organizar un túnel.
  3. Un canal de comunicación costoso, donde literalmente cada megabyte cuenta. Por ejemplo comunicaciones satelitales. Además de grandes retrasos y una franja "estrecha".
  4. La situación en la que necesita "hacer malabarismos" con una gran cantidad de enrutadores pequeños, en los que, por un lado, se instala OpenWrt / Lede para ampliar las capacidades y, por otro lado, los recursos (memoria) del enrutador están lejos de ser suficientes.

Nota número veces
¿Y qué impide que se instale una memoria USB del enrutador y expanda la memoria del enrutador?

Muy a menudo, los requisitos para el costo de la solución en su conjunto, pero a veces el factor de forma también juega un papel clave. Por ejemplo, TP-Link ML3020 está en el objeto, su único puerto USB se usa para un módem 2G / 3G, todo esto está envuelto en un hilo con una pequeña caja de plástico y se coloca en algún lugar alto, alto (en el mástil), lejos, lejos (en campo, a 30 km de la estación base más cercana de un operador móvil). Sí, puede conectar un concentrador USB y ampliar la cantidad de puertos, pero la experiencia ha demostrado 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 muy importante, solitario y pequeño que ejecuta Linux. Es importante saber al menos una vez al día que está "vivo" y, si es necesario, se le enviaron comandos, por ejemplo, "¡sol, reinicie!"

Pasemos a la implementación:

1) En el lado del enrutador, cron cada 5/10/1440 minutos, o cada vez que necesite enviar una solicitud http al servidor usando wget, guarde el resultado de la solicitud en un archivo, haga que el archivo sea ejecutable y ejecútelo.

Mi línea en cron se ve así:

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 - el dominio de mi servidor. Notaré de inmediato: sí, también puede especificar una dirección IP de servidor específica, lo hicimos antes, mientras que nuestro estado, en un exabrupto de lucha, ya no me pareció, no bloqueó el acceso a la mayor parte de las "nubes" de DigitalOcean y Amazon. En el caso de utilizar un dominio simbólico, cuando se produce un incidente de este tipo, puede elevar tranquilamente la nube de respaldo, redirigir el dominio a este y restaurar la supervisión del dispositivo.

a.php: el nombre de la secuencia de comandos en el lado del servidor. Sí, sé que está mal nombrar variables y nombres de archivos con una letra ... Sugiero que guardemos algunos bytes al enviar una solicitud :)
u - nombre de usuario, inicio de sesión de hardware
p - contraseña
"-O /tmp/wa.sh" es el 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, no curl, porque a través de curl puedes enviar solicitudes https y no GET, sino POST? Ahhh, porque como en el viejo chiste "¡NE se mete en la choza!". Curl incluye bibliotecas de cifrado de aproximadamente 2 MB de tamaño, y en virtud de esto, podrá ensamblar una imagen para un pequeño TP-LINK ML3020, por ejemplo. Y con wget, por favor.

2) En el 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 una cosa tan encantadora como un agente zabbix. A través del agente, llamaremos al script php en el servidor, que devolverá información sobre si nuestro enrutador se registró en 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 tomar del repositorio de Git en: https://github.com/BazDen/iotnet.online.git
Ahora los scripts PHP alojados en el lado del servidor (por conveniencia, puede ponerlos en la carpeta / usr / share / zabbix /):

Archivo 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("Ymd 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 llamado 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(); ?> 

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

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

 apt-get install zabbix-agent 

Edición del archivo /etc/zabbix/zabbix_agentd.conf.

Agrega la línea:

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

donde:
prueba es el nombre de nuestro agente
"Contraseña de usuario php /usr/share/zabbix/agent.php": el script llamado con los datos de registro del dispositivo.

Agregar gráficos: abra la interfaz web de zabbix, seleccione del menú:
Configuración -> Hosts -> Crear host. Es suficiente especificar el nombre de host, su grupo, la interfaz de agente predeterminada:



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



Bueno, agrega el horario. Recomiendo elegir "Relleno" como estilo de dibujo.



El resultado es algo muy conciso, por ejemplo, así:



A la pregunta razonable: “¿Valió la pena?”, Responderé: bueno, por supuesto, vea las “razones para crear una bicicleta” al comienzo del artículo.

Si mi primera experiencia grafomaníaca despertará el interés de los lectores, en los siguientes artículos quiero describir cómo enviar comandos a equipos remotos. También fue posible implementar todo el esquema para dispositivos basados ​​en RouterOS (Mikrotiks).

Source: https://habr.com/ru/post/445568/


All Articles