MikroTik REST API — автоматизация через HTTP
RouterOS 7 представила полноценный REST API, позволяющий управлять маршрутизатором через стандартные HTTP-запросы. Это открывает двери для интеграции MikroTik с любыми системами: мониторинг через Python-скрипты, управление из веб-приложений на Node.js, автоматизация через CI/CD пайплайны. REST API работает поверх HTTPS, использует Basic Auth для аутентификации и возвращает данные в JSON. В этом руководстве разберём все аспекты REST API: включение, аутентификацию, CRUD-операции с примерами curl, автоматизацию на Python и JavaScript, а также сравнение REST API с альтернативными способами программного доступа к RouterOS.
Описание
Что такое REST API в RouterOS
REST API — это HTTP-интерфейс, который транслирует HTTP-запросы в команды RouterOS CLI. Каждый путь в API соответствует пути в CLI:
| CLI-команда | REST API URL |
|---|---|
/ip/address/print | GET /rest/ip/address |
/ip/firewall/filter/print | GET /rest/ip/firewall/filter |
/interface/print | GET /rest/interface |
/system/identity/print | GET /rest/system/identity |
/system/reboot | POST /rest/system/reboot |
REST API доступен начиная с RouterOS 7.1beta4 и стабилизирован в 7.x ветке. В RouterOS 7.20+ он полностью готов к production-использованию.
Архитектура
codeHTTP Client ──[HTTPS, порт 443]──> RouterOS Web Service ──> REST Handler ──> CLI Engine │ ┌──────┼──────┐ │ │ │ Config State Actions
REST API использует тот же веб-сервер, что и WebFig. Запросы обрабатываются через /rest/ prefix и транслируются во внутренние CLI-команды.
HTTP-методы и CRUD
| HTTP-метод | RouterOS-операция | Описание |
|---|---|---|
GET | print | Чтение данных (списки, свойства) |
PUT | add | Создание нового элемента |
PATCH | set | Изменение существующего элемента |
DELETE | remove | Удаление элемента |
POST | любая команда | Выполнение произвольной команды |
REST API vs RouterOS API (8728) vs SSH
| Параметр | REST API | RouterOS API | SSH |
|---|---|---|---|
| Порт | 443 (HTTPS) | 8728 / 8729 (TLS) | 22 |
| Протокол | HTTP/HTTPS | Бинарный | SSH |
| Аутентификация | Basic Auth | API login | Ключи/пароль |
| Формат данных | JSON | Бинарные sentence | Текст |
| Клиентские библиотеки | Любой HTTP-клиент | librouteros, routeros-api | paramiko, ssh2 |
| Overhead | Средний (HTTP) | Минимальный (binary) | Средний (SSH) |
| Streaming | Нет | Да (listen) | Да (watch) |
| Firewall-совместимость | Легко (HTTPS) | Нужен открытый порт 8728 | Легко (SSH) |
| Интеграция | Любой язык/платформа | Нужна специальная библиотека | Любой SSH-клиент |
| Подходит для | Web-интеграции, скрипты, CI/CD | Высокопроизводительные приложения | Ручное управление, скрипты |
Рекомендация: REST API — лучший выбор для интеграций и автоматизации. RouterOS API — для приложений с высокими требованиями к производительности (мониторинг с частым опросом). SSH — для разовых задач и скриптов.
Настройка
Шаг 1: включение HTTPS-сервиса
REST API работает через веб-сервис RouterOS. Для безопасности используйте HTTPS:
[admin@MikroTik] ># Проверяем текущее состояние веб-сервисов /ip/service/print # Включаем HTTPS (www-ssl) /ip/service/set www-ssl disabled=no # Отключаем HTTP (небезопасный) /ip/service/set www disabled=yes # Ограничиваем доступ к API по IP /ip/service/set www-ssl address=192.168.88.0/24,10.0.0.0/8 # Проверяем порт (по умолчанию 443) /ip/service/print where name=www-ssl
Для HTTPS нужен SSL-сертификат. Можно использовать самоподписанный или Let's Encrypt:
[admin@MikroTik] ># Генерируем самоподписанный сертификат (для тестов) /certificate/add name=rest-api-cert \ common-name=router.local \ key-size=2048 \ days-valid=3650 \ key-usage=tls-server /certificate/sign rest-api-cert # Назначаем сертификат веб-сервису /ip/service/set www-ssl certificate=rest-api-cert
Шаг 2: создание пользователя для API
Создайте отдельного пользователя с минимальными правами:
[admin@MikroTik] ># Группа только для чтения (мониторинг) /user/group/add name=api-read \ policy=read,api,winbox,test,!write,!policy,!ftp,!reboot,!sensitive \ comment="REST API read-only access" # Группа для полного управления /user/group/add name=api-full \ policy=read,write,api,test,!policy,!ftp \ comment="REST API full access" # Пользователь для мониторинга (только чтение) /user/add name=api-monitor \ group=api-read \ password="MonitorPass!2025" \ address=192.168.88.0/24 \ comment="REST API monitoring user" # Пользователь для управления /user/add name=api-admin \ group=api-full \ password="AdminApiPass!2025" \ address=192.168.88.100/32 \ comment="REST API admin user"
Шаг 3: первый запрос через curl
Базовый синтаксис: curl -k -u user:password https://router-ip/rest/path
Флаг -k пропускает проверку SSL-сертификата (для самоподписанных). В production используйте валидный сертификат.
[admin@MikroTik] ># Эти команды выполняются на внешнем компьютере, не на MikroTik # GET — получить identity роутера # curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/system/identity # GET — список всех интерфейсов # curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/interface # GET — IP-адреса # curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/ip/address # GET — таблица маршрутизации # curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/ip/route
Шаг 4: CRUD-операции
GET — чтение данных:
[admin@MikroTik] ># Все IP-адреса (эквивалент /ip/address/print) # curl -k -u admin:pass https://192.168.88.1/rest/ip/address # Ответ JSON: # [ # {".id":"*1","address":"192.168.88.1/24","network":"192.168.88.0", # "interface":"bridge","actual-interface":"bridge","disabled":"false", # "dynamic":"false","comment":"LAN"} # ]
GET с фильтрацией (query parameters):
[admin@MikroTik] ># Фильтр по имени интерфейса # curl -k -u admin:pass "https://192.168.88.1/rest/interface?name=ether1" # Фильтр — только активные интерфейсы # curl -k -u admin:pass "https://192.168.88.1/rest/interface?running=true" # Фильтр по нескольким условиям # curl -k -u admin:pass "https://192.168.88.1/rest/ip/firewall/filter?chain=input&action=drop" # Получить конкретный элемент по .id # curl -k -u admin:pass "https://192.168.88.1/rest/ip/address/*1" # Свойства — выбрать конкретные поля # curl -k -u admin:pass "https://192.168.88.1/rest/interface?.proplist=name,type,running"
PUT — создание элемента:
[admin@MikroTik] ># Добавить IP-адрес (эквивалент /ip/address/add) # curl -k -u api-admin:AdminApiPass!2025 \ # -X PUT \ # -H "Content-Type: application/json" \ # -d '{"address":"10.0.0.1/24","interface":"ether2","comment":"REST API added"}' \ # https://192.168.88.1/rest/ip/address # Ответ: {"ret":"*A"} — возвращает .id нового элемента # Добавить firewall-правило # curl -k -u api-admin:AdminApiPass!2025 \ # -X PUT \ # -H "Content-Type: application/json" \ # -d '{"chain":"input","protocol":"tcp","dst-port":"8291","action":"accept","comment":"Allow Winbox"}' \ # https://192.168.88.1/rest/ip/firewall/filter # Добавить статический маршрут # curl -k -u api-admin:AdminApiPass!2025 \ # -X PUT \ # -H "Content-Type: application/json" \ # -d '{"dst-address":"10.10.0.0/16","gateway":"192.168.88.254","comment":"Office network"}' \ # https://192.168.88.1/rest/ip/route
PATCH — изменение элемента:
[admin@MikroTik] ># Изменить comment у IP-адреса (по .id) # curl -k -u api-admin:AdminApiPass!2025 \ # -X PATCH \ # -H "Content-Type: application/json" \ # -d '{"comment":"Updated via REST API"}' \ # https://192.168.88.1/rest/ip/address/*1 # Отключить интерфейс # curl -k -u api-admin:AdminApiPass!2025 \ # -X PATCH \ # -H "Content-Type: application/json" \ # -d '{"disabled":"true"}' \ # https://192.168.88.1/rest/interface/ether5 # Изменить identity роутера # curl -k -u api-admin:AdminApiPass!2025 \ # -X PATCH \ # -H "Content-Type: application/json" \ # -d '{"name":"office-router-01"}' \ # https://192.168.88.1/rest/system/identity
DELETE — удаление элемента:
[admin@MikroTik] ># Удалить IP-адрес по .id # curl -k -u api-admin:AdminApiPass!2025 \ # -X DELETE \ # https://192.168.88.1/rest/ip/address/*A # Удалить firewall-правило # curl -k -u api-admin:AdminApiPass!2025 \ # -X DELETE \ # https://192.168.88.1/rest/ip/firewall/filter/*5
POST — выполнение команд:
[admin@MikroTik] ># Перезагрузка роутера # curl -k -u api-admin:AdminApiPass!2025 \ # -X POST \ # https://192.168.88.1/rest/system/reboot # Пинг хоста # curl -k -u api-admin:AdminApiPass!2025 \ # -X POST \ # -H "Content-Type: application/json" \ # -d '{"address":"8.8.8.8","count":"4"}' \ # https://192.168.88.1/rest/ping # Создать бэкап # curl -k -u api-admin:AdminApiPass!2025 \ # -X POST \ # -H "Content-Type: application/json" \ # -d '{"name":"api-backup"}' \ # https://192.168.88.1/rest/system/backup/save
JSON-ответы и коды ошибок
Успешные ответы:
| Метод | HTTP-код | Тело ответа |
|---|---|---|
| GET | 200 | JSON-массив элементов |
| PUT | 201 | {"ret":"*id"} |
| PATCH | 200 | Пустое тело |
| DELETE | 200 | Пустое тело |
| POST | 200 | JSON-результат команды |
Ошибки:
| HTTP-код | Описание | Пример |
|---|---|---|
| 400 | Bad Request | Неверный формат JSON, неизвестное свойство |
| 401 | Unauthorized | Неверный логин/пароль |
| 404 | Not Found | Несуществующий путь или .id |
| 405 | Method Not Allowed | Неподдерживаемый HTTP-метод |
| 500 | Internal Error | Ошибка на стороне RouterOS |
Пример ошибки:
json{ "error": 400, "message": "input does not match any value of address", "detail": "failure: input does not match any value of address at ... (line 1 column 10)" }
Python: мониторинг MikroTik через REST API
Полноценный скрипт мониторинга на Python:
python#!/usr/bin/env python3 """MikroTik REST API Monitor — мониторинг через REST API.""" import requests import json import time from datetime import datetime from urllib3.exceptions import InsecureRequestWarning # Отключаем предупреждения о самоподписанном сертификате requests.packages.urllib3.disable_warnings(InsecureRequestWarning) class MikroTikAPI: def __init__(self, host, username, password, port=443, use_ssl=True): proto = "https" if use_ssl else "http" self.base_url = f"{proto}://{host}:{port}/rest" self.auth = (username, password) self.verify = False # True для production с валидным сертификатом def get(self, path, params=None): """GET-запрос — чтение данных.""" url = f"{self.base_url}/{path.strip('/')}" resp = requests.get(url, auth=self.auth, verify=self.verify, params=params) resp.raise_for_status() return resp.json() def put(self, path, data): """PUT-запрос — создание элемента.""" url = f"{self.base_url}/{path.strip('/')}" resp = requests.put(url, auth=self.auth, verify=self.verify, json=data) resp.raise_for_status() return resp.json() def patch(self, path, data): """PATCH-запрос — изменение элемента.""" url = f"{self.base_url}/{path.strip('/')}" resp = requests.patch(url, auth=self.auth, verify=self.verify, json=data) resp.raise_for_status() return resp.status_code def delete(self, path): """DELETE-запрос — удаление элемента.""" url = f"{self.base_url}/{path.strip('/')}" resp = requests.delete(url, auth=self.auth, verify=self.verify) resp.raise_for_status() return resp.status_code def post(self, path, data=None): """POST-запрос — выполнение команды.""" url = f"{self.base_url}/{path.strip('/')}" resp = requests.post(url, auth=self.auth, verify=self.verify, json=data or {}) resp.raise_for_status() return resp.json() if resp.content else None def monitor_router(api): """Сбор и вывод метрик роутера.""" # Системная информация identity = api.get("system/identity") resource = api.get("system/resource") print(f"\n{'='*60}") print(f"Router: {identity['name']}") print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"{'='*60}") print(f"Board: {resource[0]['board-name']}") print(f"Version: {resource[0]['version']}") print(f"Uptime: {resource[0]['uptime']}") print(f"CPU Load: {resource[0]['cpu-load']}%") total_mem = int(resource[0]['total-memory']) free_mem = int(resource[0]['free-memory']) used_pct = round((total_mem - free_mem) / total_mem * 100, 1) print(f"RAM Used: {used_pct}% ({(total_mem - free_mem) // 1048576}MB / {total_mem // 1048576}MB)") # Интерфейсы interfaces = api.get("interface") print(f"\nInterfaces ({len(interfaces)} total):") for iface in interfaces: status = "UP" if iface.get('running') == 'true' else "DOWN" print(f" {iface['name']:20s} {iface['type']:15s} [{status}]") # IP-адреса addresses = api.get("ip/address") print(f"\nIP Addresses ({len(addresses)}):") for addr in addresses: print(f" {addr['address']:20s} -> {addr['interface']}") # DHCP-лизы try: leases = api.get("ip/dhcp-server/lease") active = [l for l in leases if l.get('status') == 'bound'] print(f"\nDHCP Leases: {len(active)} active / {len(leases)} total") except Exception: print("\nDHCP: not configured") # Firewall try: rules = api.get("ip/firewall/filter") print(f"\nFirewall Rules: {len(rules)} in filter") except Exception: pass if __name__ == "__main__": api = MikroTikAPI( host="192.168.88.1", username="api-monitor", password="MonitorPass!2025" ) try: monitor_router(api) except requests.exceptions.ConnectionError: print("ERROR: Cannot connect to router") except requests.exceptions.HTTPError as e: print(f"ERROR: {e.response.status_code} — {e.response.text}")
JavaScript/Node.js: управление из веб-приложения
Пример на Node.js с использованием fetch:
javascript// mikrotik-rest-client.js // Node.js 18+ (встроенный fetch) class MikroTikREST { constructor(host, username, password) { this.baseUrl = `https://${host}/rest`; this.headers = { 'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'), 'Content-Type': 'application/json', }; // Для самоподписанного сертификата в Node.js // process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; } async get(path) { const resp = await fetch(`${this.baseUrl}/${path}`, { method: 'GET', headers: this.headers, }); if (!resp.ok) throw new Error(`GET ${path}: ${resp.status} ${await resp.text()}`); return resp.json(); } async create(path, data) { const resp = await fetch(`${this.baseUrl}/${path}`, { method: 'PUT', headers: this.headers, body: JSON.stringify(data), }); if (!resp.ok) throw new Error(`PUT ${path}: ${resp.status} ${await resp.text()}`); return resp.json(); } async update(path, data) { const resp = await fetch(`${this.baseUrl}/${path}`, { method: 'PATCH', headers: this.headers, body: JSON.stringify(data), }); if (!resp.ok) throw new Error(`PATCH ${path}: ${resp.status} ${await resp.text()}`); return resp.status; } async remove(path) { const resp = await fetch(`${this.baseUrl}/${path}`, { method: 'DELETE', headers: this.headers, }); if (!resp.ok) throw new Error(`DELETE ${path}: ${resp.status} ${await resp.text()}`); return resp.status; } } // Пример использования async function main() { const router = new MikroTikREST('192.168.88.1', 'api-admin', 'AdminApiPass!2025'); // Получить identity const identity = await router.get('system/identity'); console.log('Router name:', identity.name); // Получить список интерфейсов const interfaces = await router.get('interface'); interfaces.forEach(iface => { console.log(`${iface.name} (${iface.type}) - ${iface.running === 'true' ? 'UP' : 'DOWN'}`); }); // Добавить IP-адрес const result = await router.create('ip/address', { address: '10.99.0.1/24', interface: 'ether3', comment: 'Added from Node.js', }); console.log('Created with ID:', result.ret); // Удалить добавленный адрес await router.remove(`ip/address/${result.ret}`); console.log('Address removed'); } main().catch(console.error);
Безопасность REST API
Рекомендации по безопасности:
[admin@MikroTik] ># 1. Только HTTPS — отключаем HTTP /ip/service/set www disabled=yes /ip/service/set www-ssl disabled=no # 2. Ограничиваем доступ по IP /ip/service/set www-ssl address=192.168.88.100/32,10.0.0.50/32 # 3. Отдельный пользователь с минимальными правами /user/group/add name=api-readonly \ policy=read,api,!write,!policy,!test,!ftp,!reboot,!sensitive /user/add name=api-reader group=api-readonly \ password="ReadOnlyPass!2025" \ address=192.168.88.100/32 # 4. Firewall — разрешаем HTTPS только с доверенных IP /ip/firewall/filter/add \ chain=input \ protocol=tcp \ dst-port=443 \ src-address-list=api-clients \ action=accept \ comment="Allow REST API from trusted IPs" /ip/firewall/filter/add \ chain=input \ protocol=tcp \ dst-port=443 \ action=drop \ comment="Drop REST API from other IPs" /ip/firewall/address-list/add \ list=api-clients \ address=192.168.88.100 \ comment="Monitoring server" # 5. Логирование API-доступа /system/logging/add topics=web-proxy,info action=memory
Проверка
Базовая проверка доступности
[admin@MikroTik] ># На роутере — проверяем что сервис запущен /ip/service/print where name=www-ssl # Проверяем сертификат /certificate/print where name=rest-api-cert # Проверяем пользователя /user/print where name=api-monitor # Проверяем группу и политики /user/group/print where name=api-read
С внешнего компьютера:
[admin@MikroTik] ># curl — проверка доступности # curl -k -v https://192.168.88.1/rest/system/identity -u api-monitor:MonitorPass!2025 # Ожидаемый ответ: # HTTP/1.1 200 OK # Content-Type: application/json # {"name":"MikroTik"}
Проверка CRUD-операций
[admin@MikroTik] ># Тестовая последовательность: создать → прочитать → изменить → удалить # 1. Создаём тестовый IP-адрес # curl -k -u api-admin:AdminApiPass!2025 -X PUT \ # -H "Content-Type: application/json" \ # -d '{"address":"10.255.255.1/32","interface":"lo","comment":"REST API test"}' \ # https://192.168.88.1/rest/ip/address # Ответ: {"ret":"*B"} # 2. Читаем созданный адрес # curl -k -u api-admin:AdminApiPass!2025 https://192.168.88.1/rest/ip/address/*B # 3. Изменяем комментарий # curl -k -u api-admin:AdminApiPass!2025 -X PATCH \ # -H "Content-Type: application/json" \ # -d '{"comment":"Updated via REST"}' \ # https://192.168.88.1/rest/ip/address/*B # 4. Удаляем # curl -k -u api-admin:AdminApiPass!2025 -X DELETE \ # https://192.168.88.1/rest/ip/address/*B
Мониторинг производительности API
[admin@MikroTik] ># Проверяем нагрузку на веб-сервис /system/resource/print # Смотрим активные подключения к порту 443 /ip/firewall/connection/print where dst-port=443 # Логи веб-сервера /log/print where topics~"web-proxy"
Типичные ошибки
1. Ошибка 401 Unauthorized
codeHTTP/1.1 401 Unauthorized
Причины и решения:
[admin@MikroTik] ># Проверяем что пользователь существует /user/print where name=api-monitor # Проверяем что группа имеет policy=api /user/group/print detail where name=api-read # Должно быть: policy=... api ... # Проверяем ограничение по IP /user/print detail where name=api-monitor # address= должен включать IP клиента # Проверяем что www-ssl включён /ip/service/print where name=www-ssl # disabled=no
2. Ошибка "connection refused" или "SSL handshake failed"
[admin@MikroTik] ># www-ssl отключён /ip/service/set www-ssl disabled=no # Нет сертификата /ip/service/print detail where name=www-ssl # certificate= должен быть заполнен # Генерируем и назначаем сертификат /certificate/add name=api-cert common-name=router key-size=2048 days-valid=3650 /certificate/sign api-cert /ip/service/set www-ssl certificate=api-cert
3. Ошибка 400 — неверное свойство
json{"error":400,"message":"unknown parameter","detail":"unknown parameter (line 1 column 10)"}
Имена свойств в JSON должны точно соответствовать CLI:
[admin@MikroTik] ># Неправильно: "srcAddress" (camelCase) # Правильно: "src-address" (kebab-case, как в CLI) # Проверяем доступные свойства # curl -k -u admin:pass https://192.168.88.1/rest/ip/firewall/filter # Посмотрите ключи в ответе — используйте точно такие же
4. Ошибка 404 — неверный путь
json{"error":404,"message":"Not Found"}
[admin@MikroTik] ># Путь должен точно соответствовать CLI # Неправильно: /rest/ip/addresses (множественное число) # Правильно: /rest/ip/address # Неправильно: /rest/system/resources # Правильно: /rest/system/resource # Проверяем путь в CLI /ip/address/print # если работает — REST путь: /rest/ip/address
5. CORS-ошибки при вызове из браузера
RouterOS не отдаёт CORS-заголовки. Вызов REST API напрямую из браузерного JavaScript (другой домен) не работает. Решения:
- Прокси-сервер: настройте nginx/caddy прокси с CORS-заголовками
- Backend: вызывайте REST API с серверной стороны (Node.js, Python)
- Расширение браузера: только для разработки
6. Таймаут при большом количестве данных
[admin@MikroTik] ># Если таблица маршрутизации или connection tracking огромная, # запрос может зависнуть. Используйте фильтры: # Вместо получения ВСЕХ соединений # curl ... https://router/rest/ip/firewall/connection # Фильтруйте по нужным полям # curl ... "https://router/rest/ip/firewall/connection?src-address=192.168.88.100" # curl ... "https://router/rest/interface?.proplist=name,running,type"
7. Безопасность — не используйте HTTP
[admin@MikroTik] ># НИКОГДА не используйте REST API через HTTP (порт 80) # Логин/пароль передаются в Base64 — легко перехватить # Всегда HTTPS /ip/service/set www disabled=yes /ip/service/set www-ssl disabled=no # Если используете самоподписанный сертификат в production: # 1. Импортируйте CA-сертификат на клиентские машины # 2. Или используйте Let's Encrypt (см. статью о Let's Encrypt)
8. Rate limiting — нет встроенного ограничения
RouterOS не имеет встроенного rate limiting для REST API. При большом количестве запросов роутер может перегрузиться:
[admin@MikroTik] ># Ограничиваем количество подключений через firewall /ip/firewall/filter/add \ chain=input \ protocol=tcp \ dst-port=443 \ connection-limit=10,32 \ action=drop \ comment="REST API: max 10 concurrent connections per IP" # Мониторинг нагрузки /system/resource/print /ip/firewall/connection/print count-only where dst-port=443
HTTP Client ──[HTTPS, порт 443]──> RouterOS Web Service ──> REST Handler ──> CLI Engine
│
┌──────┼──────┐
│ │ │
Config State Actions
# Проверяем текущее состояние веб-сервисов
/ip/service/print
# Включаем HTTPS (www-ssl)
/ip/service/set www-ssl disabled=no
# Отключаем HTTP (небезопасный)
/ip/service/set www disabled=yes
# Ограничиваем доступ к API по IP
/ip/service/set www-ssl address=192.168.88.0/24,10.0.0.0/8
# Проверяем порт (по умолчанию 443)
/ip/service/print where name=www-ssl
# Генерируем самоподписанный сертификат (для тестов)
/certificate/add name=rest-api-cert \
common-name=router.local \
key-size=2048 \
days-valid=3650 \
key-usage=tls-server
/certificate/sign rest-api-cert
# Назначаем сертификат веб-сервису
/ip/service/set www-ssl certificate=rest-api-cert
# Группа только для чтения (мониторинг)
/user/group/add name=api-read \
policy=read,api,winbox,test,!write,!policy,!ftp,!reboot,!sensitive \
comment="REST API read-only access"
# Группа для полного управления
/user/group/add name=api-full \
policy=read,write,api,test,!policy,!ftp \
comment="REST API full access"
# Пользователь для мониторинга (только чтение)
/user/add name=api-monitor \
group=api-read \
password="MonitorPass!2025" \
address=192.168.88.0/24 \
comment="REST API monitoring user"
# Пользователь для управления
/user/add name=api-admin \
group=api-full \
password="AdminApiPass!2025" \
address=192.168.88.100/32 \
comment="REST API admin user"
# Эти команды выполняются на внешнем компьютере, не на MikroTik
# GET — получить identity роутера
# curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/system/identity
# GET — список всех интерфейсов
# curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/interface
# GET — IP-адреса
# curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/ip/address
# GET — таблица маршрутизации
# curl -k -u api-monitor:MonitorPass!2025 https://192.168.88.1/rest/ip/route
# Все IP-адреса (эквивалент /ip/address/print)
# curl -k -u admin:pass https://192.168.88.1/rest/ip/address
# Ответ JSON:
# [
# {".id":"*1","address":"192.168.88.1/24","network":"192.168.88.0",
# "interface":"bridge","actual-interface":"bridge","disabled":"false",
# "dynamic":"false","comment":"LAN"}
# ]
# Фильтр по имени интерфейса
# curl -k -u admin:pass "https://192.168.88.1/rest/interface?name=ether1"
# Фильтр — только активные интерфейсы
# curl -k -u admin:pass "https://192.168.88.1/rest/interface?running=true"
# Фильтр по нескольким условиям
# curl -k -u admin:pass "https://192.168.88.1/rest/ip/firewall/filter?chain=input&action=drop"
# Получить конкретный элемент по .id
# curl -k -u admin:pass "https://192.168.88.1/rest/ip/address/*1"
# Свойства — выбрать конкретные поля
# curl -k -u admin:pass "https://192.168.88.1/rest/interface?.proplist=name,type,running"
# Добавить IP-адрес (эквивалент /ip/address/add)
# curl -k -u api-admin:AdminApiPass!2025 \
# -X PUT \
# -H "Content-Type: application/json" \
# -d '{"address":"10.0.0.1/24","interface":"ether2","comment":"REST API added"}' \
# https://192.168.88.1/rest/ip/address
# Ответ: {"ret":"*A"} — возвращает .id нового элемента
# Добавить firewall-правило
# curl -k -u api-admin:AdminApiPass!2025 \
# -X PUT \
# -H "Content-Type: application/json" \
# -d '{"chain":"input","protocol":"tcp","dst-port":"8291","action":"accept","comment":"Allow Winbox"}' \
# https://192.168.88.1/rest/ip/firewall/filter
# Добавить статический маршрут
# curl -k -u api-admin:AdminApiPass!2025 \
# -X PUT \
# -H "Content-Type: application/json" \
# -d '{"dst-address":"10.10.0.0/16","gateway":"192.168.88.254","comment":"Office network"}' \
# https://192.168.88.1/rest/ip/route
# Изменить comment у IP-адреса (по .id)
# curl -k -u api-admin:AdminApiPass!2025 \
# -X PATCH \
# -H "Content-Type: application/json" \
# -d '{"comment":"Updated via REST API"}' \
# https://192.168.88.1/rest/ip/address/*1
# Отключить интерфейс
# curl -k -u api-admin:AdminApiPass!2025 \
# -X PATCH \
# -H "Content-Type: application/json" \
# -d '{"disabled":"true"}' \
# https://192.168.88.1/rest/interface/ether5
# Изменить identity роутера
# curl -k -u api-admin:AdminApiPass!2025 \
# -X PATCH \
# -H "Content-Type: application/json" \
# -d '{"name":"office-router-01"}' \
# https://192.168.88.1/rest/system/identity
# Удалить IP-адрес по .id
# curl -k -u api-admin:AdminApiPass!2025 \
# -X DELETE \
# https://192.168.88.1/rest/ip/address/*A
# Удалить firewall-правило
# curl -k -u api-admin:AdminApiPass!2025 \
# -X DELETE \
# https://192.168.88.1/rest/ip/firewall/filter/*5
# Перезагрузка роутера
# curl -k -u api-admin:AdminApiPass!2025 \
# -X POST \
# https://192.168.88.1/rest/system/reboot
# Пинг хоста
# curl -k -u api-admin:AdminApiPass!2025 \
# -X POST \
# -H "Content-Type: application/json" \
# -d '{"address":"8.8.8.8","count":"4"}' \
# https://192.168.88.1/rest/ping
# Создать бэкап
# curl -k -u api-admin:AdminApiPass!2025 \
# -X POST \
# -H "Content-Type: application/json" \
# -d '{"name":"api-backup"}' \
# https://192.168.88.1/rest/system/backup/save
#### Python: мониторинг MikroTik через REST API
Полноценный скрипт мониторинга на Python:
#### JavaScript/Node.js: управление из веб-приложения
Пример на Node.js с использованием `fetch`:
#### Безопасность REST API
Рекомендации по безопасности:
### Проверка
#### Базовая проверка доступности
С внешнего компьютера:
#### Проверка CRUD-операций
#### Мониторинг производительности API
### Типичные ошибки
#### 1. Ошибка 401 Unauthorized
Причины и решения:
#### 2. Ошибка "connection refused" или "SSL handshake failed"
#### 3. Ошибка 400 — неверное свойство
Имена свойств в JSON должны точно соответствовать CLI:
#### 4. Ошибка 404 — неверный путь
#### 5. CORS-ошибки при вызове из браузера
RouterOS не отдаёт CORS-заголовки. Вызов REST API напрямую из браузерного JavaScript (другой домен) не работает. Решения:
1. **Прокси-сервер**: настройте nginx/caddy прокси с CORS-заголовками
2. **Backend**: вызывайте REST API с серверной стороны (Node.js, Python)
3. **Расширение браузера**: только для разработки
#### 6. Таймаут при большом количестве данных
#### 7. Безопасность — не используйте HTTP
#### 8. Rate limiting — нет встроенного ограничения
RouterOS не имеет встроенного rate limiting для REST API. При большом количестве запросов роутер может перегрузиться: