четверг, 8 декабря 2016 г.

Переносим динамический адрес-лист на другой Mikrotik.

  Обратился человек по имени Serg и попросил помочь с написанием скрипта. Суть скрипта такова, есть некий динамически список (dynamic address list) в Mikrotik - его нужно сохранить. А после перезагрузки маршрутизатора - восстановить с тем же таймаутом (address-list timeout). Проблема эта возникла из-за того, что после перезагрузки маршрутизатора динамические адрес-листы очищаются. Попутно было бы не плохо переносить эти адрес-листы на другие Микротики.
  Начнем с того, что командой экспорта динамические листы экспортировать не получиться, она сохраняет только статические листы:



  Поэтому для экспорта динамического листа можно использовать команду print. Для адрес-листа 3333 команда будет такая:

/ip firewall address-list print file=list where list="3333"
Файл list.txt имеет такой вид:


  После сохранения этого файла мы можем его импортировать на другой маршрутизатор, или на этот же, но после перезагрузки. Скрипт импорта:
if ( [/file get [/file find name=list.txt] size] > 0 ) do={
:global content [/file get [/file find name=list.txt] contents] ;
:global contentLen [ :len $content ] ;
:global lineEnd 0;
:global line "";
:global lastEnd 0;
:global addrip "";
:global list "";
:global timeout "";
:global end 0;
:do {
:set lineEnd [:find $content "\n" $lastEnd ] ;
:set line [:pick $content $lastEnd $lineEnd] ;
:set lastEnd ( $lineEnd + 1 ) ;
:if ( [:pick $line 0 1] != "#" and [:pick $line 0 1] != "F" and [:pick $line 0 2] != " #" and [:len $line ] > 40) do={
:set end [:find $line " " 27] ;
:set addrip [:pick $line 27 $end] ;
:set end [:find $line " " 5] ;
:set list [:pick $line 5 $end] ;
:set end [:find $line " " 59] ;
:set timeout [:pick $line 59 $end] ;
:put "IP: $addrip, list: $list, timeout: $timeout"
/ip firewall address-list add address=$addrip list=$list timeout=$timeout comment="imported"
}
} while ($lineEnd < $contentLen)
}
 Этот скрипт возвращает наш динамический лист на место со всеми количествами записей которые в нем есть. Так же сохраняется таймаут записей на момент создания файла list.txt. 

Импортированные записи с комментарием "imported".

  Есть еще один путь, это скриптом сделать файл импорта:
{
:local lists {"3333"}
:local export "list"
:local file "/ip firewall address-list\n"
:foreach i in=$lists do={
:set $file ($file . "remove [find list=\"" . $i . "\"]\n")
:foreach j in=[/ip firewall address-list print as-value where list=$i] do={
:set $file ($file . "add list=\"" . ($j->"list") . "\" address=\"" . ($j->"address") . "\" timeout=\"" . ($j->"timeout") . "\"\n")
}
}
:if ([/file print count-only where name=$export] = 0) do={
/file print file=$export
:delay 2
}
/file set $export contents=$file
delay 2
/tool fetch address=1.1.1.1 port=21 src-path=list.txt upload=yes user=admin mode=ftp password=admin dst-path=list.rsc
delay 2
/file remove list.txt
}
  Для отработки скрипта нужно создать ftp-аккаунт и дать права на загрузку файлов для этого пользователя. Загружать будем с себя на себя. Это нужно из-за того, что напрямую (кроме как командой export) создать файл .rsc нельзя - тут подробнее. После этого скрипта создается файл list.rsc.


   С таким содержанием:


  Который можно импортировать командой:
/import list.rsc
  Или загрузить по ftp с другого Микротика:
#Filename of export (must match receiving router import filename)
:local importFile "list.rsc"
#IP Address of router with existing address list(s)
:local hostIP 1.1.1.1
#FTP Username and Password
:local ftpUser admin
:local ftpPassword admin
tool fetch address=$hostIP src-path=$importFile dst-path=$importFile mode=ftp user=$ftpUser password=$ftpPassword
/import $importFile
  Стоит обратить внимание, что записи в нашем адрес-листе должны обязательно содержать поле "timeout" и не содержать комментариев. В противном случае - нужно будет подправлять скрипт. Скрипты проверены на версии RouterOS 6.37.3 (stable).
  Так же, нельзя забывать о том, что при таком исполнении мы упираемся в ограничение 4K размера буфера (переменных и другого). Это всегда активно обсуждается на офф. форуме, но ограничение как было - так и есть. Из-за этого адрес-лист большого размера может просто не экспортироваться. Ну и в v6.38rc микротиковцы поломали колонку timeout при команде "ip firewall address-list print file=" - в файле ее просто нет, из-за этого, естественно, скрипт уходит в ошибку (хотя команда "print detail" это поле имеет). Будем надеяться - пофиксят.
  Если вы знаете другой путь, как можно сохранить динамический список, например, в файл, без использования переменных (а соответственно и ограничения в 4096 = 4k) - пишите в комментариях.

UPD 15.12.16
  В теме на офф форуме нашли путь сохранения динамических листов в файлы большого обьема.



Используемые материалы:

Подписаться на новые статьи.

12 комментариев:

  1. День добрый!
    Кстати команда Import проглатывает и обычные текстовы файлы (/import *.txt) и можно не заморачиваться с ftp.

    Serg.

    ОтветитьУдалить
  2. Этот комментарий был удален автором.

    ОтветитьУдалить
  3. Не знаю как на предыдущих версиях, но на прошивке 6.45.6 можно не переименовывать через FTP txt в rsc, а сразу командой /import list.txt выполнить команды из файла.

    Вот такой скрипт сохранения адресов у меня (без поля timeout оно мне не нужно)

    {
    :local lists {"3333"}
    :local export "list"
    :local file "/ip firewall address-list\n"
    :foreach i in=$lists do={
    :set $file ($file . "remove [find list=\"" . $i . "\"]\n")
    :foreach j in=[/ip firewall address-list print as-value where list=$i] do={
    :set $file ($file . "add list=\"" . ($j->"list") . "\" address=\"" . ($j->"address") . "\"\n")
    }
    }
    :if ([/file print count-only where name=$export] = 0) do={
    /file print file=$export
    :delay 2
    /file set $export contents=$file
    }
    }

    ОтветитьУдалить
  4. супер, огромная тебе благодарность!

    ОтветитьУдалить
  5. День добрый ! Спасибо за статью! Но почему тов автомате через ваш скрипт из файла лист не происходит отработка, а по комменту Art все получается, но я так понял новые полученные динамические данные, тогда в этот лист попадать не будут, если делать без скрипта! Буду благодарен за наводочку, где могут быть грабли! Спс

    ОтветитьУдалить
  6. Добрый день. Выгрузил с помощью команды /ip firewall address-list print file=list where list="3333" провел обновление, перезагрузился. попытался обратно загрузить через команду /import list.txt и через скрипт. Не загружаются записи. Может подскажите в чем может быть дело и как еще попробовать. Железка mikrotika 3011

    ОтветитьУдалить
  7. Этот комментарий был удален автором.

    ОтветитьУдалить
  8. ip firewall address-list export file=address-list.rsc
    import file=address-list.rsc

    ОтветитьУдалить
    Ответы
    1. Это не будет работать с динамическими записями, только статика

      Удалить
  9. в filter rules, в моем правиле input поставил none static и айпи в Address lists стали статическими и по этому хорошо експортировались и импортировались через:
    ip firewall address-list export file=address-list.rsc
    import file=address-list.rsc

    для перевода динамики в статику использую в шеджулере таск:

    :foreach i in=[/ip firewall address-list find list=Fucking Hacker] do={
    :local ipaddress [/ip firewall address-list get $i address]
    :local dynamic [/ip firewall address-list get $i dynamic]
    if ($dynamic = true) do={
    /ip firewall address-list remove $i
    /ip firewall address-list add list=BAN Hacker address=$ipaddress
    }
    }



    железо:
    RB962UiGS-5HacT2HnT
    firmware 6.49

    ОтветитьУдалить
  10. Время сохрангяется только часы минуты секунды, если в неделях, месяцах то сохраняется только часы, минуты, секунды.

    ОтветитьУдалить