Это заключительная часть статьи, вот начало.

В прошлый раз я написал о том, как реализовал мониторинг устройств, теперь речь пойдет о управлении. В дискуссиях с «технарями» со стороны Заказчика я часто встречаюсь с ограниченным восприятием возможностей таких маленьких устройств (с невысокими ресурсами памяти и производительностью), многие считают что «максимум что нам потребуется это отправить reboot, для чего-то более серьезного — отправим бригаду».

Но практика показывает, что это не совсем так.

Вот небольшой перечень частых типичных задач:

  1. Сетевая диагностика и устранение. За ethernet-портом Вашего роутера обычно «живет» другая железка, у которой свой внутренний ip-адрес. Иногда, ее можно(нужно) «попингать». Или управление туннелем — если на роутере, работающем через 3G-модем вдруг не поднимается туннель, но сам роутер мы видим.
  2. Системное обслуживание. Обновление прошивки, апгрейд служебных скриптов.
  3. Эквилибристика. Это можно было бы назвать «извращениями», но понятие «эквилибристка» как, цитирую, «способность циркового артиста удерживать равновесие при неустойчивом положении тела» — подходит больше. Подобные ситуации возникают по причине ограниченности бюджета заказчика. Ниже привел пару примеров, но т.к. прямого отношения к теме повествования они не имеют, вынес их в примечания

Wi-Fi мониторинг
Модная последние пять лет тема в основном среди федеральных сетей ритейла. Вы неспешно прогуливаетесь по торговым залам, а Ваш мобильник с включенным Wi-Fi в попытках «присосаться» к какой-нить сети регулярно рассылает пакеты Probe Request, которые можно анализировать, с целью Вас посчитать: как часто Вы приходите в этот магазин, по каким траекториям гуляете и так далее. Дальше данные собираются, анализируются, рисуются тепловые карты и менеджеры за такие картинки «выбивают» деньги у руководства или инвесторов. Ну а пока....«денег нет, но вы держитесь...», а результат(реальный) уже надо показать, включается старая добрая песня «Да-да, потом мы конечно поставим циски и все что пожелаете, но сейчас надо показать Заказчику результат! Кстати забыли сказать, Заказчик разрешил наше оборудование подключать к своему хотспоту через вайфай, но на общих началах, просто как будто мы гостевые клиенты». И вот приходится делать роутеров-эквилибристов — поднимается несколько WiFi сабинтерфейсов, одним из которых он цепляется за хотспот, а вторым мониторит окружающую среду, судорожно выгружает результат tcpdump-а в себя же, далее содержимое файла пакует в архив и рискуя помереть от «переедания» пытается выплюнуть содержимое на фтп-сервер. Неудивительно, что роутер-эквилибрист часто «срывается» и его как-то приходится удаленно «реанимировать».

Radius
Здесь описать ситуацию проще примерно таким утверждением заказчика: «Мы хотим децентрализованную сеть хотспотов, которые бы работали на оборудовании модель которого заранее не известна, через каналы, но какие мы еще не знаем. Ах, забыли сказать, мы не только хотим показывать рекламу клиентам, но и анализировать все вокруг места установки хотспота. Нет, мы пока не знаем зачем, но придумаем, не сомневайтесь, мы же смогли придумать эту идею»

И надо не забывать, что в силу массу неопределенных заранее обстоятельств, управление должно осуществлять в нестандартных условиях, когда мы не можем подключится к роутеру напрямую через ip: порт и вынуждены просто ждать проявления активности от него. Если абстрагироваться, то диалог между сервером и роутером можно представить вот так:

  • Роутер: привет. я роутер такой-то, есть ли для меня задачи ?
  • Сервер: роутер такой-то я тебя зарегистрировал, что ты живой. Вот задача: покажи мне результат команды ifconfig ?
  • Роутер: привет. я роутер такой-то, в прошлый раз ты просил показать результат ifconfig, вот он. Есть ли для меня задачи ?
  • Сервер: роутер такой-то я тебя зарегистрировал, что ты живой. Задач для тебя нет.

Самый интересный вопрос: а каким образом удаленный роутер может прислать определенный объем информации? В прошлой части я описывал, что на роутере из-за ограниченности ресурсов стоит только «урезанный» wget, который работает только через GET и ничего больше, нет ни фтп-клиента, ни curl. Точнее, нам нужен универсальный способ, независимо от особенностей сборки образа. Я остановился на использовании wget. Точнее, ну как «остановился» — у меня просто не было выбора :)

Сразу оговорка
Мое решение по управлению рабочее, но сильно ограниченное и я уверен — кривое, даже если оно устраивает большинство моих заказчиков. Как БЫ можно было сделать по уму — написать небольшую утилиту, которая через 80-ый порт шлет POST-ом бинарные данные. Включить ее(утилиту) в состав прошивки роутера и уже с помощью bash-а обращаться к ней. Но реальность такова, что: а) надо быстро б) возможно надо делать все на существующем «зоопарке роутеров» в) «не навреди!» — если роутер работает и выполняет другие задачи, старайся вносить изменения, которые на затронут существующий функционал.

Перейдем к реализации. Допустим ваш заказчик хочет из zabbix, перезагружать роутер легко и непринужденно, «щелчком мыши». Сегодня мы начнем описание реализации с заббикса.

В меню «Администрирование» -> «Скрипты» добавляем новый скрипт. Называем его «Reboot», в качестве команды прописываем «php /usr/share/zabbix/reboot.php {HOST.HOST}»



Далее: Меню «Мониторинг» -> «Последние данные» -> «Щелчок правой кнопкой мыши на нужно узле сети». Вот так вот будет выглядеть меню после добавления скрипта.


Соответственно, скрипт reboot.php кладем в директорию /usr/share/zabbix (у Вас она может быть другая, я использую корневую директорию zabbixa).

Оговорка для безопасности
Для наглядности объяснения в скрипте я использую только id роутера, но не пользуюсь паролем. В рабочей версии так делать не рекомендуется! Почему так сделал я: потому что большой вопрос — где хранить пароли к роутерам? В самом zabbixe в «инвентарных данных»? Противоречивая практика. Как вариант: ограничить доступ извне к самому файлу reboot.php

Файл reboot.php

<?php
	// присваиваем параметры с консоли переменным
	$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");
			
	// "Отправляем" команду reboot за счет изменения поля task таблицы users. В поле task можно отправлять любую команду.
	$sql_users=$conn->prepare("UPDATE users SET task='reboot' WHERE id=? AND status='active';");
	$sql_users->bind_param('s', $user);
	$sql_users->execute();
	$sql_users->close();
?>

Собственно все. Открытым остается вопрос «как получать результат выполнения команды со стороны устройства». Рассмотрим задачу на примере с командой ifconfig. Вот такую команду можно отправить устройству:

message=`ifconfig`; wget "http://xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai/a.php?u=user&p=password!&m=$message" -O /tmp/out.txt

, где:
message=`ifconfig` — мы переменной $message присваем результат вывода команды ifconfig
wget «xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai/a.php — наш скрипт a.php, регистрирующий роутеры и принимающий сообщения от них
u=user&p=password!&m=$message — учетные данные и значению переменной запроса m — присваивает содержимое переменной $message
-O /tmp/out.txt — вывод в файл /tmp/out.txt нам в данном случае не нужен, но если не указывать данный параметр, wget не срабатывает

Почему это криво работает
Потому что это потенциальная дыра в безопасности. самая безобидная ошибка, которая может случится — это если в выводе вашей команды к примеру будет символ „&“. Поэтому надо фильтровать и все что отправляется с роутеров и все что приходит на сервер. Дааа, мне стыдно, правда. В свое оправдание могу лишь написать — что вся статья посвящена тому, как управлять роутерами с неопределенной заранее прошивкой, с неопределенными заранее каналами связи.

Ну и задел на будущее: пока не разобрался, как стандартными средствами zabbix-а отражать результаты(например результат выполнения команды), которые приходят на сервер.

Напоминаю, что все исходники можно забрать с Git-репозитория

Комментарии (0)