четверг, 5 апреля 2018 г.

Запуск стороннего ПО на рутерах Mikrotik

В прошлом посте я описал один из способов получения рута на Mikrotik, путем создания симлинка на корневой каталог. Отмечу, что при использовании данного метода наблюдается один не смертельный баг - очень долго открывается меню работы с файлами через WebFig и WinBox, а так же медленно отрабатывают команды "/file print ...", "/file set ..." в скриптах (вплоть до отказа по таймауту). Вызвано это тем, что модуль /nova/bin/fileman, реализующий операции по работе с файлами, зачем-то при запуске каждой команды "/file", сканирует диски и собирает список всех находящихся на них файлов. Занимает это довольно долгое время, отсюда и "тормоза".
Но так как работа с файлами на Mikrotik и без этого весьма убога - данный баг не критичен. Лучше для работы с файлами использовать нативный BASH.

Разблокированный логин "devel" уже позволяет запускать на рутере стороннее ПО. Осталось найти способ автоматического запуска нужных нам команд при загрузке рутера, без необходимости подключения к нему по Telnet/SSH. Первой мыслью было попробовать написать скрипт, подключающийся с рутера самому к себе по SSH под "devel" и выполнять нужные команды - однако, этот вариант не работает. Kirils Solovjovs в своей jailbreak tool правит файловую систему рутера - я подобные изменения вносить не планирую, чтобы иметь минимум проблем после штатного апгрейда RouterOS. Поэтому, пришлось искать другой способ. И он нашелся.

