Skip to content

Хосты плагинов: MikroTik и другие устройства ​

Не всё, чем нужно управлять, — Linux с агентом nkt. Роутер MikroTik, Windows-сервер, облачная ВМ: у них нет агента, зато есть API или SSH. Хост плагина — такое устройство в списке хостов nkt: читает его и управляет им плагин, а хаб даёт всё остальное — группы, пределы токенов, оповещения, «Мониторинг», сценарии, MCP, экспорт.

Плагины: MikroTik (RouterOS 7) — README; connector — устройства по профилям без своего кода (macOS, FreeBSD, OpenWrt, Linux без агента, Keenetic, принтеры и коммутаторы по SNMP) — ниже; Windows — через встроенный OpenSSH и PowerShell, без WinRM: находки (обновления, Defender, брандмауэр, RDP без NLA, SMBv1, BitLocker), службы, установка обновлений, команды PowerShell — README; ВМ Yandex Cloud — плагин Yandex Cloud; Home Assistant — одним устройством через REST API: недоступные устройства, разряженные батареи, обновления, резервные копии, сценарии и вызов служб — README.

Добавить устройство ​

  1. Поставьте плагин: «О системе» → «Плагины» → «Установить на хост» → MikroTik — на машину хаба или любой хост, откуда видны устройства.
  2. «Хосты» → «Добавить устройство» → тип → поля (адрес, пользователь, пароль…) → «Проверить» → «Добавить». Имя можно не писать — возьмётся с устройства.

Добавить устройство

  • Учётки хранит хаб, зашифрованными мастер-ключом, как SSH-ключи хостов, и передаёт плагину в каждом вызове. Пароль никому не показывается — в карточке только «задан»; не попадает ни в журнал действий, ни в параметры заданий.
  • Свой сертификат устройства (у роутеров обычно так): отпечаток запоминается при «Проверить» и сверяется при каждом подключении — как ключ SSH хоста.

Что видно и что можно ​

Строка в списке хостов — как у всех: состояние, находки, адрес, «виден». «Открыть» — панель устройства с разделами, которые есть у его типа:

РазделЧто
Составмодель, версия, интерфейсы и адреса, порты служб и откуда открыты, соседи по сети, таблицы типа (у MikroTik — маршруты, firewall, DHCP)
Метрикисейчас; хаб опрашивает устройство раз в минуту — история в «Мониторинге» вместе с остальными хостами
Находкичто не так (обновления, открытые наружу службы…) с подсказкой, как исправить; критичные — в оповещения, как у хостов с агентом
Конфигурацияхаб читает её раз в час и хранит 30 версий: изменилась на устройстве — новая версия и дифф, кто бы ни менял
Действияперезагрузка, обновление и прочее, что объявил тип; с подтверждением и сухим прогоном
Командыкоманда на языке устройства (RouterOS, PowerShell) — с подтверждением, в журнал действий
Учёткисменить логин и пароль (пусто — прежний), с «Проверить» и диффом

Устройство: состав

Устройство: дифф конфигурации

Windows: находки

Смотреть может любой, кто видит хост (и токен чтения в пределах его хостов); действия, команды и учётки — администратор или токен «по правам» с действием «плагин ИМЯ». Убрать устройство из nkt — на самом устройстве ничего не меняет.

Windows: вход, брандмауэр, виртуальные машины ​

Пользователь. Локальное имя — то, что после «\» в whoami. Для учётной записи Microsoft (name@outlook.com) в поле пишется тоже локальное имя, не почта (обычно как папка в C:\Users), а пароль — от учётной записи, не PIN Windows Hello. Если в Windows включён вход только через Windows Hello, вход паролем по SSH может не пройти — тогда ключ:

powershell
Add-Content C:\ProgramData\ssh\administrators_authorized_keys "ssh-ed25519 AAAA… nkt"
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant "*S-1-5-32-544:F" /grant "*S-1-5-18:F"

Без icacls sshd файл молча не читает; SID вместо названий групп — на русской Windows группа называется «Администраторы». Закрытый ключ — в поле «Закрытый ключ SSH», пароль пустой. (В RDP, наоборот, вход учётной записью Microsoft — почтой.)

Брандмауэр. Сеть ВМ или новая сеть Windows обычно «Общедоступная», а правило SSH может быть включено только для частных сетей:

powershell
Set-NetFirewallRule -Name OpenSSH-Server-In-TCP -Enabled True -Profile Any

Проверять доступность — портом (nc -zv -w 5 АДРЕС 22), не ping: на ping Windows по умолчанию не отвечает.

Windows в виртуальной машине. Плагин ставится на хост, с которого виден адрес Windows, — и это не всегда хост, где работает ВМ. Тип сети ВМ: virsh domiflist ВМ (колонка Type).

Сеть ВМКто видит WindowsКуда ставить плагин
macvtap (direct)вся сеть, кроме самого хоста KVMхаб или любой другой хост этой сети, не хост KVM
мост Linux (bridge, br0)все, и хост KVMхост KVM или любой хост сети
NAT default или изолированная (network)только хост KVMтолько хост KVM
VirtualBox NAT с пробросом портахост ВМхост ВМ, адрес 127.0.0.1:ПОРТ

macvtap — ограничение Linux, а не настройка: хост не обменивается пакетами со своими ВМ на macvtap, и брандмауэр тут ни при чём. Беспроводной адаптер в мост обычно не включить — точка доступа не пропускает чужие MAC.

Сценарии и MCP ​

Команда сценария on ХОСТ run "КОМАНДА" — или блок до end:

on router-office run "/ip dns cache flush"
on router-office run
/ip firewall address-list add list=blocked address=198.51.100.7
/ip firewall address-list print where list=blocked
end

«Проверить» отдаёт команду плагину на разбор, сухой прогон — плагин отвечает, что выполнил бы. Хосту плагина — только run (агента nkt у него нет), хосту с агентом — run нельзя.

MCP: list_hosts показывает и хосты плагинов (kind: plugin), а device_snapshot, device_findings, device_config (чтение), device_action и device_exec (администратор) — их разделы.

Connector: устройства по профилям ​

Плагин connector — типы устройств без своего кода: каждый тип — профиль JSON. Встроенные: Linux без агента, macOS, FreeBSD, OpenWrt (SSH), Keenetic (HTTP), принтер и коммутатор (SNMP v2c), ИБП (SNMP — UPS-MIB и APC PowerNet; NUT), IP-камеры и регистраторы (ONVIF; диски регистраторов Hikvision и Dahua) — README.

OpenWrt (с connector 1.1.0): Wi-Fi — сети и шифрование, клиенты с уровнем сигнала; DHCP — выданные и закреплённые адреса; зоны firewall и проброс портов; пакеты с обновлениями (opkg, на OpenWrt 24+ — apk); температура. Находки: зона wan пускает всё, из wan открыт SSH или веб-интерфейс, открытая сеть, WEP, WPA1 или смешанный режим, TKIP, WPS, проброс портов, root без пароля, SSH по паролю, /overlay заполнен, ветка старше 23.05. Действия: перезагрузка, Wi-Fi, служба, обновление пакета (в фоне), резервная копия на роутер. Ключи Wi-Fi, WireGuard и прочие секреты в uci export — под ***: история конфигураций хаба их не хранит. Версии, сохранённые до 1.1.0, ключи ещё содержат — чтобы их не было, удалите устройство из хаба и добавьте снова (история уйдёт вместе с ним). Свои — раздел плагина «Профили» (правка с диффом и историей в хабе).

Профили connector

Правка профиля

Профиль:

json
{"id": "my-nas", "title": {"ru": "Мой NAS", "en": "My NAS"}, "transport": "ssh",
 "hint": "что включить на устройстве",
 "info": {"name": {"cmd": "hostname", "parse": [{"trim": 1}]},
          "version": {"cmd": "cat /etc/os-release", "parse": [{"kv": "="}, {"key": "VERSION_ID"}]}},
 "snapshot": {"packages": {"cmd": "opkg list-installed", "parse": [{"each": "^(?P<name>\\S+) - (?P<version>\\S+)"}]}},
 "metrics": {"cpu_pct": {"cmd": "top -bn1", "parse": [{"regex": "(\\d+)% idle"}, {"rev": 100}]}},
 "findings": [{"id": "disk", "severity": "warning", "title": "Диск заполнен на {value}%",
               "value": {"cmd": "df -P / | awk 'NR==2{print $5+0}'", "parse": [{"num": 1}]}, "if": {"gt": 90}}],
 "config": {"cmd": "uci export"},
 "actions": [{"op": "reboot", "title": "Перезагрузить", "cmd": "reboot", "danger": true, "disconnects": true}]}
  • Связь (transport): ssh — источник {"cmd": "…"} (команда на устройстве; считать можно и в ней — awk, sed); http — {"get": "/путь"} (auth: basic, bearer, keenetic, digest); snmp — {"oid": "…"} и {"table": {"столбец": "OID"}} (обход, строки по индексу); nut — {"nut": "vars"} (все переменные ИБП, поле формы «Имя ИБП»); onvif — {"onvif": "info" | "time" | "streams" | "config"} (пароль — дайджестом WS-Security) и {"get": …} с HTTP digest для API производителя. Ещё {"const": значение}, {"conn": "поле учёток"}, {"any": [источник, …]} (первое непустое: UPS-MIB или APC), {"fields": [[название, источник], …]} (таблица «параметр — значение»). "optional": true у источника — API, которого у устройства может не быть: не ответило — поле пустое, а не ошибка вызова.
  • Разбор (parse, по порядку): json (путь a.b.0, a[].b), kv (ключ=значение построчно), key, regex (первое совпадение; именованные группы — объект), each (регулярное выражение на каждую строку → строки-объекты), lines (пропустить N строк), cols (столбцы по пробелам), num (число × множитель), rev (X − число), pick (переименовать поля строк), items (объект → строки), filter (поле — путь a.b), pct, join, count, first, trim, mask (регулярное выражение с группой v — она заменяется на ***), xml (XML → объект, атрибуты — @имя, путь как у json), list (одно значение → список), map (замена значений по таблице), dahua (ответ CGI дисков Dahua).
  • Куда: info (name, os, version, model, serial, arch, firmware, uptime_s), snapshot (mem_total, cpu, interfaces, services, packages, ports, users, neighbors, disks — строки с полями общей модели), extra (свои таблицы), metrics (cpu_pct, mem_used, mem_total, disk_used, disk_size, temp_c, uptime_s, net — строки name/rx/tx), findings (if: gt, lt, ge, le, eq, ne, contains, empty, nonempty, prefix, in, nin, word — слово целиком, как OB в статусе NUT; для строк — field), config, actions (cmd, post, instcmd — команда NUT, onvif — SystemReboot; поля формы подставляются в кавычках), exec (у ssh — команды sh), icon — значок типа в списке хостов (ups, camera…; см. ниже).

Неудачный разбор поля — поле пустое, а не ошибка: один профиль подходит к разным версиям устройства.

Свой тип устройств (для авторов плагинов) ​

Плагин объявляет в манифесте provides: ["hosts"] и host_types:

json
{"provides": ["hosts"],
 "host_types": [{
   "id": "routeros", "title": "MikroTik RouterOS", "hint": "что включить на устройстве",
   "fields": [{"name": "address", "title": "Адрес", "required": true},
              {"name": "password", "title": "Пароль", "type": "password", "required": true},
              {"name": "fingerprint", "title": "Отпечаток"}],
   "sections": ["overview", "metrics", "findings", "config", "actions", "exec"],
   "actions": [{"title": "Перезагрузить", "op": "reboot", "confirm": "Точно?", "danger": true}],
   "exec": "routeros"}]}

Поле address обязательно; type: password — секрет (хаб его не показывает); поле fingerprint хаб заполняет тем, что вернула проверка. icon (с nkt 1.16.1, необязательно) — значок типа в списке хостов: mikrotik, openwrt, macos, windows, keenetic, yandexcloud, homeassistant, printer, switch, ups, camera, device или значок ОС (debian, freebsd…); незнакомый хабу — общий «устройство». Хаб вызывает служебные операции с args: {type, conn, …} (conn — поля формы):

ОперацияОтвет
_host_checkresult: name, os, version, model, serial, firmware, uptime_s, fingerprint
_host_snapshotresult: info, cpu, mem_total, disks, interfaces, services, packages, ports, users, neighbors, extra (виды-таблицы)
_host_metricsresult: cpu_pct, mem_used, mem_total, disk_used, disk_size, temp_c, uptime_s, net ({интерфейс: {rx, tx}} — байты с начала работы)
_host_findingsresult.findings: id, severity (critical / warning / info), title, detail, fix
_host_actionaction, args, dry_run → text
_host_configresult.text (без меняющихся строк — времени выгрузки)
_host_execcommand, check (только разобрать), dry_run → text

Образец — examples/mikrotik/deploy/nkt-plugin.py и его тест на поддельном устройстве.

Экспорт и импорт ​

Хосты плагинов переносятся экспортом хаба вместе с группой, плагином и типом; учётки перешифровываются ключом хаба-получателя. Версии конфигурации не переносятся — новый хаб соберёт их опросом.