Віддалений моніторинг та керування пристроїв на базі Linux/OpenWrt/Lede через 80-й порт, продовження

Це заключна частина статті, ось початок habr.com/ua/post/445568
Минулого разу я написав про те, як реалізував моніторинг пристроїв, тепер йтиметься про управління. У дискусіях з «технарями» з боку Замовника я часто зустрічаюся з обмеженим сприйняттям можливостей таких маленьких пристроїв (з невисокими ресурсами пам'яті та продуктивністю), багато хто вважає що «максимум що нам потрібно це відправити reboot, для чогось серйознішого — відправимо бригаду» .
Але практика показує, що це зовсім так. Ось невеликий перелік частих типових завдань:

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

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

радіусТут описати ситуацію простіше приблизно таким твердженням замовника: «Ми хочемо децентралізовану мережу хотспотів, які б працювали на обладнанні, модель якого заздалегідь не відома, через канали, але які ми ще не знаємо. Ах, забули сказати, ми не тільки хочемо показувати рекламу клієнтам, а й аналізувати все навколо місця встановлення хотспоту. Ні, ми поки що не знаємо навіщо, але придумаємо, не сумнівайтеся, ми ж змогли вигадати цю ідею»

І слід пам'ятати, що з масу невизначених заздалегідь обставин, управління має здійснювати у нестандартних умовах, коли ми можемо підключиться до роутеру безпосередньо через ip: порт і змушені просто чекати прояви активності від цього. Якщо абстрагуватися, то діалог між сервером та роутером можна уявити ось так:

  • Роутер: Привіт. я роутер такий-то, чи є для мене завдання?
  • Сервер: роутер такий-то я тебе зареєстрував, що ти живий Ось завдання: покажи мені результат команди ifconfig?
  • Роутер: Привіт. я роутер такий-то, минулого разу ти просив показати результат ifconfig, ось він. Чи є для мене завдання?
  • Сервер: роутер такий-то я тебе зареєстрував, що ти живий Завдань тобі немає.

Найцікавіше питання: а яким чином віддалений роутер може надіслати певний обсяг інформації? У минулій частині я описував, що на роутері через обмеженість ресурсів стоїть лише «урізаний» wget, який працює тільки через GET і нічого більше немає ні фтп-клієнта, ні curl. Точніше, нам потрібний універсальний спосіб, незалежно від особливостей збирання образу. Я зупинився на використанні wget. Точніше, ну як «зупинився» — я просто не мав вибору 🙂

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

Перейдемо до реалізації. Допустимо ваш замовник хоче з zabbix, перезавантажувати роутер легко і невимушено, «клацанням миші». Сьогодні ми почнемо опис реалізації з заббіксу.
У меню "Адміністрування" -> "Скрипти" додаємо новий скрипт. Називаємо його «Reboot», як команду прописуємо «php /usr/share/zabbix/reboot.php {HOST.HOST}»

Віддалений моніторинг та керування пристроїв на базі Linux/OpenWrt/Lede через 80-й порт, продовження

Далі: Меню "Моніторинг" -> "Останні дані" -> "Клацання правою кнопкою миші на потрібно вузлі мережі". Ось так буде виглядати меню після додавання скрипта.

Віддалений моніторинг та керування пристроїв на базі Linux/OpenWrt/Lede через 80-й порт, продовження
Відповідно, скрипт 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-репозиторію за адресою: github.com/BazDen/iotnet.online.git

Джерело: habr.com

Додати коментар або відгук