From 31f1ff13dd40a93edbebb210e1382d354783d3dd Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 12 Jun 2026 13:23:19 +0000 Subject: [PATCH] Optimize telegram-ip-updater (fetch to variable, atomic rebuild) + Obsidian guide --- routeros/docs/telegram-ip-updater-obsidian.md | 124 +++++++++++++++ routeros/telegram-ip-updater.rsc | 148 +++++++----------- 2 files changed, 182 insertions(+), 90 deletions(-) create mode 100644 routeros/docs/telegram-ip-updater-obsidian.md diff --git a/routeros/docs/telegram-ip-updater-obsidian.md b/routeros/docs/telegram-ip-updater-obsidian.md new file mode 100644 index 0000000..e44456e --- /dev/null +++ b/routeros/docs/telegram-ip-updater-obsidian.md @@ -0,0 +1,124 @@ +--- +title: Telegram IP Updater — установка на MikroTik +tags: + - mikrotik + - routeros + - firewall + - telegram + - script +created: 2026-06-12 +aliases: + - telegram-ip-updater + - TG address-list +--- + +# Telegram IP Updater — установка на MikroTik + +Скрипт [[telegram-ip-updater]] (`routeros/telegram-ip-updater.rsc`) скачивает актуальный список IPv4-сетей Telegram и наполняет ими firewall `address-list` с именем **`TG`**. + +> [!info] Назначение +> Список `TG` сам по себе ничего не блокирует и не разрешает — он используется в правилах firewall (например, разрешить/маркировать трафик к Telegram). Обновляется по расписанию, чтобы соответствовать официальным диапазонам Telegram (`https://core.telegram.org/resources/cidr.txt`). + +> [!warning] Требования +> - **RouterOS 6.43+** или **7.x** (используется `/tool fetch ... as-value`). +> - Доступ роутера в интернет (HTTPS к `core.telegram.org`). +> - Права скрипта: `read,write,test`. + +--- + +## Способ 1. Разовый запуск через `import` + +> [!tip] Когда использовать +> Быстро проверить работу или наполнить список один раз, без автообновления. + +### 1. Загрузить файл на роутер + +Перетащить `telegram-ip-updater.rsc` в **Files** (Winbox/WebFig), или скачать прямо на роутер: + +```routeros +/tool fetch url="https://raw.githubusercontent.com/gpas45/scripts/main/routeros/telegram-ip-updater.rsc" +``` + +### 2. Выполнить импорт + +```routeros +/import file-name=telegram-ip-updater.rsc +``` + +После этого `address-list TG` наполнится сразу. + +--- + +## Способ 2. System script + автозапуск (рекомендуется) + +> [!tip] Когда использовать +> Постоянная установка с обновлением по расписанию. + +### 1. Создать именованный скрипт + +```routeros +/system script +add name=telegram-ip-updater policy=read,write,test \ + source=[/file get telegram-ip-updater.rsc contents] +``` + +> [!note] +> Альтернатива — вставить тело скрипта вручную в `source={ ... }`, если файл не загружали в Files. + +### 2. Запустить вручную (проверка) + +```routeros +/system script run telegram-ip-updater +``` + +### 3. Поставить на автообновление (раз в сутки) + +```routeros +/system scheduler +add name=telegram-update interval=1d start-time=03:30:00 \ + on-event="/system script run telegram-ip-updater" \ + policy=read,write,test +``` + +--- + +## Проверка результата + +```routeros +/ip firewall address-list print where list=TG +/log print where message~"Telegram" +``` + +> [!success] Ожидаемый результат +> В списке появятся сети Telegram (`91.108.4.0/22`, `149.154.160.0/20`, …), а в логе — строка `Added N IPv4 entries`. + +--- + +## Использование списка в firewall + +Пример: разрешить трафик к сетям Telegram. + +```routeros +/ip firewall filter +add chain=forward dst-address-list=TG action=accept comment="allow Telegram" +``` + +--- + +## Возможные проблемы + +> [!bug]- Fetch ругается на сертификат +> На старых сборках добавь `check-certificate=no` в команду `fetch` внутри скрипта. + +> [!bug]- `as-value` не поддерживается +> RouterOS до 6.43 не умеет `fetch output=user as-value`. Нужна версия 6.43+ либо файловый вариант скрипта. + +> [!bug]- Список `TG` пустой +> Проверь интернет-доступ роутера и `policy` скрипта/расписания (`read,write`). Скрипт намеренно НЕ очищает старый список, если новый ответ пустой. + +--- + +## Связанные заметки + +- [[cloudflare-ip-updater-obsidian|CloudFlare IP Updater]] — тот же подход для CloudFlare +- [[initial-setup]] — базовый firewall и interface-lists diff --git a/routeros/telegram-ip-updater.rsc b/routeros/telegram-ip-updater.rsc index 3c9f66d..0e4c62e 100644 --- a/routeros/telegram-ip-updater.rsc +++ b/routeros/telegram-ip-updater.rsc @@ -1,116 +1,68 @@ # Telegram IP Address List Updater (IPv4 only) -# Работает на RouterOS 6.x и 7.x -# Скачивает и обновляет список IPv4-адресов Telegram -# +# Работает на RouterOS 6.43+ и 7.x +# Скачивает актуальный список IPv4-сетей Telegram и обновляет address-list. +# # Установка: # /system script add name=telegram-ip-updater source={ ... код ... } # /system script run telegram-ip-updater # # Автозапуск: -# /system scheduler add name=telegram-update interval=1d on-event=telegram-ip-updater start-time=03:30:00 +# /system scheduler add name=telegram-update interval=1d \ +# start-time=03:30:00 on-event="/system script run telegram-ip-updater" :local url "https://core.telegram.org/resources/cidr.txt" :local listName "TG" -:local tempFile "telegram-ips.txt" -# --- 1. Удаляем старый файл --- +# --- 1. Скачиваем список прямо в переменную (без временного файла) --- +# output=user as-value отдаёт тело ответа в массив, минуя файловую систему: +# это убирает создание/удаление файла, ожидание загрузки и проверки файла. +:local content "" :do { - /file remove $tempFile - :delay 1s -} on-error={} - -:log info "Telegram IP updater: Downloading $url..." - -# --- 2. Скачиваем файл --- -:do { - /tool fetch url=$url dst-path=$tempFile + :local result [/tool fetch url=$url output=user as-value] + :if (($result->"status") = "finished") do={ + :set content ($result->"data") + } } on-error={ - :log error "Telegram IP updater: Fetch command failed" + :log error "Telegram IP updater: Fetch failed" :error "Fetch failed" } -# --- 3. Ждём завершения загрузки --- -:local maxWait 30 -:local waited 0 -:while ([:len [/file find name=$tempFile]] = 0 && $waited < $maxWait) do={ - :delay 1s - :set waited ($waited + 1) -} - -:if ($waited >= $maxWait) do={ - :log error "Telegram IP updater: Download timeout" - :error "Download timeout" -} - -:delay 2s - -# --- 4. Проверка файла --- -:if ([:len [/file find name=$tempFile]] = 0) do={ - :log error "Telegram IP updater: File not found after download" - :error "Download failed" -} - -:local fileSize [/file get $tempFile size] -:if ($fileSize = 0) do={ - :log error "Telegram IP updater: Downloaded file is empty" - /file remove $tempFile - :error "Empty file" -} - -:log info "Telegram IP updater: File downloaded successfully ($fileSize bytes)" - -# --- 5. Очищаем старые записи --- -:local oldCount [:len [/ip firewall address-list find list=$listName]] -:if ($oldCount > 0) do={ - /ip firewall address-list remove [find list=$listName] - :log info "Telegram IP updater: Removed $oldCount old entries from '$listName'" +# --- 2. Проверяем, что что-то скачалось --- +:local size [:len $content] +:if ($size = 0) do={ + :log error "Telegram IP updater: Empty response" + :error "Empty response" } +:log info "Telegram IP updater: Downloaded successfully ($size bytes)" -# --- 6. Читаем файл и добавляем новые записи --- -:local content [/file get $tempFile contents] -:local start 0 -:local len [:len $content] -:local count 0 +# --- 3. Разбираем ответ во временный набор адресов --- +# Сначала собираем валидные IPv4-сети в массив и только потом меняем +# боевой address-list — так список не остаётся пустым во время обновления. +:local newList [:toarray ""] :local skipped 0 +:local start 0 +:local len $size :while ($start < $len) do={ :local pos [:find $content "\n" $start] - :if ([:typeof $pos] = "nil") do={ - :set pos $len - } - + :if ([:typeof $pos] = "nil") do={ :set pos $len } + :local line [:pick $content $start $pos] - - # Убираем \r + + # Убираем \r (CRLF) и пробелы по краям :local crPos [:find $line "\r"] - :if ([:typeof $crPos] != "nil") do={ - :set line [:pick $line 0 $crPos] - } - - # Убираем пробелы в начале + :if ([:typeof $crPos] != "nil") do={ :set line [:pick $line 0 $crPos] } :while ([:len $line] > 0 && [:pick $line 0 1] = " ") do={ :set line [:pick $line 1 [:len $line]] } - - # Убираем пробелы в конце :while ([:len $line] > 0 && [:pick $line ([:len $line] - 1)] = " ") do={ :set line [:pick $line 0 ([:len $line] - 1)] } - - # Пропускаем пустые строки и комментарии + + # Пропускаем пустые строки, комментарии и IPv6 (содержат двоеточие) :if ([:len $line] > 0 && [:pick $line 0 1] != "#") do={ - # Простая проверка: если есть двоеточие - это IPv6, пропускаем - :local colonPos [:find $line ":"] - - :if ([:typeof $colonPos] = "nil") do={ - # Нет двоеточия - пробуем добавить как IPv4 - :do { - /ip firewall address-list add list=$listName address=$line comment="Telegram IPv4" - :set count ($count + 1) - } on-error={ - :set skipped ($skipped + 1) - :log warning "Telegram IP updater: Skipped invalid IPv4 line: '$line'" - } + :if ([:typeof [:find $line ":"]] = "nil") do={ + :set newList ($newList , $line) } else={ :set skipped ($skipped + 1) } @@ -118,12 +70,28 @@ :set start ($pos + 1) } -# --- 7. Убираем временный файл --- -/file remove $tempFile - -# --- 8. Финальный лог --- -:if ($count > 0) do={ - :log info "Telegram IP updater: Successfully added $count IPv4 entries to address list '$listName' (skipped $skipped IPv6 entries)" -} else={ +# --- 4. Обновляем address-list только при наличии валидных записей --- +:if ([:len $newList] = 0) do={ :log warning "Telegram IP updater: No valid IPv4 entries found! (skipped $skipped entries)" + :error "No valid entries" } + +:local oldCount [:len [/ip firewall address-list find list=$listName]] +:if ($oldCount > 0) do={ + /ip firewall address-list remove [find list=$listName] + :log info "Telegram IP updater: Removed $oldCount old entries from '$listName'" +} + +:local count 0 +:foreach ip in=$newList do={ + :do { + /ip firewall address-list add list=$listName address=$ip comment="Telegram IPv4" + :set count ($count + 1) + } on-error={ + :set skipped ($skipped + 1) + :log warning "Telegram IP updater: Skipped invalid IPv4 entry: '$ip'" + } +} + +# --- 5. Финальный лог --- +:log info "Telegram IP updater: Added $count IPv4 entries to '$listName' (skipped $skipped non-IPv4/invalid entries)"