Това е финалната част на статията, ето началото
В последния път писах как прилагам мониторинг на устройства, сега ще стане дума за управление. В дискусиите с 'техниците' от страна на Клиента често срещам ограничено възприятие на възможностите на такива малки устройства (с ниски ресурси на памет и производителност), много хора смятат, че 'максимумът, от който ще имаме нужда, е да изпратим reboot, за нещо по-сериозно — ще изпратим екип'.
Но практиката показва, че това не е съвсем така. Ето малък списък с чести типични задачи:
- Мрежова диагностика и отстраняване. Зад ethernet-порта на вашия рутер обикновено 'живее' друго устройство, което има свой собствен вътрешен ip-адрес. Понякога, то може (и трябва) да бъде 'пингнато'. Или управление на тунела — ако на рутера, работещ през 3G-модем, внезапно не се вдига тунел, но самият рутер го виждаме.
- Системно обслужване. Актуализация на фърмуера, ъпгрейд на служебните скриптове.
- Еквилибристика. Това можеше да се нарече 'извращения', но понятието 'еквилибристика' като, цитирам, 'способността на цирков артист да поддържа равновесие при нестабилно положение на тялото' — подхожда повече. Подобни ситуации възникват поради ограничения бюджет на клиента. По-долу представям няколко примера, но тъй като нямат пряко отношение към темата на разказа, ги изнесох в бележки.
Wi-Fi мониторингПоследните пет години актуална тема, основно сред федералните мрежи на търговията. Вие бавно се разхождате из магазините, а Вашият мобилен телефон с включен Wi-Fi редовно изпраща пакети Probe Request в опити да се свърже с някоя мрежа, които могат да се анализират, за да се определи: колко често посещавате този магазин, по какви маршрути се движите и т.н. След това данните се събират, анализират, създават се топлинни карти и мениджърите за такива графики "изстискват" пари от ръководството или инвеститорите. А междувременно... "парите ги няма, но вие се стараете...", а резултатът (реален) вече трябва да бъде показан, включва се старата добра песен "Да-да, после определено ще изнесем всичко необходимо, но сега трябва да покажем на Клиента резултата! Между другото, забравихме да споменем, че Клиентът разреши нашето оборудване да се свърже с неговия хотспот чрез Wi-Fi, но на общи начала, просто като че сме гости." И така се налага да правим роутери-еквилибристи — създават се няколко WiFi подинтерфейса, един от които се свързва с хотспота, а другият следи околната среда, втурвайки се да експортира резултата от tcpdump в себе си, след това съдържанието на файла се пакетира в архив и рискувайки да "преяжда" се опитва да изпрати съдържанието на FTP сървър. Не е изненадващо, че роутер-еквилиристите често "изпадат" и по някакъв начин трябва да бъдат възстановявани дистанционно.
RadiusТук е по-лесно да се опише ситуацията с следното твърдение от клиента: "Искаме децентрализирана мрежа от хотспотове, които да работят на оборудване, моделът на което не е известен предварително, през канали, за които все още не знаем. О, забравихме да споменем, не само искаме да показваме реклама на клиентите, но и да анализираме всичко около мястото на инсталиране на хотспота. Не, все още не знаем защо, но ще измислим, не се притеснявайте, успяхме да измислим тази идея."
И не бива да се забравя, че поради множество предопределени обстоятелства управлението трябва да се осъществява в нестандартни условия, когато не можем да се свържем с роутера директно през ip: порт и сме принудени просто да чакаме появата на активност от него. Ако се абстрахираме, диалогът между сървъра и роутера може да се представи по следния начин:
- Роутер: привет. аз съм роутер такъв, имам ли задачи?
- Сървър: рутер такъв, аз те регистрирах, че си жив. Ето задачата: покажи ми резултата от командата ifconfig?
- Роутер: здравей. аз съм рутер такъв, миналия път поиска да покажа резултата от ifconfig, ето го. Има ли задачи за мен?
- Сървър: рутер такъв, аз те регистрирах, че си жив. Нямам задачи за теб.
Най-интересният въпрос: как по-точно отдалеченият рутер може да изпрати определен обем информация? В предишната част описах, че на рутера заради ограничените ресурси има само 'осакатен' wget, който работи само чрез GET и нищо повече, няма нито FTP клиент, нито curl. По-точно, ни е нужен универсален начин, независимо от особеностите на сборката на образа. Застанах на решение с wget. По-точно, както 'застанах' — просто нямах избор 🙂
Веднага уточнявамМоето решение за управление е работещо, не е много ограничено и съм сигурен — неправилно, дори ако удовлетворява повечето от моите клиенти. Как БИ могло да се направи по-разумно — да се напише малка утилита, която изпраща бинарни данни чрез POST на 80-ти порт. Да я включим (утилитата) в състава на фърмуера на рутера и чрез bash да се обръщаме към нея. Но реалността е такава, че: а) трябва бързо б) може би всичко да е на съществуващия 'зоопарк от рутери' в) 'не вреди!' — ако рутерът работи и изпълнява други задачи, опитайте се да правите промени, които да не засегнат съществуващата функционалност.
Да преминем към реализацията. Да предположим, че вашият клиент иска от zabbix да рестартира рутера лесно и удобно, 'с клик на мишката'. Днес ще започнем описание на реализацията с zabbix.
В менюто 'Администриране' -> 'Скриптове' добавяме нов скрипт. Наравяме го 'Reboot', като команда пишем 'php /usr/share/zabbix/reboot.php {HOST.HOST}'

След това: Меню 'Мониторинг' -> 'Последни данни' -> 'Щракнете с десния бутон на нужния възел в мрежата'. Така ще изглежда менюто след добавянето на скрипта.

Съответно, скриптът reboot.php поставяме в директория /usr/share/zabbix (при вас може да е друга, аз използвам основната директория на zabbix).
Уточнение за безопасностЗа наглядност в обяснението на скрипта използвам само id на рутера, но не ползвам паролата. В работната версия така не е препоръчително! Защо го направих така: защото е важен въпрос — къде да се съхраняват паролите за рутерите? В самия Zabbix в «инвентарните данни»? Противоречива практика. Като вариант: да ограничим достъпа до самия файл reboot.php.
Файл reboot.php
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 " — нашият скрипт a.php, който регистрира рутерите и приема съобщения от тях.
u=user&p=password!&m=$message — идентификационни данни, а на параметъра m — присвоява стойността на променливата $message.
-O /tmp/out.txt — изходът в файл /tmp/out.txt в този случай не ни е нужен, но ако не посочим този параметър, wget не сработва.
Защо това не работи добре?Защото е потенциална дупка в сигурността. Най-невинната грешка, която може да се случи — е ако в изхода на вашата команда, например, има символ „&“. Затова е необходимо да се филтрира всичко, което се изпраща от рутерите и всичко, което идва на сървъра. Дааа, срам ме е, наистина. В своето оправдание мога само да напиша — че цялата статия е посветена на това как да управляваме рутери с неопределима предварително фърмуер, с неопределими предварително канали за свързване.
И задел за framtid: все още не съм разбрал как стандартно да отразявам резултатите (например, резултата от изпълнението на команди), които идват на сървера в zabbix.
Напомням, че всички изходни кодове могат да се вземат от Git хранилището на адрес:
Източник: habr.com
