Здравейте на всички, това е моят първи опит в Хабра. Искам да напиша как нестандартно да управлявате мрежово оборудване във външната мрежа. Какво означава нестандартно: в повечето случаи, за управление на оборудването във външната мрежа, ще ви е необходимо:
- Публичен IP адрес. Или, ако оборудването е зад нечий NAT, то публичен IP и „пробит“ порт.
- Тунел (PPTP/OpenVPN/L2TP+IPSec и т.н.) до централния възел, през който да бъде достъпен.
Следователно, „моят велосипед“ ще е нужен, когато стандартните методи не са подходящи, например:
- Оборудването е зад NAT и освен обикновения http (80-ти порт) — всичко е затворено. Напълно нормална ситуация за големи федерални корпоративни мрежи. Могат да отворят портовете — но не веднага, не бързо и не за вас.
- Нестабилен и/или „тесен“ канал за връзка. Ниска скорост, постоянни загуби. Болка и разочарование при опити за организиране на тунел.
- Скъп канал за връзка, където буквално всеки мегабайт е на цена. Например сателитна връзка. Плюс големи закъснения и „тясна“ лента.
- Ситуация, при която трябва да „жонглирате“ с голямо количество малки рутери, на които от една страна е инсталиран OpenWrt/Lede за разширяване на възможностите, а от друга страна ресурсите (паметта) на рутера не достигат за всичко.
Забележка номер едно Какво пречи да поставите „флашка“ в USB порта на рутера и да разширите паметта на рутера?
Често изискванията за цената на решението като цяло, но понякога ключова роля играе и формата. Например на обекта стои TP-Link ML3020, единственият му USB порт се използва за 2G/3G модем, всичко това е опаковано в някакъв малък пластмасов корпус и е поставено някъде много високо (на мачта), далеч-далеч (в полето, на 30 км от най-близката базова станция на мобилния оператор). Да, можете да поставите USB-хъб и да разширите броя на портовете, но опитът показва, че това е обемисто и ненадеждно.
И така, опитах се да ви опиша моята типична ситуация: „някъде далеко-далеч, стои много важен, самотен и малък рутер, управляван от Linux. Важно е да знам поне веднъж на ден, че той е „жив“ и при необходимост да му изпратя команди, например „слънчице, рестартирай се!“
Преминаваме към реализацията:
1) От страната на рутера по cron-а на всеки 5/10/1440 минути, или когато е нужно, е необходимо да се изпраща http-запит до сървъра с помощта на wget, резултатът от записа да се запазва в файл, файлът да бъде изпълним и да се изпълнява.
Стрингът ми в cron-а изглежда приблизително така:
Файл /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 , където:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai — домейнът на моя сървър. Веднага ще кажа: да, може да укажете и конкретен ip-адрес на сървъра, така направихме преди, докато нашето правителство, в праведния си порив да се бори с нещо, което не знам — не закри достъпа до преобладаващата част от „облаците“ DigitalOcean и Amazon. В случай на използване на символен домейн, при възникването на подобен казаус, спокойно можете да стартирате резервно облако, да пренасочите домейна към него и да възстановите мониторинга на устройствата.
a.php — името на скрипта на сървъра. Да, знам, че това не е правилно, да наричаш променливи и имена на файлове с една буква… предлагам да смятаме, че така спестяваме няколко байта при изпращането на запитването 🙂
u — името на потребителя, логин на устройството
p — паролата
„-O /tmp/wa.sh“ — файл на отдалечения рутер, където ще се запазва отговорът на сървъра, например командата reboot.
Забележка номер две: Аааа, защо използваме wget, а не curl, нали през curl може да се изпращат https запитвания и не само GET, а и POST? Аааа, защото, както в стария виц „В кринка не лази!“. В състава на curl влизат библиотеките за криптиране с размер около 2MB и поради това трудно ще успеете да съберете образ за малкия TP-LINK ML3020 например. А с wget — моля.
2) На страната на сървера (при мен е Ubuntu) ще използваме Zabbix. Защо: искам да е красиво (с графики) и удобно (да изпращам команди през контекстното меню). Zabbix има такава приятно нещо, като zabbix-агент. Чрез агента ще извикаме php-скрипт на сървър, който ще връща информация за това, регистриран ли е нашият рутер в необходимия период от време. За съхранение на информацията за времето на регистрация и командите за устройствата, използвам MySQL, отделна таблица users с приблизително следните полета:
СЪЗДАЙ ТАБЛИЦА `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,
`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; Всички изходни файлове могат да бъдат изтеглени от Git репозиторий на адрес:
Сега PHP скриптове, разположени на сървъра (за удобство, може да се поставят в папка /usr/share/zabbix/):
Файл a.php:
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();
}
// Сега трябва да запазим времето на регистрация на потребителя, неговия IP и съобщение от него. В момента само съобщението
$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();
?>Файл agent.php (това е скрипт на извиквания zabbix-агент):
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();
?> И последният етап: конфигуриране на агента и добавяне на графици.
Ако все още нямате инсталиран zabbix-агент, то:
apt-get install zabbix-agentРедактирайте файла /etc/zabbix/zabbix_agentd.conf.
Добавете ред:
UserParameter=test,php /usr/share/zabbix/agent.php user password , където:
test — името на нашия агент
„php /usr/share/zabbix/agent.php user password“ — извикваният скрипт с указание на удостоверителните данни на устройството.
Добавяне на графици: отворете уеб интерфейса на zabbix, в менюто изберете:
Настройка -> Узли на мрежата -> Създайте узел на мрежата. Тук е достатъчно да посочите името на узела на мрежата, неговата група, интерфейса на агента по подразбиране:

Сега за този узел на мрежата трябва да добавим елемент от данни. Обърнете внимание на двете полета: „ключ“ — това е параметърът, който написахме във файла /etc/zabbix/zabbix_agentd.conf (в нашия случай това е test), и „интервал на обновление“ — аз задавам 5 минути, тъй като и оборудването се регистрира на сървера веднъж на пет минути.

Сега добавяме график. Препоръчвам да изберете стил на рисуване „Запълване“.

Накрая получавате нещо много лаконично, например така:

На основателния въпрос: „и това ли си струва?“, отговарям: разбира се, вижте „причини за създаването на велосипеда“ в началото на статията.
Ако моят първи графомански опит предизвика интерес у читателите, в следващите статии искам да опиша как да изпращате команди на отдалечено оборудване. Успях да реализирам цялата схема и за устройства на базата на RouterOS (Mikrotik).
Източник: habr.com
