20.11.2017

Мikrotik RouterOS Configuration Management с помощью скриптов и какой-то там матери

Жизненный цикл сети часто переживает закономерный рост. В это время начинают появляться десятки и сотни устройств, конфигурация которых однотипна. Например, это могут быть маршрутизаторы в филиалах, которые имеют одинаковые настройки и отличаются только IP адресами, паролями на VPN и Wi-Fi. Внесение даже незначительных изменений на десяток устройств потребует значительного времени и концентрации.

Для управления сотнями и тысячами устройств весь цивилизованный мир уже давно использует специальные системы менеджмента конфигураций: Ansible, Chef, Puppet. Каждая из них имеет свои плюсы и минусы.


Но для десяти-двадцати устройств не каждый захочет выделять отдельный сервер с такой системой. Поэтому в ход идут скрипты, SSH, FTP и куча матов, когда всё это поделие роняет сразу все филиалы.

Видео для привлечения внимания
Это визуализация запросов от роутеров к системе, о которой идет речь в этом посте.



Я тоже накостылил подобную систему в соответствии со своими потребностями и расскажу о ней.

Мои требования к системе централизованного управления:
  • Надежность.  Система должна работать независимо от скорости соединения или после месячного оффлайна
  • Приемлемая скорость актуализации конфигурации. Если девайс месяц не включался, то свежий конфиг он должен применить за обозримое время
  • Низкая нагрузка на каналы связи и ресурсы сервера. Обновление конфигурации не должно положить интернет в ЦОДе и процессор машины
  • Масштабируемость. Систему можно увеличить в 5-10 раз
  • Разделение устройств по группам. Применение разных настроек к разным группам
  • Обратная связь о применении конфигурации 
  • Постараться не использовать Flash память микротика по причине её износа


Из требований родились идеи к реализации:
  • Чтобы обеспечить применение всех изменений, роутер должен сам обращаться за конфигурацией
  • Актуализация обеспечивается за счет опроса сервера раз в час
  • Чтобы не нагружать ресурсы и каналы, роутеры должны обращаться за обновлениями в разное время
  • Для оповещений использовать Telegram
  • Следование принципу KISS

Для работы системы понадобится только web сервер. В моем случае apache. Как его установить и настроить я рассказывать не буду, к тому же необязательно это должен быть апач.

Логика такая: на веб сервере лежат RouterOS скрипты, с определенным именованием. Имя скрипта указывает на его версию и группу устройств, для которой должна примениться конфигурация. Маршрутизаторы с периодичностью раз в час обращаются к серверу за новым конфигом. Если новый конфиг есть, то он скачивается на роутер и выполняется. Если конфига нет - ничего не скачивается, что позволяет не дергать лишний раз быстроубиваемую память.


Чтобы начать применять подобную систему, надо привести конфиги всех роутеров к одному стандарту. К примеру, не так давно в RouterOS появилась новая фича: Interface List. Теперь можно одним правилом в фаерволе заменить несколько правил, если их надо применить к разным интерфейсам. Наш скрипт должен добавить в интерфейс-лист интерфейс, который "смотрит" к провайдеру. На одном роутере это может быть eth1, на другом PPPoE, на третьем - вообще wlan1.

Как в таком случае поступить? Надо как-то выделить внешние интерфейсы. Например, добавить к ним комментарий "WAN".
Также стОит привести к одному виду фаервол, Queues - вообще всё, что есть на роутерах. И создать отдельную учетную запись,  с правами которой будут выполняться скрипты. Как создать скрипт для быстрой настройки роутеров я расскажу в следующем посте.


Принцип именования скриптов: A000, где А - группа устройств, а номер - версия скрипта.

Каждому роутеру в планировщик добавляем такие строки:

/system scheduler
/tool fetch url="http://rbconf.bubnovd.net/A001" user=mikrotik-ninja password=mikrotik-ninja.ru

/import A001


Это задание скачивает с сервера скрипт и выполняет его. Для обеспечения хоть какой-то безопасности, доступ к серверу только по паролю, который указан в задании.


Сами скрипты лежат на сервере и выглядят примерно так:

/log info message=".....................Autoconfiguration started....................."
#Версия внедряемой конфигурации
#Описание задачи, которую выполняет скрипт: Удаление пользователя

#Первая часть скрипта нужна для только для определения  версии конфига, который нужно применить следующим
:local ver
:set $ver A001
#Версия следующей конфигурации
:local verNext
#Версия предыдущей конфигурации
:local verPrev
:set $verNext ("A" . [tostr ([tonum [pick $ver 1 4]] + 1)])
:set $verPrev ("A" . [tostr ([tonum [pick $ver 1 4]] - 1)])
#Добавляем нули, если надо
        if ([:len $verNext] =2) do={
                :set $verNext ([pick $verNext 0 1] . "00" . [pick $verNext ([len $verNext] -1) ([len $verNext])])} else={
                if ([:len $verNext] =3) do={
                        :set $verNext ([pick $verNext 0 1] . "0" . [pick $verNext ([len $verNext] -2) ([len $verNext])])} else={}}

        if ([:len $verPrev] =2) do={
                :set $verPrev ([pick $verPrev 0 1] . "00" . [pick $verPrev ([len $verPrev] -1) ([len $verPrev])])} else={
                if ([:len $verPrev] =3) do={
                        :set $verPrev ([pick $verPrev 0 1] . "0" . [pick $verPrev ([len $verPrev] -2) ([len $verPrev])])} else={}}

