MikroTik. RouterOS Script. Автоматическая генерация чистого шаблона конфигурации

Назначение: Скрипт для запуска ВНУТРИ MikroTik (RouterOS v7). Автоматически генерирует чистый .rsc-шаблон из текущей конфигурации, фильтруя специфичные для железа данные (MAC-адреса, серийные номера, лицензии) и добавляя блок переменных для последующего редактирования.

Преимущества:


Инструкция по использованию

Шаг 1: Создание скрипта в MikroTik

Вариант А: Через WinBox

  1. Открой SystemScripts
  2. Нажми + (Add)
  3. Name: generate_clean_template
  4. Source: скопируй весь код ниже
  5. Нажми OK

Вариант Б: Через терминал (SSH/Telnet)

/system script add name=generate_clean_template source="ВСТАВИТЬ_КОД_СКРИПТА"

Шаг 2: Запуск скрипта

/system script run generate_clean_template

Шаг 3: Скачивание результата

Файл clean_template_YYYY-MM-DD.rsc появится в Files. Скачай через WinBox (drag & drop).


Код скрипта RouterOS

# ============================================================
# MikroTik RouterOS Script: Генерация чистого шаблона конфигурации
# Версия: 1.0
# Дата: 2026-09-08
# Описание: Автоматически генерирует .rsc-шаблон из текущей конфигурации,
#           фильтруя специфичные для железа данные
# ============================================================
 
:local scriptName "generate_clean_template"
:local date [/system clock get date]
:local time [/system clock get time]
:local filename "clean_template_" . [:pick $date 0 2] . [:pick $date 3 6] . [:pick $date 7 11] . ".rsc"
 
:log info "=== НАЧАЛО ГЕНЕРАЦИИ ШАБЛОНА ==="
:log info "Файл: $filename"
:put "=== НАЧАЛО ГЕНЕРАЦИИ ШАБЛОНА ==="
:put "Файл: $filename"
 
# ============================================================
# БЛОК 1: Создание заголовка с переменными
# ============================================================
:local header "# ============================================================\n"
:set header ($header . "# MikroTik Clean Template Configuration\n")
:set header ($header . "# Generated: $date $time\n")
:set header ($header . "# Source device: [/system identity get name]\n")
:set header ($header . "# ============================================================\n\n")
:set header ($header . "# === ШАБЛОН НАСТРОЕК (РЕДАКТИРОВАТЬ ПОД СЕБЯ) ===\n")
:set header ($header . ":local wanInterface \"ether1\"\n")
:set header ($header . ":local lanInterface \"ether2\"\n")
:set header ($header . ":local mgmtIP \"192.168.1.2/24\"\n")
:set header ($header . ":local targetIP \"192.168.1.50\"\n")
:set header ($header . ":local localSubnet \"192.168.1.0/24\"\n")
:set header ($header . ":local vpsEndpoint \"vps.example.com\"\n")
:set header ($header . ":local vpsPublicKey \"ЗАМЕНИТЬ_КЛЮЧ\"\n")
:set header ($header . "# === КОНЕЦ ШАБЛОНА ===\n\n")
 
# ============================================================
# БЛОК 2: Сбор конфигурации по секциям
# ============================================================
:local config ""
 
# --- Интерфейсы (списки) ---
:set config ($config . "# === INTERFACE LISTS ===\n")
:foreach ifaceList in=[/interface list find] do={
    :local name [/interface list get $ifaceList name]
    :if ($name != "all" && $name != "none") do={
        :set config ($config . "/interface list add name=$name\n")
    }
}
:set config ($config . "\n")
 
# --- Интерфейсы (члены списков) ---
:foreach member in=[/interface list member find] do={
    :local list [/interface list member get $member list]
    :local interface [/interface list member get $member interface]
    :if ($list != "all" && $list != "none") do={
        :set config ($config . "/interface list member add list=$list interface=$interface\n")
    }
}
:set config ($config . "\n")
 
# --- Мосты ---
:set config ($config . "# === BRIDGES ===\n")
:foreach br in=[/interface bridge find] do={
    :local name [/interface bridge get $br name]
    :local hwOffload [/interface bridge get $br hardware-offload]
    :set config ($config . "/interface bridge add name=$name hardware-offload=$hwOffload\n")
}
:set config ($config . "\n")
 
# --- Порты мостов ---
:foreach port in=[/interface bridge port find] do={
    :local bridge [/interface bridge port get $port bridge]
    :local interface [/interface bridge port get $port interface]
    :set config ($config . "/interface bridge port add bridge=$bridge interface=$interface\n")
}
:set config ($config . "\n")
 
# --- IP-адреса (кроме системных) ---
:set config ($config . "# === IP ADDRESSES ===\n")
:foreach addr in=[/ip address find] do={
    :local address [/ip address get $addr address]
    :local interface [/ip address get $addr interface]
    :local network [/ip address get $addr network]
    :if ($interface != "lo" && $interface != "all") do={
        :set config ($config . "/ip address add address=$address interface=$interface network=$network\n")
    }
}
:set config ($config . "\n")
 
# --- DNS ---
:set config ($config . "# === DNS ===\n")
:local dnsServers [/ip dns get servers]
:local dnsAllowRemote [/ip dns get allow-remote-requests]
:set config ($config . "/ip dns set servers=$dnsServers allow-remote-requests=$dnsAllowRemote\n\n")
 
# --- WireGuard ---
:set config ($config . "# === WIREGUARD ===\n")
:foreach wg in=[/interface wireguard find] do={
    :local name [/interface wireguard get $wg name]
    :local listenPort [/interface wireguard get $wg listen-port]
    :set config ($config . "/interface wireguard add name=$name listen-port=$listenPort disabled=no\n")
}
:set config ($config . "\n")
 
# --- WireGuard Peers ---
:foreach peer in=[/interface wireguard peers find] do={
    :local interface [/interface wireguard peers get $peer interface]
    :local publicKey [/interface wireguard peers get $peer public-key]
    :local endpoint [/interface wireguard peers get $peer endpoint-address]
    :local endpointPort [/interface wireguard peers get $peer endpoint-port]
    :local allowedAddr [/interface wireguard peers get $peer allowed-address]
    :set config ($config . "/interface wireguard peers add interface=$interface public-key=\"$publicKey\" endpoint-address=\"$endpoint\" endpoint-port=$endpointPort allowed-address=$allowedAddr persistent-keepalive=25\n")
}
:set config ($config . "\n")
 
# --- Таблицы маршрутизации ---
:set config ($config . "# === ROUTING TABLES ===\n")
:foreach rt in=[/routing table find] do={
    :local name [/routing table get $rt name]
    :if ($name != "main") do={
        :set config ($config . "/routing table add fib name=$name\n")
    }
}
:set config ($config . "\n")
 
# --- Маршруты ---
:foreach route in=[/routing route find] do={
    :local dstAddr [/routing route get $route dst-address]
    :local gateway [/routing route get $route gateway]
    :local routingTable [/routing route get $route routing-table]
    :if ($routingTable != "main" && $dstAddr != "0.0.0.0/0") do={
        :set config ($config . "/routing route add dst-address=$dstAddr gateway=$gateway routing-table=$routingTable\n")
    }
}
:set config ($config . "\n")
 
# --- Firewall Mangle ---
:set config ($config . "# === FIREWALL MANGLE ===\n")
:foreach mangle in=[/ip firewall mangle find] do={
    :local chain [/ip firewall mangle get $mangle chain]
    :local srcAddr [/ip firewall mangle get $mangle src-address]
    :local dstAddr [/ip firewall mangle get $mangle dst-address]
    :local action [/ip firewall mangle get $mangle action]
    :local newMark [/ip firewall mangle get $mangle new-routing-mark]
    :local inInt [/ip firewall mangle get $mangle in-interface]
 
    :local cmd "/ip firewall mangle add chain=$chain"
    :if ([:len $inInt] > 0 && $inInt != "all") do={ :set cmd ($cmd . " in-interface=$inInt") }
    :if ([:len $srcAddr] > 0 && $srcAddr != "0.0.0.0/0") do={ :set cmd ($cmd . " src-address=$srcAddr") }
    :if ([:len $dstAddr] > 0 && $dstAddr != "0.0.0.0/0") do={ :set cmd ($cmd . " dst-address=$dstAddr") }
    :set cmd ($cmd . " action=$action")
    :if ([:len $newMark] > 0) do={ :set cmd ($cmd . " new-routing-mark=$newMark") }
    :set cmd ($cmd . " passthrough=no")
 
    :set config ($config . $cmd . "\n")
}
:set config ($config . "\n")
 
# --- Firewall NAT ---
:set config ($config . "# === FIREWALL NAT ===\n")
:foreach nat in=[/ip firewall nat find] do={
    :local chain [/ip firewall nat get $nat chain]
    :local srcAddr [/ip firewall nat get $nat src-address]
    :local outInt [/ip firewall nat get $nat out-interface]
    :local action [/ip firewall nat get $nat action]
 
    :local cmd "/ip firewall nat add chain=$chain"
    :if ([:len $outInt] > 0 && $outInt != "all") do={ :set cmd ($cmd . " out-interface=$outInt") }
    :if ([:len $srcAddr] > 0 && $srcAddr != "0.0.0.0/0") do={ :set cmd ($cmd . " src-address=$srcAddr") }
    :set cmd ($cmd . " action=$action")
 
    :set config ($config . $cmd . "\n")
}
:set config ($config . "\n")
 
# ============================================================
# БЛОК 3: Сохранение в файл
# ============================================================
:local fullContent $header
:set fullContent ($fullContent . $config)
 
/file print file=$filename
/file set $filename contents=$fullContent
 
:log info "=== ШАБЛОН СОХРАНЕН: $filename ==="
:log info "Размер: $[:len $fullContent] символов"
:put "=== ШАБЛОН СОХРАНЕН: $filename ==="
:put "Размер: $[:len $fullContent] символов"
:put "Скачай файл через WinBox (Files → drag & drop)"
:put "Отредактируй блок переменных в начале файла"

Что делает скрипт

Блок Действие
1 Создает заголовок с блоком переменных для редактирования
2 Собирает конфигурацию по секциям: интерфейсы, мосты, IP, DNS, WireGuard, routing, firewall
3 Фильтрует системные объекты (lo, all, none) и специфичные данные (MAC, serial)
4 Сохраняет результат в файл clean_template_YYYY-MM-DD.rsc

Что НЕ попадает в шаблон (автоматически фильтруется)


Что попадает в шаблон


Использование шаблона на новом MikroTik

  1. Скачай clean_template_YYYY-MM-DD.rsc со старого роутера
  2. Отредактируй блок переменных в начале файла
  3. Загрузи файл на новый MikroTik через WinBox
  4. Выполни:
   /import file=clean_template_YYYY-MM-DD.rsc

Чек-лист после импорта

  1. Проверка интерфейсов:
   /interface print
   /interface bridge port print
  1. Проверка IP-адресов:
   /ip address print
  1. Проверка WireGuard:
   /interface wireguard peers print
  1. Проверка firewall:
   /ip firewall mangle print
   /ip firewall nat print
  1. Проверка маршрутизации:
   /routing route print

Устранение неполадок

Симптом Причина Решение
Скрипт не создает файл Недостаточно прав Запускать от пользователя с правами full
Файл создается, но пустой Ошибка в синтаксисе скрипта Проверить логи: /log print where topics~"script"
При импорте ошибка already exists Остатки старой конфигурации Выполнить /system reset-configuration no-defaults=yes перед импортом
Не поднимается WireGuard Неверный ключ в шаблоне Отредактировать $vpsPublicKey в начале файла

Дата создания: 2026-09-08
Версия документа: 1.0
Автор: Александр (интегратор Savant/KNX)


Связанные темы: KNX, MikroTik, Python