"Быстрый
<br />
Tool fetch — встроенный HTTP/HTTPS-клиент RouterOS. Качает файлы, отправляет GET и POST запросы, передаёт данные на внешние сервисы. Работает из консоли, скриптов и планировщика. Один инструмент — весь HTTP-стек на роутере без лишних зависимостей.<br />
<h2>Диагноз: зачем вообще fetch на роутере</h2>
<p>Поднял мониторинг, написал <a class="wpil_keyword_link" href="https://it-apteka.com/category/scripts/" target="_blank" rel="noopener" title="Скрипты" data-wpil-keyword-link="linked" data-wpil-monitor-id="1572">скрипт</a>, нужно отправить алерт в Telegram. Или забрать конфиг с внешнего сервера. Или скачать сертификат. Всё это можно сделать прямо из RouterOS — без сторонних инструментов, без SSH-тоннелей, без «а давай поставим Python на роутер».</p>
<p>Tool fetch делает именно это. Работает начиная с RouterOS 3.x, в современных версиях поддерживает HTTPS, POST, заголовки и работу через прокси. По факту это curl для бедных — но для большинства задач хватает с запасом.</p>
<p>Что ты получишь из этой статьи: все флаги с примерами, типовые сценарии от скачивания файла до отправки JSON, troubleshooting по ошибкам которые встречаются чаще всего, и готовые блоки кода которые можно копировать в скрипты.</p>
<p>Времени займёт 15 минут. Нужен: доступ к консоли RouterOS и понимание базового синтаксиса скриптов.</p>
<h3>Что будет в статье</h3>
<ul>
<li>Синтаксис и все параметры tool fetch</li>
<li>GET-запросы: скачивание файлов и получение данных</li>
<li>POST-запросы: отправка данных на внешний сервер</li>
<li>Работа через HTTP-прокси</li>
<li>HTTPS и работа с IPv6</li>
<li>Использование в скриптах и планировщике</li>
<li>Реальные примеры: Telegram, webhook, обновление конфига</li>
<li>Troubleshooting по ошибкам</li>
</ul>
<h2>Совместимость и системные требования</h2>
<table>
<thead>
<tr>
<th>Параметр</th>
<th>Значение</th>
<th>Примечание</th>
</tr>
</thead>
<tbody>
<tr>
<td>RouterOS минимум</td>
<td>v3.x</td>
<td>Базовый HTTP</td>
</tr>
<tr>
<td>HTTPS поддержка</td>
<td>v6.x+</td>
<td>Требует синхронизацию времени</td>
</tr>
<tr>
<td>HTTP POST</td>
<td>v6.x+</td>
<td>Параметры http-data и http-method</td>
</tr>
<tr>
<td>IPv6 fetch</td>
<td>v6.40+</td>
<td>Адрес в квадратных скобках</td>
</tr>
<tr>
<td>Proxy поддержка</td>
<td>v6.x+</td>
<td>Параметр proxy-server</td>
</tr>
<tr>
<td>Проверена на</td>
<td>v7.x (LTS)</td>
<td>Актуальная на момент публикации</td>
</tr>
</tbody>
</table>
<p>На момент публикации актуальна ветка RouterOS 7.x. Перед использованием проверь свежие релизы на mikrotik.com/download.</p>
<h2>Синтаксис tool fetch: все параметры</h2>
<p>Полный вид команды выглядит так:</p>
<pre><code class="language-bash">
/tool fetch \
url="https://example.com/file" \
mode=http \
http-method=get \
dst-path="/flash/file.txt" \
user="login" \
password="pass" \
http-header-field="Authorization: Bearer token123" \
http-data="key=value" \
proxy-server="192.168.1.100:3128" \
address="192.168.1.100" \
port=80 \
src-path="/path/on/server" \
upload=no \
keep-result=yes \
output=file \
as-value
</code></pre>
<p>Не пугайся — большинство параметров опциональны. В реальных задачах используешь 3-4 штуки. Разберём каждый.</p>
<h3>Параметры: справочник</h3>
<table>
<thead>
<tr>
<th>Параметр</th>
<th>Значения</th>
<th>Что делает</th>
</tr>
</thead>
<tbody>
<tr>
<td>url</td>
<td>строка</td>
<td>Полный URL запроса. Обязателен если не используешь address+src-path</td>
</tr>
<tr>
<td>mode</td>
<td>http, https, ftp, tftp, sftp</td>
<td>Протокол. По умолчанию определяется из url</td>
</tr>
<tr>
<td>http-method</td>
<td>get, post, put, head</td>
<td>HTTP-метод запроса. По умолчанию get</td>
</tr>
<tr>
<td>http-data</td>
<td>строка</td>
<td>Тело POST/PUT запроса</td>
</tr>
<tr>
<td>http-header-field</td>
<td>строка</td>
<td>Дополнительный HTTP-заголовок</td>
</tr>
<tr>
<td>dst-path</td>
<td>путь</td>
<td>Куда сохранить скачанный файл</td>
</tr>
<tr>
<td>output</td>
<td>file, user, none</td>
<td>Куда направить результат: файл, в переменную, никуда</td>
</tr>
<tr>
<td>as-value</td>
<td>флаг</td>
<td>Вернуть результат как значение (для скриптов)</td>
</tr>
<tr>
<td>keep-result</td>
<td>yes, no</td>
<td>Сохранять ли ответ. Нужен при output=file</td>
</tr>
<tr>
<td>proxy-server</td>
<td>ip:port</td>
<td>HTTP-прокси для запроса</td>
</tr>
<tr>
<td>user / password</td>
<td>строки</td>
<td>HTTP Basic Auth</td>
</tr>
<tr>
<td>check-certificate</td>
<td>yes, no</td>
<td>Проверять ли SSL-сертификат</td>
</tr>
<tr>
<td>upload</td>
<td>yes, no</td>
<td>Загрузить файл на сервер вместо скачивания</td>
</tr>
<tr>
<td>src-path</td>
<td>путь</td>
<td>Локальный файл для upload или путь на FTP</td>
</tr>
<tr>
<td>address</td>
<td>IP или hostname</td>
<td>Альтернатива url для FTP/TFTP</td>
</tr>
<tr>
<td>port</td>
<td>число</td>
<td>Порт сервера</td>
</tr>
</tbody>
</table>
<h2>Таблица портов и протоколов</h2>
<table>
<thead>
<tr>
<th>Протокол</th>
<th>Порт по умолчанию</th>
<th>Параметр mode</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTTP</td>
<td>80</td>
<td>http</td>
</tr>
<tr>
<td>HTTPS</td>
<td>443</td>
<td>https</td>
</tr>
<tr>
<td>FTP</td>
<td>21</td>
<td>ftp</td>
</tr>
<tr>
<td>TFTP</td>
<td>69 UDP</td>
<td>tftp</td>
</tr>
<tr>
<td>SFTP</td>
<td>22</td>
<td>sftp</td>
</tr>
</tbody>
</table>
<h2>Архитектура: как работает fetch</h2>
<pre class="mermaid">
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Скрипт / консоль / scheduler"] --> B["tool fetch"]
B --> C{Прокси?}
C -- нет --> D["DNS resolve"]
C -- да --> E["HTTP-прокси"]
E --> D
D --> F["TCP connect"]
F --> G{HTTPS?}
G -- да --> H["TLS handshake + cert check"]
G -- нет --> I["HTTP request"]
H --> I
I --> J["Ответ сервера"]
J --> K{output=?}
K -- file --> L["Сохранить в dst-path"]
K -- user --> M["Вернуть в переменную"]
K -- none --> N["Проверить status-code"]
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style H fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
style L fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style M fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style N fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
</pre>
<h2>Рецепт: базовые примеры</h2>
<h3>Шаг 1. Скачать файл на роутер</h3>
<p>Самый частый сценарий — обновить конфиг или скачать скрипт с внешнего сервера.</p>
<pre><code class="language-bash">
/tool fetch url="http://192.168.1.100/backup.rsc" dst-path="/flash/backup.rsc"
</code></pre>
<p>Результат: файл появляется в файловой системе RouterOS. Проверяй через:</p>
<pre><code class="language-bash">
/file print where name="backup.rsc"
</code></pre>
<p>Если файл есть — fetch отработал. Если нет — смотри раздел Troubleshooting.</p>
<h3>Шаг 2. HTTPS-запрос с проверкой сертификата</h3>
<p>Для HTTPS роутеру нужно синхронизированное время и пул сертификатов. Сначала проверь:</p>
<pre><code class="language-bash">
/system clock print
</code></pre>
<p>Если время верное — запускай:</p>
<pre><code class="language-bash">
/tool fetch url="https://example.com/api/data" \
mode=https \
check-certificate=yes \
output=user \
as-value
</code></pre>
<p>Если сертификат не проходит проверку (самоподписанный или внутренний CA) — используй check-certificate=no. Но не оставляй это в продакшне без понимания рисков.</p>
"Внимание:
<br />
Отключение проверки сертификата убирает защиту от MITM. Используй только для внутренних сервисов или тестирования. В продакшне всегда импортируй CA-сертификат через /certificate import.<br />
<h3>Шаг 3. GET-запрос и получение результата в переменную</h3>
<p>Нужно получить данные от API и что-то с ними сделать в скрипте:</p>
<pre><code class="language-bash">
:local result [/tool fetch url="http://api.example.com/status" \
output=user as-value]
:put ($result->"data")
</code></pre>
<p>Параметр as-value возвращает ответ как массив с ключами status, data, filename. Ключ data содержит тело ответа.</p>
<h3>Шаг 4. POST-запрос: отправка данных</h3>
<p>Отправить данные на вебхук, в REST API или в Telegram:</p>
<pre><code class="language-bash">
/tool fetch url="https://api.telegram.org/bot<TOKEN>/sendMessage" \
http-method=post \
http-data="chat_id=123456789&text=Router+alert" \
output=none
</code></pre>
<p>Вот тут важно: http-data передаётся как строка form-urlencoded. Если API ожидает JSON — нужно добавить заголовок Content-Type.</p>
<h3>Шаг 5. POST-запрос с JSON-телом</h3>
<pre><code class="language-bash">
/tool fetch url="https://hooks.example.com/webhook" \
http-method=post \
http-header-field="Content-Type: application/json" \
http-data="{\"event\":\"router_up\",\"host\":\"gw01\"}" \
output=none
</code></pre>
<p>Кавычки внутри JSON экранируются через \». Если скрипт сложный — выноси тело в переменную заранее.</p>
<h3>Шаг 6. HTTP Basic Authentication</h3>
<pre><code class="language-bash">
/tool fetch url="http://monitor.example.com/api/push" \
user="apiuser" \
password="secretpass" \
http-method=post \
http-data="status=ok" \
output=none
</code></pre>
<h3>Шаг 7. Запрос через прокси</h3>
<p>Роутер за NAT без прямого доступа в интернет — используй прокси:</p>
<pre><code class="language-bash">
/tool fetch url="http://update.example.com/config.rsc" \
proxy-server="10.0.0.1:3128" \
dst-path="/flash/config.rsc"
</code></pre>
<p>Прокси указывается как ip:port. Аутентификация на прокси через Basic Auth пока не поддерживается нативно — если прокси требует авторизацию, нужен прокси без неё или обходное решение.</p>
<h3>Шаг 8. IPv6 fetch</h3>
<p>Адрес IPv6 нужно заключить в квадратные скобки прямо в URL:</p>
<pre><code class="language-bash">
/tool fetch url="http://[2001:db8::1]/path/file.txt" \
dst-path="/flash/file.txt"
</code></pre>
<p>Если hostname резолвится в IPv6 — всё работает автоматически без квадратных скобок. Скобки нужны только при явном указании IPv6-адреса.</p>
<h3>Шаг 9. Загрузка файла на сервер (upload)</h3>
<pre><code class="language-bash">
/tool fetch address="192.168.1.100" \
src-path="/flash/backup.rsc" \
upload=yes \
user="ftpuser" \
password="ftppass" \
mode=ftp
</code></pre>
<h3>Шаг 10. Скачать и сразу выполнить скрипт</h3>
<p>Классический паттерн для централизованного управления конфигами:</p>
<pre><code class="language-bash">
/tool fetch url="http://cfg.example.com/setup.rsc" dst-path="/flash/setup.rsc"
/import /flash/setup.rsc
</code></pre>
<p>Сначала скачиваешь, потом импортируешь. Никогда не делай это в одну строку через eval — сначала убедись что файл скачался корректно.</p>
<h2>Реальные сценарии использования</h2>
<h3>Алерт в Telegram при падении линка</h3>
<p>Скрипт для Netwatch или scheduler. Срабатывает при изменении статуса интерфейса:</p>
<pre><code class="language-bash">
:local botToken "1234567890:ABCdefGHIjklMNOpqrSTUvwxyz"
:local chatId "123456789"
:local hostname [/system identity get name]
:local msg ("ALERT: " . $hostname . " - WAN link DOWN")
/tool fetch \
url=("https://api.telegram.org/bot" . $botToken . "/sendMessage") \
http-method=post \
http-data=("chat_id=" . $chatId . "&text=" . $msg) \
output=none
</code></pre>
<p>Точка — оператор конкатенации строк в RouterOS. Собираешь URL и тело динамически.</p>
<h3>Проверка внешнего IP и запись в переменную</h3>
<pre><code class="language-bash">
:local ipResult [/tool fetch url="http://ifconfig.me/ip" \
output=user as-value]
:local currentIP ($ipResult->"data")
:log info ("Current external IP: " . $currentIP)
</code></pre>
<h3>Динамическое обновление DNS через API</h3>
<pre><code class="language-bash">
:local apiKey "your-api-key"
:local domain "home.example.com"
:local newIP [/ip address get [find interface="pppoe-out1"] address]
# Убираем маску подсети
:set newIP [:pick $newIP 0 [:find $newIP "/"]]
/tool fetch \
url=("https://dyndns.example.com/update?hostname=" . $domain . "&myip=" . $newIP) \
http-header-field=("Authorization: ApiKey " . $apiKey) \
output=none
</code></pre>
<h3>Max Bot / мониторинг через webhook</h3>
<p>Паттерн для отправки метрик на внешний мониторинг. Работает с любым сервисом который принимает POST:</p>
<pre><code class="language-bash">
:local cpuLoad [/system resource get cpu-load]
:local memFree [/system resource get free-memory]
:local hostname [/system identity get name]
:local jsonBody ("{\"host\":\"" . $hostname . "\",\"cpu\":" . $cpuLoad . ",\"mem_free\":" . $memFree . "}")
/tool fetch url="https://metrics.example.com/push" \
http-method=post \
http-header-field="Content-Type: application/json" \
http-data=$jsonBody \
output=none
</code></pre>
<h3>Скачивание конфига по расписанию</h3>
<p>Создаёшь задачу в scheduler, которая раз в сутки тянет конфиг с сервера:</p>
<pre><code class="language-bash">
/system scheduler add \
name="fetch-config" \
start-time=03:00:00 \
interval=1d \
on-event="/tool fetch url=\"http://cfg.example.com/gw01.rsc\" dst-path=\"/flash/gw01.rsc\""
</code></pre>
<h2>Проверка: как убедиться что fetch сработал</h2>
<h3>Проверить статус последней команды</h3>
<pre><code class="language-bash">
# Запустить fetch и проверить код ответа
:local res [/tool fetch url="http://example.com/test" output=user as-value]
:put ($res->"status")
</code></pre>
<p>Поле status содержит «finished» при успехе. При ошибке fetch выбрасывает исключение — оборачивай в :do { } on-error { }.</p>
<h3>Проверить что файл скачался</h3>
<pre><code class="language-bash">
/file print detail where name="backup.rsc"
</code></pre>
<h3>Посмотреть лог выполнения</h3>
<pre><code class="language-bash">
/log print where topics~"script"
/log print where topics~"error"
</code></pre>
<h3>Тест DNS-резолвинга</h3>
<pre><code class="language-bash">
/ip dns cache print
/tool resolve address="api.telegram.org"
</code></pre>
<h2>Обработка ошибок в скриптах</h2>
<p>Fetch при ошибке кидает исключение и останавливает скрипт. Нормальная практика — обернуть в do/on-error:</p>
<pre><code class="language-bash">
:do {
:local res [/tool fetch url="https://example.com/api" \
output=user as-value]
:local data ($res->"data")
:log info ("Fetch OK: " . $data)
} on-error={
:log error "Fetch failed: connection error or timeout"
}
</code></pre>
<p>Это не опциональная практика. Если fetch упадёт без обёртки в планировщике — следующие строки скрипта не выполнятся. Узнаешь об этом в лучшем случае по логу.</p>
<h2>Осложнения: ошибки и их решения</h2>
<h3>could not resolve host</h3>
<table>
<thead>
<tr>
<th>Причина</th>
<th>Решение</th>
</tr>
</thead>
<tbody>
<tr>
<td>DNS не настроен</td>
<td>Проверить /ip dns print, добавить серверы</td>
</tr>
<tr>
<td>DNS работает но не отвечает</td>
<td>/tool resolve address=»google.com» — если ошибка, DNS недоступен</td>
</tr>
<tr>
<td>Нет маршрута к DNS-серверу</td>
<td>/ip route print — проверить дефолтный маршрут</td>
</tr>
</tbody>
</table>
<pre><code class="language-bash">
/ip dns set servers=8.8.8.8,1.1.1.1
/tool resolve address="example.com"
</code></pre>
<h3>SSL error / certificate verification failed</h3>
<table>
<thead>
<tr>
<th>Причина</th>
<th>Решение</th>
</tr>
</thead>
<tbody>
<tr>
<td>Неверное время на роутере</td>
<td>Настроить NTP: /system ntp client set enabled=yes servers=pool.ntp.org</td>
</tr>
<tr>
<td>Самоподписанный сертификат</td>
<td>Импортировать CA или поставить check-certificate=no</td>
</tr>
<tr>
<td>Устаревший CA в RouterOS</td>
<td>Обновить RouterOS или импортировать актуальный CA вручную</td>
</tr>
</tbody>
</table>
<pre><code class="language-bash">
/system ntp client set enabled=yes servers=pool.ntp.org
/system clock print
# Убедись что дата и время корректны
# Импорт CA-сертификата:
/certificate import file-name=ca.crt passphrase=""
</code></pre>
<h3>connection timed out</h3>
<table>
<thead>
<tr>
<th>Причина</th>
<th>Решение</th>
</tr>
</thead>
<tbody>
<tr>
<td>Нет маршрута к серверу</td>
<td>Проверить default route, /ip route print</td>
</tr>
<tr>
<td>Firewall блокирует исходящий трафик</td>
<td>/ip firewall filter print — проверить правила output/forward</td>
</tr>
<tr>
<td>Сервер недоступен</td>
<td>/tool ping address=»example.com»</td>
</tr>
</tbody>
</table>
<pre><code class="language-bash">
/ip route print where active=yes
/tool ping address="8.8.8.8" count=4
/ip firewall filter print chain=output
</code></pre>
<h3>got error response: 403 / 401</h3>
<p>Это не ошибка fetch — это ответ сервера. 401 — нет авторизации, 403 — нет прав.</p>
<pre><code class="language-bash">
# Проверить что передаёшь правильные учётные данные:
/tool fetch url="http://api.example.com/test" \
user="login" password="pass" \
output=user as-value
</code></pre>
<h3>fetch через прокси не работает</h3>
<pre><code class="language-bash">
# Проверить доступность прокси:
/tool ping address="10.0.0.1"
# Проверить что прокси принимает запросы без авторизации:
/tool fetch url="http://ifconfig.me/ip" \
proxy-server="10.0.0.1:3128" \
output=user as-value
</code></pre>
<h3>fetch не работает из scheduler</h3>
<p>Планировщик запускает скрипты в ограниченном окружении. Частая проблема — интерфейс ещё не поднялся в момент выполнения.</p>
<pre><code class="language-bash">
# Добавить задержку в начало скрипта:
:delay 10s
# Или проверять наличие маршрута перед запросом:
:if ([/ip route print count-only where active=yes gateway!=""] > 0) do={
/tool fetch url="http://example.com/config.rsc" dst-path="/flash/config.rsc"
}
</code></pre>
<h3>Некорректные символы в http-data</h3>
<p>Пробелы, кириллица и спецсимволы в POST-данных нужно экранировать. Пробел — это +, остальное — percent-encoding.</p>
<pre><code class="language-bash">
# Пробел в тексте - заменяем на +:
http-data="chat_id=123&text=Link+is+down"
# Для сложного текста с кириллицей - лучше JSON:
http-data="{\"text\":\"Линк упал\"}"
</code></pre>
<h2>Альтернативы tool fetch</h2>
<p>Fetch не единственный способ получить данные извне. Вот когда стоит смотреть в другую сторону:</p>
<table>
<thead>
<tr>
<th>Инструмент</th>
<th>Когда использовать</th>
<th>Ограничения</th>
</tr>
</thead>
<tbody>
<tr>
<td>tool fetch</td>
<td>HTTP/HTTPS/FTP задачи, скрипты, автоматизация</td>
<td>Нет multipart, ограниченный набор заголовков</td>
</tr>
<tr>
<td>TFTP (встроен)</td>
<td>Скачать firmware, конфиг по TFTP</td>
<td>Только простая передача файлов</td>
</tr>
<tr>
<td>FTP через fetch</td>
<td>Загрузка бэкапов на FTP-сервер</td>
<td>FTP без TLS не безопасен</td>
</tr>
<tr>
<td>Netinstall</td>
<td>Переустановка RouterOS</td>
<td>Не для автоматизации из скриптов</td>
</tr>
<tr>
<td>SSH из внешней системы</td>
<td>Когда нужны сложные HTTP-операции</td>
<td>Требует внешнего сервера с curl/python</td>
</tr>
</tbody>
</table>
<h2>Профилактика: как не поломать</h2>
<h3>Мониторинг</h3>
<p>Если fetch отправляет алерты — добавь мониторинг самого роутера. Нет смысла в алертах если роутер молчит из-за проблем с сетью.</p>
<pre><code class="language-bash">
/tool netwatch add host="8.8.8.8" interval=30s \
up-script="/log info \"Internet OK\"" \
down-script="/log warning \"Internet DOWN - fetch alerts may fail\""
</code></pre>
<h3>Резервное копирование</h3>
"Что
<br />
Перед тем как скрипты с fetch уйдут в продакшн — сохрани конфиг роутера. Экспорт конфига включает все скрипты и задачи планировщика.<br />
<pre><code class="language-bash">
# Создать бэкап и отправить на сервер:
/system backup save name="gw01-backup"
/tool fetch address="192.168.1.100" \
src-path="/flash/gw01-backup.backup" \
upload=yes \
user="ftpuser" \
password="ftppass" \
mode=ftp
</code></pre>
<p>Что бэкапить: полный <a class="wpil_keyword_link" href="https://it-apteka.com/category/rezervnoe-kopirovanie/" target="_blank" rel="noopener" title="Резервное копирование" data-wpil-keyword-link="linked" data-wpil-monitor-id="1573">backup</a> (.backup) и RSC-экспорт конфига (/export). Как часто: ежедневно. Где хранить: на отдельном сервере, не на самом роутере.</p>
<h3>Безопасность</h3>
<p>Несколько правил которые нельзя игнорировать:</p>
<ul>
<li>Не храни токены и пароли прямо в скриптах — используй /system script env если версия поддерживает, или выноси в переменные которые задаются при запуске</li>
<li>Ограничь доступ к конфигурации роутера по IP в /ip service</li>
<li>Не используй check-certificate=no для внешних сервисов — настрой время и импортируй CA</li>
<li>Лог fetch-запросов с токенами попадает в /log — учти это при настройке remote syslog</li>
</ul>
<pre><code class="language-bash">
# Ограничить WinBox и SSH по IP:
/ip service set winbox address=192.168.1.0/24
/ip service set ssh address=192.168.1.0/24
# Настроить NTP:
/system ntp client set enabled=yes servers=pool.ntp.org,time.cloudflare.com
</code></pre>
<h3>Обновление RouterOS</h3>
<p>Перед обновлением: сделай бэкап, проверь changelog на наличие изменений в tool fetch, проверь скрипты на тестовом устройстве. Откат: /system backup load name=»pre-update-backup».</p>
<pre><code class="language-bash">
# Проверить текущую версию:
/system resource print
# Проверить доступные обновления:
/system package update check-for-updates
</code></pre>
<h2>FAQ: вопросы которые задают чаще всего</h2>
<h3>Почему fetch не работает с HTTPS на старом RouterOS?</h3>
<p>Две причины. Первая — версия RouterOS до 6.x не поддерживает HTTPS в fetch вообще. Вторая — не синхронизировано время. Сертификаты проверяются в том числе по времени: если на роутере 2018 год, а сертификат выпущен в 2023 — проверка провалится. Настрой NTP первым делом.</p>
<pre><code class="language-bash">
/system clock print
/system ntp client print
</code></pre>
<h3>Как проверить что fetch отправил данные правильно?</h3>
<p>Используй webhook.site или requestbin.com — сервисы которые принимают любые HTTP-запросы и показывают их содержимое. Направь тестовый fetch туда и посмотри что реально пришло на сервер.</p>
<pre><code class="language-bash">
/tool fetch url="https://webhook.site/your-unique-id" \
http-method=post \
http-header-field="Content-Type: application/json" \
http-data="{\"test\":\"hello\"}" \
output=none
</code></pre>
<h3>Что если нужно передать несколько HTTP-заголовков?</h3>
<p>RouterOS поддерживает только один http-header-field в одной команде. Это ограничение платформы. Обходное решение — если нужны несколько заголовков, проверь нельзя ли обойтись одним (например, Authorization + Content-Type). Если без нескольких заголовков никак — задачу придётся решать с внешнего сервера через curl или Python.</p>
<h3>Почему fetch работает из консоли но не из scheduler?</h3>
<p>Планировщик запускает скрипты в момент загрузки или по таймеру. Если задача запускается при старте — сетевой интерфейс может быть ещё не поднят. Добавь :delay 15s в начало скрипта или проверяй наличие активного маршрута перед запросом fetch.</p>
<h3>Как передать бинарные данные через fetch?</h3>
<p>Никак. Tool fetch работает только с текстом. Для передачи бинарных файлов используй ftp/sftp upload или настрой внешний сервис.</p>
<h3>Можно ли использовать fetch для скачивания больших файлов?</h3>
<p>Технически да, но с ограничениями: оперативная память роутера ограничена, при output=user весь ответ буферизуется в памяти. Для файлов больше нескольких мегабайт используй output=file и dst-path. Для RouterOS с ограниченной флеш-памятью — TFTP или FTP могут быть надёжнее.</p>
<h2>Прогноз</h2>
<p>Теперь у тебя есть полная картина по tool fetch: от базового скачивания файла до отправки JSON в Telegram из скрипта планировщика. Команда простая, параметров немного, а применений — масса. Автоматизация мониторинга, централизованное управление конфигами, интеграция с внешними сервисами — всё это закрывается несколькими строками RouterOS-скрипта.</p>
<p>Одна мысль напоследок. Fetch это инструмент, а не архитектура. Если у тебя десятки роутеров и сложная логика — смотри в сторону Ansible с модулем routeros или централизованного управления через The Dude / Zabbix. Но для одного роутера, простых алертов и автоматического обновления конфига — fetch закрывает задачу элегантно и без лишних зависимостей.</p>
"Не
<br />
Если что-то пошло не так — опиши в комментариях: RouterOS версию, команду и текст ошибки из /log. Разберём конкретный случай.<br />
Быстрый ответ
Tool fetch — встроенный HTTP/HTTPS-клиент RouterOS. Качает файлы, отправляет GET и POST запросы, передаёт данные на внешние сервисы. Работает из консоли, скриптов и планировщика. Один инструмент — весь HTTP-стек на роутере без лишних зависимостей.
Диагноз: зачем вообще fetch на роутере
Поднял мониторинг, написал скрипт, нужно отправить алерт в Telegram. Или забрать конфиг с внешнего сервера. Или скачать сертификат. Всё это можно сделать прямо из RouterOS — без сторонних инструментов, без SSH-тоннелей, без «а давай поставим Python на роутер».
Tool fetch делает именно это. Работает начиная с RouterOS 3.x, в современных версиях поддерживает HTTPS, POST, заголовки и работу через прокси. По факту это curl для бедных — но для большинства задач хватает с запасом.
Что ты получишь из этой статьи: все флаги с примерами, типовые сценарии от скачивания файла до отправки JSON, troubleshooting по ошибкам которые встречаются чаще всего, и готовые блоки кода которые можно копировать в скрипты.
Времени займёт 15 минут. Нужен: доступ к консоли RouterOS и понимание базового синтаксиса скриптов.
Что будет в статье
- Синтаксис и все параметры tool fetch
- GET-запросы: скачивание файлов и получение данных
- POST-запросы: отправка данных на внешний сервер
- Работа через HTTP-прокси
- HTTPS и работа с IPv6
- Использование в скриптах и планировщике
- Реальные примеры: Telegram, webhook, обновление конфига
- Troubleshooting по ошибкам
Совместимость и системные требования
| Параметр |
Значение |
Примечание |
| RouterOS минимум |
v3.x |
Базовый HTTP |
| HTTPS поддержка |
v6.x+ |
Требует синхронизацию времени |
| HTTP POST |
v6.x+ |
Параметры http-data и http-method |
| IPv6 fetch |
v6.40+ |
Адрес в квадратных скобках |
| Proxy поддержка |
v6.x+ |
Параметр proxy-server |
| Проверена на |
v7.x (LTS) |
Актуальная на момент публикации |
На момент публикации актуальна ветка RouterOS 7.x. Перед использованием проверь свежие релизы на mikrotik.com/download.
Синтаксис tool fetch: все параметры
Полный вид команды выглядит так:
/tool fetch \
url="https://example.com/file" \
mode=http \
http-method=get \
dst-path="/flash/file.txt" \
user="login" \
password="pass" \
http-header-field="Authorization: Bearer token123" \
http-data="key=value" \
proxy-server="192.168.1.100:3128" \
address="192.168.1.100" \
port=80 \
src-path="/path/on/server" \
upload=no \
keep-result=yes \
output=file \
as-value
Не пугайся — большинство параметров опциональны. В реальных задачах используешь 3-4 штуки. Разберём каждый.
Параметры: справочник
| Параметр |
Значения |
Что делает |
| url |
строка |
Полный URL запроса. Обязателен если не используешь address+src-path |
| mode |
http, https, ftp, tftp, sftp |
Протокол. По умолчанию определяется из url |
| http-method |
get, post, put, head |
HTTP-метод запроса. По умолчанию get |
| http-data |
строка |
Тело POST/PUT запроса |
| http-header-field |
строка |
Дополнительный HTTP-заголовок |
| dst-path |
путь |
Куда сохранить скачанный файл |
| output |
file, user, none |
Куда направить результат: файл, в переменную, никуда |
| as-value |
флаг |
Вернуть результат как значение (для скриптов) |
| keep-result |
yes, no |
Сохранять ли ответ. Нужен при output=file |
| proxy-server |
ip:port |
HTTP-прокси для запроса |
| user / password |
строки |
HTTP Basic Auth |
| check-certificate |
yes, no |
Проверять ли SSL-сертификат |
| upload |
yes, no |
Загрузить файл на сервер вместо скачивания |
| src-path |
путь |
Локальный файл для upload или путь на FTP |
| address |
IP или hostname |
Альтернатива url для FTP/TFTP |
| port |
число |
Порт сервера |
Таблица портов и протоколов
| Протокол |
Порт по умолчанию |
Параметр mode |
| HTTP |
80 |
http |
| HTTPS |
443 |
https |
| FTP |
21 |
ftp |
| TFTP |
69 UDP |
tftp |
| SFTP |
22 |
sftp |
Архитектура: как работает fetch
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Скрипт / консоль / scheduler"] --> B["tool fetch"]
B --> C{Прокси?}
C -- нет --> D["DNS resolve"]
C -- да --> E["HTTP-прокси"]
E --> D
D --> F["TCP connect"]
F --> G{HTTPS?}
G -- да --> H["TLS handshake + cert check"]
G -- нет --> I["HTTP request"]
H --> I
I --> J["Ответ сервера"]
J --> K{output=?}
K -- file --> L["Сохранить в dst-path"]
K -- user --> M["Вернуть в переменную"]
K -- none --> N["Проверить status-code"]
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style H fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
style L fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style M fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style N fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
Рецепт: базовые примеры
Шаг 1. Скачать файл на роутер
Самый частый сценарий — обновить конфиг или скачать скрипт с внешнего сервера.
/tool fetch url="http://192.168.1.100/backup.rsc" dst-path="/flash/backup.rsc"
Результат: файл появляется в файловой системе RouterOS. Проверяй через:
/file print where name="backup.rsc"
Если файл есть — fetch отработал. Если нет — смотри раздел Troubleshooting.
Шаг 2. HTTPS-запрос с проверкой сертификата
Для HTTPS роутеру нужно синхронизированное время и пул сертификатов. Сначала проверь:
/system clock print
Если время верное — запускай:
/tool fetch url="https://example.com/api/data" \
mode=https \
check-certificate=yes \
output=user \
as-value
Если сертификат не проходит проверку (самоподписанный или внутренний CA) — используй check-certificate=no. Но не оставляй это в продакшне без понимания рисков.
Внимание: check-certificate=no
Отключение проверки сертификата убирает защиту от MITM. Используй только для внутренних сервисов или тестирования. В продакшне всегда импортируй CA-сертификат через /certificate import.
Шаг 3. GET-запрос и получение результата в переменную
Нужно получить данные от API и что-то с ними сделать в скрипте:
:local result [/tool fetch url="http://api.example.com/status" \
output=user as-value]
:put ($result->"data")
Параметр as-value возвращает ответ как массив с ключами status, data, filename. Ключ data содержит тело ответа.
Шаг 4. POST-запрос: отправка данных
Отправить данные на вебхук, в REST API или в Telegram:
/tool fetch url="https://api.telegram.org/bot<TOKEN>/sendMessage" \
http-method=post \
http-data="chat_id=123456789&text=Router+alert" \
output=none
Вот тут важно: http-data передаётся как строка form-urlencoded. Если API ожидает JSON — нужно добавить заголовок Content-Type.
Шаг 5. POST-запрос с JSON-телом
/tool fetch url="https://hooks.example.com/webhook" \
http-method=post \
http-header-field="Content-Type: application/json" \
http-data="{\"event\":\"router_up\",\"host\":\"gw01\"}" \
output=none
Кавычки внутри JSON экранируются через \». Если скрипт сложный — выноси тело в переменную заранее.
Шаг 6. HTTP Basic Authentication
/tool fetch url="http://monitor.example.com/api/push" \
user="apiuser" \
password="secretpass" \
http-method=post \
http-data="status=ok" \
output=none
Шаг 7. Запрос через прокси
Роутер за NAT без прямого доступа в интернет — используй прокси:
/tool fetch url="http://update.example.com/config.rsc" \
proxy-server="10.0.0.1:3128" \
dst-path="/flash/config.rsc"
Прокси указывается как ip:port. Аутентификация на прокси через Basic Auth пока не поддерживается нативно — если прокси требует авторизацию, нужен прокси без неё или обходное решение.
Шаг 8. IPv6 fetch
Адрес IPv6 нужно заключить в квадратные скобки прямо в URL:
/tool fetch url="http://[2001:db8::1]/path/file.txt" \
dst-path="/flash/file.txt"
Если hostname резолвится в IPv6 — всё работает автоматически без квадратных скобок. Скобки нужны только при явном указании IPv6-адреса.
Шаг 9. Загрузка файла на сервер (upload)
/tool fetch address="192.168.1.100" \
src-path="/flash/backup.rsc" \
upload=yes \
user="ftpuser" \
password="ftppass" \
mode=ftp
Шаг 10. Скачать и сразу выполнить скрипт
Классический паттерн для централизованного управления конфигами:
/tool fetch url="http://cfg.example.com/setup.rsc" dst-path="/flash/setup.rsc"
/import /flash/setup.rsc
Сначала скачиваешь, потом импортируешь. Никогда не делай это в одну строку через eval — сначала убедись что файл скачался корректно.
Реальные сценарии использования
Алерт в Telegram при падении линка
Скрипт для Netwatch или scheduler. Срабатывает при изменении статуса интерфейса:
:local botToken "1234567890:ABCdefGHIjklMNOpqrSTUvwxyz"
:local chatId "123456789"
:local hostname [/system identity get name]
:local msg ("ALERT: " . $hostname . " - WAN link DOWN")
/tool fetch \
url=("https://api.telegram.org/bot" . $botToken . "/sendMessage") \
http-method=post \
http-data=("chat_id=" . $chatId . "&text=" . $msg) \
output=none
Точка — оператор конкатенации строк в RouterOS. Собираешь URL и тело динамически.
Проверка внешнего IP и запись в переменную
:local ipResult [/tool fetch url="http://ifconfig.me/ip" \
output=user as-value]
:local currentIP ($ipResult->"data")
:log info ("Current external IP: " . $currentIP)
Динамическое обновление DNS через API
:local apiKey "your-api-key"
:local domain "home.example.com"
:local newIP [/ip address get [find interface="pppoe-out1"] address]
# Убираем маску подсети
:set newIP [:pick $newIP 0 [:find $newIP "/"]]
/tool fetch \
url=("https://dyndns.example.com/update?hostname=" . $domain . "&myip=" . $newIP) \
http-header-field=("Authorization: ApiKey " . $apiKey) \
output=none
Max Bot / мониторинг через webhook
Паттерн для отправки метрик на внешний мониторинг. Работает с любым сервисом который принимает POST:
:local cpuLoad [/system resource get cpu-load]
:local memFree [/system resource get free-memory]
:local hostname [/system identity get name]
:local jsonBody ("{\"host\":\"" . $hostname . "\",\"cpu\":" . $cpuLoad . ",\"mem_free\":" . $memFree . "}")
/tool fetch url="https://metrics.example.com/push" \
http-method=post \
http-header-field="Content-Type: application/json" \
http-data=$jsonBody \
output=none
Скачивание конфига по расписанию
Создаёшь задачу в scheduler, которая раз в сутки тянет конфиг с сервера:
/system scheduler add \
name="fetch-config" \
start-time=03:00:00 \
interval=1d \
on-event="/tool fetch url=\"http://cfg.example.com/gw01.rsc\" dst-path=\"/flash/gw01.rsc\""
Проверка: как убедиться что fetch сработал
Проверить статус последней команды
# Запустить fetch и проверить код ответа
:local res [/tool fetch url="http://example.com/test" output=user as-value]
:put ($res->"status")
Поле status содержит «finished» при успехе. При ошибке fetch выбрасывает исключение — оборачивай в :do { } on-error { }.
Проверить что файл скачался
/file print detail where name="backup.rsc"
Посмотреть лог выполнения
/log print where topics~"script"
/log print where topics~"error"
Тест DNS-резолвинга
/ip dns cache print
/tool resolve address="api.telegram.org"
Обработка ошибок в скриптах
Fetch при ошибке кидает исключение и останавливает скрипт. Нормальная практика — обернуть в do/on-error:
:do {
:local res [/tool fetch url="https://example.com/api" \
output=user as-value]
:local data ($res->"data")
:log info ("Fetch OK: " . $data)
} on-error={
:log error "Fetch failed: connection error or timeout"
}
Это не опциональная практика. Если fetch упадёт без обёртки в планировщике — следующие строки скрипта не выполнятся. Узнаешь об этом в лучшем случае по логу.
Осложнения: ошибки и их решения
could not resolve host
| Причина |
Решение |
| DNS не настроен |
Проверить /ip dns print, добавить серверы |
| DNS работает но не отвечает |
/tool resolve address=»google.com» — если ошибка, DNS недоступен |
| Нет маршрута к DNS-серверу |
/ip route print — проверить дефолтный маршрут |
/ip dns set servers=8.8.8.8,1.1.1.1
/tool resolve address="example.com"
SSL error / certificate verification failed
| Причина |
Решение |
| Неверное время на роутере |
Настроить NTP: /system ntp client set enabled=yes servers=pool.ntp.org |
| Самоподписанный сертификат |
Импортировать CA или поставить check-certificate=no |
| Устаревший CA в RouterOS |
Обновить RouterOS или импортировать актуальный CA вручную |
/system ntp client set enabled=yes servers=pool.ntp.org
/system clock print
# Убедись что дата и время корректны
# Импорт CA-сертификата:
/certificate import file-name=ca.crt passphrase=""
connection timed out
| Причина |
Решение |
| Нет маршрута к серверу |
Проверить default route, /ip route print |
| Firewall блокирует исходящий трафик |
/ip firewall filter print — проверить правила output/forward |
| Сервер недоступен |
/tool ping address=»example.com» |
/ip route print where active=yes
/tool ping address="8.8.8.8" count=4
/ip firewall filter print chain=output
got error response: 403 / 401
Это не ошибка fetch — это ответ сервера. 401 — нет авторизации, 403 — нет прав.
# Проверить что передаёшь правильные учётные данные:
/tool fetch url="http://api.example.com/test" \
user="login" password="pass" \
output=user as-value
fetch через прокси не работает
# Проверить доступность прокси:
/tool ping address="10.0.0.1"
# Проверить что прокси принимает запросы без авторизации:
/tool fetch url="http://ifconfig.me/ip" \
proxy-server="10.0.0.1:3128" \
output=user as-value
fetch не работает из scheduler
Планировщик запускает скрипты в ограниченном окружении. Частая проблема — интерфейс ещё не поднялся в момент выполнения.
# Добавить задержку в начало скрипта:
:delay 10s
# Или проверять наличие маршрута перед запросом:
:if ([/ip route print count-only where active=yes gateway!=""] > 0) do={
/tool fetch url="http://example.com/config.rsc" dst-path="/flash/config.rsc"
}
Некорректные символы в http-data
Пробелы, кириллица и спецсимволы в POST-данных нужно экранировать. Пробел — это +, остальное — percent-encoding.
# Пробел в тексте - заменяем на +:
http-data="chat_id=123&text=Link+is+down"
# Для сложного текста с кириллицей - лучше JSON:
http-data="{\"text\":\"Линк упал\"}"
Альтернативы tool fetch
Fetch не единственный способ получить данные извне. Вот когда стоит смотреть в другую сторону:
| Инструмент |
Когда использовать |
Ограничения |
| tool fetch |
HTTP/HTTPS/FTP задачи, скрипты, автоматизация |
Нет multipart, ограниченный набор заголовков |
| TFTP (встроен) |
Скачать firmware, конфиг по TFTP |
Только простая передача файлов |
| FTP через fetch |
Загрузка бэкапов на FTP-сервер |
FTP без TLS не безопасен |
| Netinstall |
Переустановка RouterOS |
Не для автоматизации из скриптов |
| SSH из внешней системы |
Когда нужны сложные HTTP-операции |
Требует внешнего сервера с curl/python |
Профилактика: как не поломать
Мониторинг
Если fetch отправляет алерты — добавь мониторинг самого роутера. Нет смысла в алертах если роутер молчит из-за проблем с сетью.
/tool netwatch add host="8.8.8.8" interval=30s \
up-script="/log info \"Internet OK\"" \
down-script="/log warning \"Internet DOWN - fetch alerts may fail\""
Резервное копирование
Что бэкапить и как
Перед тем как скрипты с fetch уйдут в продакшн — сохрани конфиг роутера. Экспорт конфига включает все скрипты и задачи планировщика.
# Создать бэкап и отправить на сервер:
/system backup save name="gw01-backup"
/tool fetch address="192.168.1.100" \
src-path="/flash/gw01-backup.backup" \
upload=yes \
user="ftpuser" \
password="ftppass" \
mode=ftp
Что бэкапить: полный backup (.backup) и RSC-экспорт конфига (/export). Как часто: ежедневно. Где хранить: на отдельном сервере, не на самом роутере.
Безопасность
Несколько правил которые нельзя игнорировать:
- Не храни токены и пароли прямо в скриптах — используй /system script env если версия поддерживает, или выноси в переменные которые задаются при запуске
- Ограничь доступ к конфигурации роутера по IP в /ip service
- Не используй check-certificate=no для внешних сервисов — настрой время и импортируй CA
- Лог fetch-запросов с токенами попадает в /log — учти это при настройке remote syslog
# Ограничить WinBox и SSH по IP:
/ip service set winbox address=192.168.1.0/24
/ip service set ssh address=192.168.1.0/24
# Настроить NTP:
/system ntp client set enabled=yes servers=pool.ntp.org,time.cloudflare.com
Обновление RouterOS
Перед обновлением: сделай бэкап, проверь changelog на наличие изменений в tool fetch, проверь скрипты на тестовом устройстве. Откат: /system backup load name=»pre-update-backup».
# Проверить текущую версию:
/system resource print
# Проверить доступные обновления:
/system package update check-for-updates
FAQ: вопросы которые задают чаще всего
Почему fetch не работает с HTTPS на старом RouterOS?
Две причины. Первая — версия RouterOS до 6.x не поддерживает HTTPS в fetch вообще. Вторая — не синхронизировано время. Сертификаты проверяются в том числе по времени: если на роутере 2018 год, а сертификат выпущен в 2023 — проверка провалится. Настрой NTP первым делом.
/system clock print
/system ntp client print
Как проверить что fetch отправил данные правильно?
Используй webhook.site или requestbin.com — сервисы которые принимают любые HTTP-запросы и показывают их содержимое. Направь тестовый fetch туда и посмотри что реально пришло на сервер.
/tool fetch url="https://webhook.site/your-unique-id" \
http-method=post \
http-header-field="Content-Type: application/json" \
http-data="{\"test\":\"hello\"}" \
output=none
Что если нужно передать несколько HTTP-заголовков?
RouterOS поддерживает только один http-header-field в одной команде. Это ограничение платформы. Обходное решение — если нужны несколько заголовков, проверь нельзя ли обойтись одним (например, Authorization + Content-Type). Если без нескольких заголовков никак — задачу придётся решать с внешнего сервера через curl или Python.
Почему fetch работает из консоли но не из scheduler?
Планировщик запускает скрипты в момент загрузки или по таймеру. Если задача запускается при старте — сетевой интерфейс может быть ещё не поднят. Добавь :delay 15s в начало скрипта или проверяй наличие активного маршрута перед запросом fetch.
Как передать бинарные данные через fetch?
Никак. Tool fetch работает только с текстом. Для передачи бинарных файлов используй ftp/sftp upload или настрой внешний сервис.
Можно ли использовать fetch для скачивания больших файлов?
Технически да, но с ограничениями: оперативная память роутера ограничена, при output=user весь ответ буферизуется в памяти. Для файлов больше нескольких мегабайт используй output=file и dst-path. Для RouterOS с ограниченной флеш-памятью — TFTP или FTP могут быть надёжнее.
Прогноз
Теперь у тебя есть полная картина по tool fetch: от базового скачивания файла до отправки JSON в Telegram из скрипта планировщика. Команда простая, параметров немного, а применений — масса. Автоматизация мониторинга, централизованное управление конфигами, интеграция с внешними сервисами — всё это закрывается несколькими строками RouterOS-скрипта.
Одна мысль напоследок. Fetch это инструмент, а не архитектура. Если у тебя десятки роутеров и сложная логика — смотри в сторону Ansible с модулем routeros или централизованного управления через The Dude / Zabbix. Но для одного роутера, простых алертов и автоматического обновления конфига — fetch закрывает задачу элегантно и без лишних зависимостей.
Не заработало - разберёмся
Если что-то пошло не так — опиши в комментариях: RouterOS версию, команду и текст ошибки из /log. Разберём конкретный случай.