Архив

MikroTik автоматическое обновление листов

В прошлой статье мы разобрали как настроить маршрутизацию трафика через VPN, на основе Address Lists. В этой статье хочется собрать информацию и способы для автоматического обновления и создания листов. 

Обновление листов представляет из себя выполнение shell команд, которые исполняются на Router OS. Их можно предварительно сгенерировать и выполнить на маршрутизаторе, либо выполнять сразу, в runtime, без создания отдельного файла.

Шаблон файла обновления

/ip firewall address-list
remove numbers=[find list=spotify]
add list=spotify address=104.154.127.47
add list=spotify address=78.31.8.0/21

В моем случае обновление листа подразумевает удаление всех правил и добавление новых. Необходимости делать точечные изменения у меня не возникало.

В листе выше, мы удаляем все адреса которые присутствуют в листе spotify - remove numbers=[find list=spotify].  Затем идут команды добавления новых адресов add list=spotify address=78.31.8.0/21 их можно добавлять сколь угодно много, но большие обработка больших листов будет отнимать ресурсы роутера, поэтому заливать туда полный список от РКН не рекомендую.

Обновление из сгенерированного файла

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

Для добавления через консоль:

/system script
add dont-require-permissions=no name=sp_import owner=owner policy=\
    read,write,test source="%тут листинг скрипта%"

Мы добавили скрипт, с минимальными правами read,write,test, но набор этих прав позволит читать и записывать настройки на роутере, кроме тех которые отвечают за пользователей, поэтому нужно быть уверенным кто контролирует скрипт который будет исполнен на роутере. Подробнее о правах доступа

Сам скрипт:

/tool fetch url="https://127.0.0.1/mikrotik_spotify_list.txt" dst-path=spotify.txt
:import spotify.txt

В нем мы получаем с удаленного сервера сформированный листинг (см. Шаблон файла обновления), сохраняем его в файл spotify.txt и выполняем этот файл.

Почти готово, осталось автоматизировать.

/system scheduler
add interval=2h name=update_spotify_list on-event="/system script run sp_import" \
policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
start-date=jan/01/2019 start-time=09:00:00

Мы добавили в планировщик задание name=update_spotify_list на выполнение каждые два часа interval=2h. С policy тут несколько сложнее, если из планировщика выполняется другой скрипт, то нужно предоставить все права. Теоретически можно было весь листинг скрипта положить в планировщик и ограничить права, но я предпочитаю когда скрипты лежат в отдельных файлах.

Итак. Мы создали скрипт, который обновляет список адресов в файрволе. Создали скрипт который скачивает этот список и добавили его в планировщик. 

Обновление листа без промежуточных файлов

В вышеописанном решение все хорошо, за исключением того, что требуется где-то хостить наш список и формировать его. Как сделать тоже самое на роутере?

:local ListName "spotify"
:local ListIps {"104.154.127.47";"78.31.8.0/21"}

/ip firewall address-list remove numbers=[find list=$ListName]

:foreach v in $ListIps do={
  /ip firewall address-list add address=$v list=$ListName
}

Делает все тоже самое. Документация по MikroTik Scripting.

Обновление листа через определение ip доменов

Пока искал ссылку на документацию по MikroTik Scripting, наткнулся на статью Писать скрипты для Mikrotik RouterOS — это просто

В ней приведен листинг скрипта, который может делать определение ip адресов доменов и формировать список из них. Весьма удобно, так как иногда бывает что сайты часто меняют свои адреса в попытках борьбы с блокировками.

Для истории приведу листинг скрипта ниже, а его полный разбор с комментариями доступен в оригинальной статье.

:local DNSList {"example.com";"non-exist.domain.net";"server.local";"hostname"}
:local ListName "MyList"
:local DNSServers ( [ip dns get dynamic-servers], [ip dns get servers ], 8.8.8.8 )
:foreach addr in $DNSList do={
     :foreach DNSServer in $DNSServers do={
          :do {:resolve server=$DNSServer $addr} on-error={:log debug ("failed to resolve $addr on $DNSServer")}
     }
}
/ip firewall address-list remove [find where list~$ListName]
/ip dns cache all
:foreach i in=[find type="A"] do={
    :local bNew true
    :local cacheName [get $i name]
    :local match false
    :foreach addr in=$DNSList do={
       :if (:typeof [:find $cacheName $addr] >= 0) do={
           :set $match true
       }
    }
    :if ( $match ) do={
        :local tmpAddress [/ip dns cache get $i address]
        :if ( [/ip firewall address-list find ] = "") do={
            :log debug ("added entry: $[/ip dns cache get $i name] IP $tmpAddress")
            /ip firewall address-list add address=$tmpAddress list=$ListName comment=$cacheName
        } else={
            :foreach j in=[/ip firewall address-list find ] do={
                :if ( [/ip firewall address-list get $j address] = $tmpAddress ) do={
                    :set bNew false
                }
            }
            :if ( $bNew ) do={
                :log debug ("added entry: $[/ip dns cache get $i name] IP $tmpAddress")
                /ip firewall address-list add address=$tmpAddress list=$ListName comment=$cacheName
            }
        }
    }
}