# Вторая часть скрипта - наша рабочая конфигурация
#####
#####Тут код конфигурации
#####
if ([len [/user find name="prosvirnin"]]>0) do={/user remove [find name="
prosvirnin"]} else={/log info message="User not exist"}
#####
#/log info message="Creating script $ver"
#/system script add name=$ver source="/log info message=done"
#/log info message="Script $ver created. Starting"
#/system script run $ver
#/log info message="Removing script $ver"
#/system script remove $ver
##### Или в скрипте выше

# Третья часть - настройка планировщика для следующего изменения, оповещение и чистка файлов
/system scheduler set autoconf on-event="/tool fetch url=\"http://rbconf.bubnovd.net/$verNext\" user=mikrotik-ninja password=mikrotik-ninja.ru\r\n
/import $verNext"
/log info message="...................Autoconfiguration complete..................."
/delay 3
#Удаляем остатки предыдущих скриптов, если не удалились
if ([:len [/file find name~"sendMessage"]] >0) do={/file remove [/file find name~"sendMessage"]} else={/log info message="No item for delete"}
if ([:len [/file find name="$verPrev"]] >0) do={/file remove [/file find name="$verPrev"]} else={/log info message="No item for delete"}
/delay 3
#Отправляем уведомление о выполнении
:local name [/system identity get name]
/tool fetch keep-result=no url="https://api.telegram.org/bot-nomer-bota:tut-vasha-ssylka/sendMessage\?chat_id=-12345678&text=$ver is complete on $name"
/delay 3
if ([:len [/file find name~"sendMessage"]] >0) do={/file remove [/file find name~"sendMessage"]} else={/log info message="No item for delete"}
/delay 3
/file remove $ver



Сначала описывается версия конфига и каким будет следующая версия. Затем после комментария "#####Тут код конфигурации" перечисляются команды, которые должен выполнить роутер. Иногда роутер должен выполнить сложный скрипт. На этот случай есть закомментированный блок кода со скриптом. Сам сложный скрипт нужно описать в поле source="tut_sam_script"

После выполнения команд меняется задание в планировщике - указываем следующую версию скрипта, который надо применить. С этого момента роутер будет пытаться скачать его с сервера. Дальше шлём уведомление и удаляем файлы, которые могли создастся в ходе выполнения задания. Как слать оповещения в Telegram описано на бескрайних просторах интернета и повторяться я не буду.


Очень важно предусмотреть в скрипте всё возможное и невозможное и каждая команда должна начинаться с проверки if (...) do={ , а заканчиваться } else={/log info message="User not exist"} . У одного из моих роутеров был баг, из-за которого не отображался wireless интерфейс. И без проверки его существования, скрипт просто вываливался с ошибкой. А значит, не менялась запись в планировщике и следующий скрипт тоже не выполнялся.

Перед применением конфигурации на всю сеть нужно проверить правильность написания скрипта - даже опытный скриптописатель может чего-то не учесть и хорошо, если это какая-то мелочь и она не положит всю сеть. Поэтому перед созданием нового файла конфигурации, я проверяю  команды на работающем в продакшене роутере. А затем использую отдельную группу из 20 разнотипных роутеров (в основном это разный тип подключения к сети, остальные настройки везде идентичны) для тестирования скрипта. Эти роутеры опрашивают сервер чаще, чем остальные и после применения настроек я какое-то время наблюдаю за их поведением, а затем распространяю нововведения на остальную сеть.



Чего не хватает в моём подходе:
  • Безопасность. Хоть доступ на сервер со скриптами ограничен паролем, но этот пароль в открытом виде хранится на роутерах. Вся конфигурация передается по сети в открытом виде. У меня всё это летает внутри шифрованного VPN и я запрещаю вам использовать это на нешифрованных публичных каналах! Внутреннего нарушителя тоже никто не отменял и внутри VPN это не очень безопасно. Можно Нужно! использовать https вместо http.
  • Информативные оповещения. При возникновении ошибки, неплохо было бы сообщать о ней
  • Возможны только изменения. Хочется ещё и читать конфиги и выделять места, отличные от стандарта. Но это задача уже другого класса систем


Через полгода после внедрения этой системы, на встрече пользователей Mikrotik Михаил Москалев   рассказал об аналогичном подходе. Михаил продвинулся дальше и применил модульный подход к конфигурации. Его презентацию можно посмотреть по ссылке.
Такой же подход использует система блокировки рекламы для Mikrotik https://stopad.cgood.ru/
Постоянный докладчик нашей #Sysadminka написал свою систему управления конфигурациями. Она доступна на github. Посмотреть можно на YouTube.


В следующем посте я опишу ещё один свой скриптик с использованием Excel, который помогает младшим админам настраивать первичную конфигурацию роутеров без вникания в WinBox и настройки RouterOS.


P.S.: Видео в посте создано с помощью grep и logstalgia.

2 комментария: