From 046c83743d5b519d53721965cb82750007f98c34 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 12 Jun 2026 13:42:36 +0000 Subject: [PATCH] Add google-ip-updater.rsc (Google IP ranges -> address-list) Parses official goog.json and loads IPv4 prefixes into the VPN_ytb address-list. Follows the cloudflare/telegram updater house style: fetch with check-certificate=no + error handling, nil-safe JSON parsing (no infinite-loop risk), temp-array build then swap so the list is never empty mid-update, and summary logging. --- README.md | 1 + routeros/google-ip-updater.rsc | 103 +++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 routeros/google-ip-updater.rsc diff --git a/README.md b/README.md index 79ecfa9..436e753 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ zabbix/ Шаблоны Zabbix | `check-isp.rsc` | Проверка доступности двух провайдеров пингом и сброс соединений упавшего канала (для dual-WAN). | | `cloudflare-ip-updater.rsc` | Обновление address-list `CF` актуальными IPv4-подсетями Cloudflare (по расписанию). | | `telegram-ip-updater.rsc` | Обновление address-list `TG` актуальными IPv4-подсетями Telegram (по расписанию). | +| `google-ip-updater.rsc` | Обновление address-list `VPN_ytb` актуальными IPv4-диапазонами Google (goog.json) — для policy-routing на Google/YouTube (по расписанию). | | `ospf_filter_rules` | Фильтры OSPF: принимать только частные подсети (RFC 1918). | | `routerboard_fwupgrade` | Задание планировщика: автообновление прошивки RouterBOARD с перезагрузкой. | | `routerboard_starwars` | Имперский марш на системном динамике после загрузки. | diff --git a/routeros/google-ip-updater.rsc b/routeros/google-ip-updater.rsc new file mode 100644 index 0000000..4c7a1ac --- /dev/null +++ b/routeros/google-ip-updater.rsc @@ -0,0 +1,103 @@ +# Google IP Address List Updater (IPv4 only) +# Работает на RouterOS 6.43+ и 7.x +# Скачивает официальный список IP-диапазонов Google (goog.json) и обновляет +# address-list. Удобно для policy-routing/VPN на сервисы Google (включая YouTube). +# +# Источник: https://www.gstatic.com/ipranges/goog.json +# Внимание: goog.json содержит ВСЕ публичные диапазоны Google, а не только YouTube. +# +# Установка: +# /import file-name=google-ip-updater.rsc +# /system script +# add name=google-ip-updater policy=read,write,test source=[/file get google-ip-updater.rsc contents] +# /system script run google-ip-updater +# +# Автозапуск: +# /system scheduler +# add name=google-update interval=7d start-time=03:41:00 \ +# on-event="/system script run google-ip-updater" \ +# policy=read,write,test + +:local url "https://www.gstatic.com/ipranges/goog.json" +:local listName "VPN_ytb" +:local cmnt "google-auto" + +# --- 1. Скачиваем список прямо в переменную (без временного файла) --- +# output=user as-value отдаёт тело ответа в массив, минуя файловую систему. +:local content "" +:do { + # check-certificate=no — список публичный, а на роутере может не быть + # импортированного CA-хранилища, из-за чего HTTPS-fetch падает на TLS. + :local result [/tool fetch url=$url check-certificate=no output=user as-value] + :if (($result->"status") = "finished") do={ + :set content ($result->"data") + } +} on-error={ + :log error "Google IP updater: Fetch failed (check DNS / internet / TLS)" + :error "Fetch failed" +} + +# --- 2. Проверяем, что что-то скачалось --- +:local size [:len $content] +:if ($size = 0) do={ + :log error "Google IP updater: Empty response" + :error "Empty response" +} +:log info "Google IP updater: Downloaded successfully ($size bytes)" + +# --- 3. Разбираем JSON во временный набор адресов --- +# Сначала собираем валидные IPv4-сети в массив и только потом меняем +# боевой address-list — так список не остаётся пустым во время обновления. +# Формат goog.json: { "prefixes": [ { "ipv4Prefix": "8.8.4.0/24" }, ... ] } +:local newList [:toarray ""] +:local startTag "\"ipv4Prefix\": \"" +:local tagLen [:len $startTag] +:local pos 0 + +:while ($pos < $size) do={ + :local findPos [:find $content $startTag $pos] + :if ([:typeof $findPos] = "nil") do={ + # Больше префиксов нет — выходим из цикла. + :set pos $size + } else={ + :local start ($findPos + $tagLen) + :local endPos [:find $content "\"" $start] + :if ([:typeof $endPos] = "nil") do={ + # Незакрытая кавычка (битый ответ) — прекращаем разбор. + :set pos $size + } else={ + :local subnet [:pick $content $start $endPos] + :if ([:len $subnet] > 0) do={ :set newList ($newList , $subnet) } + # Всегда двигаем позицию вперёд, чтобы не зациклиться. + :set pos ($endPos + 1) + } + } +} + +# --- 4. Обновляем address-list только при наличии валидных записей --- +:if ([:len $newList] = 0) do={ + :log warning "Google IP updater: No valid IPv4 prefixes found!" + :error "No valid entries" +} + +:local oldCount [:len [/ip firewall address-list find list=$listName comment=$cmnt]] +:if ($oldCount > 0) do={ + /ip firewall address-list remove [find list=$listName comment=$cmnt] + :log info "Google IP updater: Removed $oldCount old entries from '$listName'" +} + +:local count 0 +:local skipped 0 +:foreach ip in=$newList do={ + :do { + /ip firewall address-list add list=$listName address=$ip comment=$cmnt + :set count ($count + 1) + } on-error={ + :set skipped ($skipped + 1) + :log warning "Google IP updater: Skipped invalid entry: '$ip'" + } +} + +# --- 5. Финальный лог --- +:log info "Google IP updater: Added $count IPv4 prefixes to '$listName' (skipped $skipped invalid)" +:put ("Done! Added: $count subnets to '$listName' (skipped $skipped)")