Monitoramento e controle remoto de dispositivos baseados em Lunix/OpenWrt/Lede via porta 80…

Olá a todos, esta é minha primeira experiência no Habré. Quero escrever sobre como gerenciar equipamentos de rede em uma rede externa de maneira não padronizada. O que significa fora do padrão: na maioria dos casos, para gerenciar equipamentos em uma rede externa, você precisa de:

  • Endereço IP público. Bem, ou se o equipamento estiver atrás do NAT de alguém, então um IP público e uma porta “encaminhada”.
  • Túnel (PPTP/OpenVPN/L2TP+IPSec, etc.) para o nó central através do qual seria acessível.

Portanto, você precisará de “minha bicicleta” quando os métodos padrão não forem adequados para você, por exemplo:

  1. O equipamento está localizado atrás do NAT e, exceto o habitual http (porta 80), está tudo fechado. Esta é uma situação completamente normal para grandes redes corporativas federais. Eles podem registrar portas, mas não imediatamente, não rapidamente e não para você.
  2. Canal de comunicação instável e/ou “estreito”. Baixa velocidade, perdas constantes. Dor e frustração ao tentar organizar um túnel.
  3. Um canal de comunicação caro, onde literalmente cada megabyte conta. Por exemplo, comunicações por satélite. Além de longos atrasos e uma banda “estreita”.
  4. Uma situação em que é necessário “fazer malabarismos” com um grande número de pequenos roteadores, nos quais, por um lado, o OpenWrt/Lede está instalado para expandir capacidades e, por outro lado, os recursos (memória) do roteador não são suficientes para tudo.

Anote o número de vezes O que impede você de instalar uma unidade flash na porta USB do roteador e expandir a memória do roteador?

Na maioria das vezes, os requisitos referem-se ao custo da solução como um todo, mas às vezes o formato também desempenha um papel fundamental. Por exemplo, existe um TP-Link ML3020 no local, sua única porta USB é usada para um modem 2G/3G, tudo isso é embrulhado em uma espécie de pequena caixa de plástico e colocado em algum lugar bem alto (no mastro), muito, muito longe (em campo, a 30 km da estação base da operadora móvel mais próxima). Sim, você pode conectar um hub USB e expandir o número de portas, mas a experiência mostra que isso é complicado e não confiável.

Então, tentei descrever para vocês minha situação típica: “em algum lugar muito, muito distante, existe um roteador muito importante, solitário e pequeno rodando Linux. É importante saber pelo menos uma vez ao dia que ele está “vivo” e, se necessário, são enviados comandos para ele, por exemplo, “querido, reinicie!”

Vamos passar para a implementação:

1) Do lado do roteador, via cron, a cada 5/10/1440 minutos, ou quando quiser, você precisa enviar uma solicitação http para o servidor usando wget, salvar o resultado da solicitação em um arquivo, tornar o arquivo executável e execute-o.

Minha linha cron é mais ou menos assim:

Arquivo /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 domínio do meu servidor. Deixe-me observar desde já: sim, você pode especificar um endereço IP específico do servidor, costumávamos fazer isso até o nosso estado, num justo impulso de luta, direi, não sei, bloqueou o acesso ao leão participação das “nuvens” DigitalOcean e Amazon. Se você usar um domínio simbólico, se tal incidente ocorrer, você poderá facilmente criar uma nuvem de backup, redirecionar o domínio para ela e restaurar o monitoramento do dispositivo.

a.php é o nome do script do lado do servidor. Sim, eu sei que é errado nomear variáveis ​​e nomes de arquivos com a mesma letra... Sugiro que assim economizemos alguns bytes ao enviar uma solicitação :)
u - nome de usuário, login de hardware
p - senha
“-O /tmp/wa.sh” é um arquivo no roteador remoto onde a resposta do servidor, por exemplo o comando de reinicialização, será salva.

Nota número dois: Ahhh, por que usamos wget e não curl, porque via curl você pode enviar solicitações https não com GET, mas com POST? Ahhh porque, como na velha piada “NE sobe na jarra!” curl inclui bibliotecas de criptografia de cerca de 2 MB e por isso é improvável que você consiga montar uma imagem para um pequeno TP-LINK ML3020, por exemplo. E com wget - por favor.

2) No lado do servidor (tenho Ubuntu) usaremos Zabbix. Por quê: quero que seja bonito (com gráficos) e conveniente (envie comandos através do menu de contexto). Zabbix tem algo maravilhoso como o agente zabbix. Através do agente, chamaremos um script PHP no servidor, que retornará informações sobre se nosso roteador foi registrado no período necessário. Para armazenar informações sobre horário de registro, comandos para dispositivos, utilizo MySQL, uma tabela separada de usuários com 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 podem ser baixadas do repositório Git em: https://github.com/BazDen/iotnet.online.git
Agora os scripts PHP são colocados no lado do servidor (por conveniência, eles podem ser colocados na pasta /usr/share/zabbix/):

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

Arquivo Agent.php (este é o script do agente 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();
?>		

Bom, a etapa final: cadastrar um agente e adicionar horários.

Se você ainda não instalou o agente zabbix, então:

apt-get install zabbix-agent

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

Adicione a linha:

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

, onde:
test é o nome do nosso agente
“php /usr/share/zabbix/agent.php user password” - um script chamado que indica os dados de registro do dispositivo.

Adicionando gráficos: abra a interface web do zabbix, selecione no menu:
Configurações -> Nós de rede -> Crie um nó de rede. Aqui basta especificar o nome do host da rede, seu grupo e a interface do agente padrão:

Monitoramento e controle remoto de dispositivos baseados em Lunix/OpenWrt/Lede via porta 80…

Agora precisamos adicionar um elemento de dados para este nó da rede. Preste atenção em dois campos: “chave” - este é exatamente o parâmetro que escrevemos no arquivo /etc/zabbix/zabbix_agentd.conf (no nosso caso é teste) e “intervalo de atualização” - configurei para 5 minutos , pois e o equipamento também é cadastrado no servidor uma vez a cada cinco minutos.

Monitoramento e controle remoto de dispositivos baseados em Lunix/OpenWrt/Lede via porta 80…

Bem, vamos adicionar um gráfico. Eu recomendo escolher “Preencher” como estilo de renderização.

Monitoramento e controle remoto de dispositivos baseados em Lunix/OpenWrt/Lede via porta 80…

A saída é algo muito lacônico, por exemplo assim:

Monitoramento e controle remoto de dispositivos baseados em Lunix/OpenWrt/Lede via porta 80…

À pergunta razoável: “valeu a pena?”, responderei: bem, claro, veja “motivos para criar uma bicicleta” no início do artigo.

Se minha primeira experiência grafomaníaca desperta o interesse dos leitores, nos próximos artigos quero descrever como enviar comandos para equipamentos remotos. Também conseguimos implementar todo o esquema para dispositivos baseados em RouterOS (Mikrotik).

Fonte: habr.com

Adicionar um comentário