В каталоге /nova/bin находятся модули, реализующие внутренние команды рутера. Внимание привлек файл /nova/bin/logmaker (он отвечает за сбор логов устройства для отправки в саппорт Mikrotik), в частности, цикл в его конце:

  1. #!/bin/ash
  2. SUPOUT=$1
  3. if [ "$SUPOUT" = "" ]then
  4.     SUPOUT="supout.rif"
  5. fi
  6. .....

  7. for i in $(path /nova/lib/logmaker)do
  8.     if [ -f $i ]then
  9.         SEC=${i#*.}
  10.         . $i | /nova/bin/append /var/tmp/supout.rif ${SEC%.lom}
  11.         echo -n .
  12.     fi
  13. done

  14. .....


Утилита /bin/path принимает в качестве параметра путь, и выводит на экран все файлы, лежащие по данному пути в подкаталогах /pckg/, а так же корневого. Например:
После чего, logmaker запускает все найденные файлы, и их вывод добавляется в конец временного supout.rif.

К слову, увидев данный скрипт, я сперва подумал, что он в качестве параметра принимает имя файла, переданное пользователем, и попробовал в консоли рутера выполнить:
/system sup-output name="$(/rw/disk/myscript.sh)"
однако, этот вариант не сработал.
Зато сработало создание файла /pckg/option/nova/lib/logmaker/9999.option.lom, из одной строки:

  1. /bin/bash /rw/disk/myscript.sh

И запуск в консоли рутера команды
/system sup-output name=supout.rif
Генерация supout.rif запускает в том числе и наш 9999.option.lom, который, в свою очередь, запускает myscript.sh с корня пользовательского хранилища рутера (запускать лучше явно через BASH, иначе будет использоваться ASH).

Теперь остался последний момент. Надо как-то положить файл 9999.option.lom с нашим содержимым по указанному пути. И делать так при каждой перезагрузке, так как содержимое каталога /pckg не сохраняется.
Команды "/file" работают крайне медленно, да и принудительно добавляют расширение ".txt" - очевидно, они не подходят. К счастью, есть замечательная команда "/tool fetch", а в рутере - встроен веб сервер. Поэтому, кладем наш файл 9999.option.lom в папку /flash/home/web/ рутера (ее содержимое лежит во флеше и доступно для записи), тем самым данный файл становится доступен по адресу http://192.168.1.1/9999.option.lom изнутри сети (192.168.1.1 = IP рутера).

Пробуем (предварительно надо удалить файл /pckg/option, чтобы он не мешал создать одноименную папку):
/tool fetch url="http://192.168.1.1/9999.option.lom" mode=http dst-path="/root/pckg/option/nova/lib/logmaker/9999.option.lom"
Работает, файл на месте. Заодно и путь /pckg/option, разблокирующий логин "devel" создался.

Подытожу.
Для того, чтобы рутер автоматически запускал наш код при каждой перезагрузке, требуется следующее:

1. Создать во встроенном хранилище (или на USB флешке) папку "/root", ссылающуюся на "/" (корневой каталог устройства). Как это сделать - написано в первых трех пунктах тут. Лучше создать линк непосредственно во встроенной памяти рутера, чтобы освободить USB порт. Ниже все скрипты рассчитаны на то, что линк создан именно во встроенной памяти (путь /root при доступе из скриптов/по FTP, или /rw/disk/root относительно корня устройства). Если линк создан на USB, то необходимо поменять пути на /disk1/root или /rw/disk/disk1/root.

2. Записать в папку /flash/home/web/ рутера (при доступе через FTP она будет доступна как /root/flash/home/web/, если папки нет - ее надо создать) файл 9999.option.lom с содержимым:
  1. /bin/bash /rw/disk/init.sh
В конце файла символа перевода строки нет.

3. Создать файл init.sh с нужными командами, и положить на рутер. Например, такой:
  1. #!/bin/bash
  2. echo init >/rw/disk/init.done
Если файл создается под Windows - не забываем про символы перевода строк. Иначе работать не будет.

4. Создать скрипт:
  1. /system script
  2. add name=callinit owner=admin policy=\
  3.     reboot,read,write,policy,test,password,sniff,sensitive source=\
  4.     ":delay 60\r\n\
  5. /tool fetch url=\"http://192.168.1.1/9999.option.lom\" \
  6.   mode=http dst-path=\
  7.   \"/root/pckg/option/nova/lib/logmaker/9999.option.lom\"\r\n\
  8. /system sup-output name=supout.rif"
Задержка в 60 секунд в начале дает время поправить или удалить данный скрипт, если что-то пойдет не так.
После создания, скрипт рекомендуется запустить вручную на свежеперезагруженном устройстве, и проверить - создался ли файл /pckg/option/nova/lib/logmaker/9999.option.lom
Из-за "delay 60", а так же, так как создание файла supout.rif занимает достаточно продолжительное время - надо подождать несколько минут после запуска скрипта.
Если файл не загрузился - проверяем настройки фаерволла.

5. Создать в шедулере задачу на запуск скрипта:

  1. /system scheduler 
  2. add comment="" disabled=no start-time=startup interval=0 name=onboot\ 
  3.     on-event=callinit \
  4.     policy=reboot,read,write,policy,test,password,sniff,sensitive

После этого - перезагрузить рутер для проверки.

У меня сейчас на рутере развернут пакет mini-native-mips.tar.bz2 с сайта µClibc, паект opkg от OpenWRT (лежат на флешке, так как весят довольно много). Запускаются через chroot, зато можно и что-нибудь с исходников собрать, да и готовые пакеты через opkg install подтянуть.
В планах - поднять нормальный DNS сервер (встроенный в Mikrotik не поддерживает условные форвардеры), а так же блокировать нежелательные сайты на уровне DNS по данным отсюда.


P.S. Для чего все это нужно, ведь есть Metarouter с полноценным OpenWRT? 
Судя по количеству негативных отзывов - Metarouter работает весьма нестабильно. Он сильно грузит процессор, периодически вызывает перезагрузку устройства, теряет настройки внутри VM. При запуске ПО непосредственно на "чистой" Linux устройства - подобные проблемы не наблюдались ни разу. Рекомендовать использование приведенной выше информации на промышленных системах я точно не буду, но в тестовой среде или "поиграться" дома - вполне можно. 

Комментариев нет: