Загрузка адресных списков огромного объема в Mikrotik на базе RouterOS

03 октября 2021, 16:56

ДИСКЛЕЙМЕР: Данная статья является исключительно исследованием в области возможностей различных систем и использования Node-RED для нетривиальных задач.

Имея в хозяйстве вполне себе неплохой роутер в лице Mikrotik 450G, подумалось мне поэкспериментировать с его возможностями. Конкретно с умением обрабатывать огромнейшие списки адресов для маршрутизации в отличном от основного направления рутинга. Зачем, спросите вы? А вот интересно стало.

В качестве тестового полигона, мне было необходимо найти где-то огромный список IP адресов, чтобы с ним играться. Недолго думая, я взял уже всем известное решение, которое подразумевает использование списка заблокированных адресов Роскомнадзором. Их на самом деле два: первый - список подсетей, который сейчас состоит из почти 20 тысяч записей и список конкретных адресов, который состоит из почти 360 тысяч записей.

Первый мучить было скучно и я взялся за второй. Благодаря ребятам из Роскомсвободы - он есть в наличии, причем в нужном мне JSON формате. Где его брать - писать не буду, захотите - сами найдете.

Итак исходные данные: JSON база на 360 тысяч позиций и необходимость его превращения в текстовый файл со строками в виде

/ip firewall address-list add list=anywhere address=IP_Address

Вроде бы простая задача, но как оказалось - есть нюансы. Для начала, с помощью ноды http request, мы запрашиваем исходные данные, потом форматируем их в JSON, сортируем, обрабатываем функцией, в результате которой мы получаем нужную последовательность строк, которую сохраняем в файл и запускаем скрипт, который этот файл уже обрабатывает и по FTP заливает на Mikrotik.

1600x_image.png?1633236800

А теперь подробнее. Начнем с первой функции. Она выглядит вот так:

var newArr = [];

msg.payload.forEach((item) => {
 let a = item.match(/.*\./);
 if (a!= null)
   {
    let res = ("/ip firewall address-list add list=anywhere address=" (тут знак плюса) item);
    newArr.push(res);
   } 
 else {}
});
msg.payload = newArr.toString().replace(/,/g, "\n");
return msg;

Зачем нам нужен item.match? А дело в том, что RouterOS не хочет брать в адресные списки IPv6 адреса. Вылетает с ошибкой и до свидания. Поэтому нам нужно отфильтровать весь список на соответствие IPv4, который слава богу делается простеньким RegExp при обработке каждого элемента массива. Кстати это уменьшает объем данных почти на 150 тысяч строк.

Функция берет каждый элемент массива, проверяет на соответствие IPv4 и добавляет в начало необходимый текст. После этого, массив преобразовывается в текст, а так как при преобразовании, в качестве разделителя появляется запятая, мы ее заменяем на перевод строки.

После обработки функцией, нам теперь достаточно сохранить полученный результат в файл. Пусть это будет файл /home/file.rsc, который мы и указываем в ноде сохранения файла.

1600x_image.png?1633240900

А дальше мы даем системе немного передохнуть, так как на такой объем данных было потрачено очень много памяти и после этого запускаем наш скрипт.

* там в одном месте надо ставить плюсик (оно помечено) и не забываем ставить свои логин и пароль вместо user:password

#!/bin/sh
LIST=/tmp/ftplist
FILENAME=""
COUNT=1
rm $LIST
echo "finish" >> $LIST

#Our local directory containing files to FTP
cd /home
rm -rf /home/small*.*
split --line-bytes=1000000 -d --additional-suffix=.rsc /home/file.rsc /home/small
#Get a directory listing & output to file
ls -lrt smal* | cut -c48-78 >> $LIST
while [ 1 ]
do
FILENAME=$(tail -$COUNT $LIST | head -1)
if [ $FILENAME = "finish" ] ; then
echo "Finished"
exit 0
else
cd /home
curl -T $FILENAME -u user:password ftp://IR_роутера/$FILENAME
COUNT=$(expr $COUNT !тут тоже знак плюса! 1)
fi
done

Что он делает? Он разделяет наш большой файл с командами на маленькие, размером в 1 мегабайт. Это необходимо для того, чтобы роутер не сходил с ума и спокойно, по чуть-чуть, мог забирать себе данные порционно. Иначе он вылетает с ошибкой.

Команда split как раз и разбивает файл file.rsc на кучу файлов smallXX.rsc, где XX это циферные суффиксы, которые создаются автоматически.

А дальше нам нужно запустить процесс, при котором стандартная команда ftp будет заливать на роутер по одному файлу за проход. Для этого нам нужно создать список файлов. Его мы получаем с помощью команды ls -lrt, которая нам выдает список файлов, обрезая ненужную нам информацию. диапазон 48-78 вам придется подбирать самостоятельно, чтобы получался чистый список файлов без каких либо дополнений.

В самом начале скрипта, мы записали во временный файл текст "finish", потом добавили в него список наших файлов, а сделано это для того, чтобы команда tail, брала из временного файла /tmp/ftplist нужный нам файл, закачивала его и переходила на строку выше. Как только цикл дойдет до текста "finish" - скрипт завершит работу.

В итоге работы этой связки, мы получаем загруженную пачку файлов (на текущий момент их 12), в которых содержатся 206 тысяч строк.

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

Для этого мы идем в раздел Firewall и во вкладке Address Lists создаем нужный нам список, например с названием anywhere.

1600x_image.png?1633240901
1600x_image.png?1633240900

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

Он очень простой и запускается несколько раз, на тот случай если первый запуск вылетит с ошибкой. Список то огромный и так у меня бывало несколько раз, что он не очищался полностью. Вообще в идеале запускать его несколько раз до полной очистки.

:do {
:do {/ip firewall address-list remove [/ip firewall address-list find list=anywhere]}
:delay 20s
:do {/ip firewall address-list remove [/ip firewall address-list find list=anywhere]}
;delay 20s
:do {/ip firewall address-list remove [/ip firewall address-list find list=anywhere]}
}

Затем мы создаем еще один скрипт, который и будет загружать наши данные в список адресов роутера. Он выполняется пошагово, с паузами, чтобы бедному роутеру дать время для разгрузки процессора, который в момент загрузки - загружен на 100%.

1600x_image.png?1633240900

Скрипт выглядит вот так:

:do {
:do {/import "/small00.rsc"}
:delay 2m
:do {/import "/small01.rsc"}
:delay 2m
:do {/import "/small02.rsc"}
:delay 2m
:do {/import "/small03.rsc"}
:delay 2m
:do {/import "/small04.rsc"}
:delay 2m
:do {/import "/small05.rsc"}
:delay 2m
:do {/import "/small06.rsc"}
:delay 2m
:do {/import "/small07.rsc"}
:delay 2m
:do {/import "/small08.rsc"}
:delay 2m
:do {/import "/small09.rsc"}
:delay 2m
:do {/import "/small10.rsc"}
:delay 2m
:do {/import "/small11.rsc"}
:delay 2m
:do {/import "/small12.rsc"}
:delay 2m
:do {/import "/small13.rsc"}
} on-error={
    :put "import failed. unknown error.";
}

:put "Update Complete.";

}

Можно конечно сделать по умному и использовать различные переборы, но так намного проще и не нужно выдумывать. Благо если файлов меньше чем указано, он просто пропустит, а если файлов больше - когда нибудь вы это увидите, благо списки растут не так быстро.

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

Чтобы их использовать, надо настроить маршрутизацию. Допустим у вас есть какой нибудь второй провайдер или VPN, который уже настроен и функционирует. Тогда нам нужно создать таблицу маршрутизации, правило маршрутизации и указать маршрут в нужном направлении, с учетом созданных правил.

1600x_image.png?1633240903
1600x_image.png?1633240904
1600x_image.png?1633240904

После этого, на вкладке Mangle, раздела Firewall, нужно создать правило, которое будет маркировать пакеты с точкой назначения из нашего мега-списка, как необходимые отправлять в отличном от основного маршрута направления.

1600x_image.png?1633240904
1600x_image.png?1633240902

Вот в общем то и все. Огромный список крутится, обновление можно настроить по любому расписанию, только необходимо учесть, что очистка списка занимает минут 20, а его загрузка где то полчаса. Поэтому это лучше делать или вручную или с помощью штатного Scheduler в RouterOS, просто расписание нужно настроить с учетом этих временных задержек.

Кстати самое смешное, linkedin.com, который по идее должен быть в этом списке и на нем очень удобно проверять - в этом списке отсутствует. Но можно сделать еще один лист, в который можно добавлять адреса вручную и также направлять их в нужном вам направлении. Также как и наоборот - исключать из списка. Необходимо только учитывать, чтоб обработка Mangle идет сверху вниз, так что максимальный приоритет идет у нижних записей. То есть сверху самые массовые, а дальше исключения.


Все новости мира умных домов - t.me/SprutAI_News или Instagram
Остались вопросы? Мы в Telegram - @SprutAI

Хочешь умный дом но нет времени разбираться?
Посмотри примеры работ и выбери себе интегратора.
  1. Anton Stolov (soulassassino)
    Anton Stolov (soulassassino) 19 дней назад

    Лойс! ...одно из лучших на портале. Спасибо.

  2. (gryphonv2)
    (gryphonv2) 19 дней назад

    Исходя из опыта, чем мучать железку, проще в список для "обхода" ручками писать буквенные адреса (тем более что микротик с определенной версии умеет их сам резолвить). Это экономит кучу времени и не так напрягает железки. Тем более, что 99,9% заблокированного так никогда и не понадобится :)

    • Виталий Никольский (bigmanekb)

      Ну тут вопрос был исключительно теоретический. Вывезет или нет. Потому что ходили разные слухи, что кто-то грузил сколько то тысяч и рутеру плохело. Вот по результату, 206 тысяч адресов в списке, загрузка процессора не превышает 15% и все бодро летает.

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

К списку статей

Похожие статьи

25 сентября 2020, 11:49
Сенсорный монитор для управления умным домом. Настройка и использование.
18 февраля 2020, 17:06
В данной статье описывается сборка слаботочного эл. щита на базе Wiren Board 6, а так же силового щита для небольшой квартиры.
01 октября 2019, 07:07
"У всякого в умном дому неведомо никому" (с) Народная мудрость
08 апреля 2020, 11:32
Голосовые уведомления через Xiaomi Gateway, Home Assistant и HomeKit. Пример реализации, кейсы применения.
09 ноября 2018, 17:31
В данной статье рассматривается определенный подход инсталляции и конфигурации базовой среды, для последующей возможности простой, в плане настройки, автоматизации УД с помощью симбиоза HomeAssistant и Node-RED.
04 апреля 2019, 08:22
Личная жизнь мешает увлечению "умным домом"? Есть решение!
09 января 2019, 17:34
Небольшая статья о том, зачем нужна малина, почему автоматизации в HomeKit это не очень хорошо и чем USB стик лучше отдельного шлюза.
03 апреля 2019, 04:29
Разбираем простейшую задачу по электрическому подключению светодиодной ленты к источнику питания и управлению через Умный дом.
04 апреля 2019, 17:48
Расскажу о том за ~1 час перевезти УД с 2мя USB стиками с Raspberry PI на Synology NAS.
06 сентября 2019, 17:03
Кладём на лопатки NodeRed и HomeAssistant с помощью iOS 13.1 и Siri Shortcuts.