Files
admin/.wiki/concepts/keenetic-rci-api.md
vitya 6844c24b77 wiki(kreknin/keenetic): DNS-override через RCI API решает loopback; концепт keenetic-rci-api
KeeneticOS 5.1.3: hairpin не работает (проверено после обновления) →
статичные DNS-записи ip host git.kreknin.site/kreknin.site → 192.168.1.43
через POST /rci/ parse. Из LAN всё 200. Правила порт-форвардинга = ip.static (to-host MAC).
2026-08-12 18:46:28 +03:00

4.3 KiB
Raw Blame History

title, type, tags, related, updated
title type tags related updated
Keenetic RCI API (KeeneticOS 4.x/5.x) — как автоматизировать concept
keenetic
router
rci
api
nat
dns
hairpin
kreknin-synology
2026-08-12

Keenetic RCI API

Автоматизация KeeneticOS (проверено на Viva 5.1.3, release 5.01.C.3.0-1, stable). Новые веб-панели (Angular) закрыли старый /api/auth-digest + /api/rci/, но есть живой RCI через /rci/.

Auth (интерактивный метод, как панель)

  1. GET /auth401 + заголовки X-NDM-Challenge + X-NDM-Realm (+ кука *.kpd*).
  2. POST /auth с JSON {"login":"admin","password":ENC}, заголовок x-ndw2-interactive: 1, куки из шага 1.
    • ENC = sha256hex( CHALLENGE + md5hex( login + ":" + realm + ":" + password ) ) (lowercase hex).
    • realm — весь заголовок целиком (например Keenetic Viva, с пробелом).
  3. Дальше все запросы с кукой из шага 1 (curl -b jar). Кука живёт ~5 мин (Max-Age=300) — перед серией запросов перелогинься.

Чтение (GET, кука)

  • GET /rci/show/version — версия OS
  • GET /rci/show/interface — интерфейсы; GET /rci/show/sc/interface/<id> — конфиг интерфейса
  • GET /rci/show/sc/ip — конфиг ip: route, dhcp, dhcp/host, static (!!), nat (только список интерфейсов), http, conntrack
  • GET /rci/show/ip/nat — ТЕКУЩИЕ NAT-сессии (не правила)
  • GET /rci/show/ip/hotspot — устройства (known hosts)

Правила переадресации (порт-форвардинг) в 5.x лежат в ip.static (!!, не nat):

{ "interface": "GigabitEthernet1", "protocol": "tcp", "port": "443",
  "to-port": "4443", "to-host": "22:06:7c:20:00:43", "comment": "gitea-https" }

to-host = MAC-адрес целевого устройства, to-port = внутренний порт (опционально, если ≠ внешнему).

Запись — CLI-parser (POST, кука)

POST /rci/ телом массивом [{"parse":"<cli-команда>"}, …] — как в командной строке Keenetic. В конце обязательно {"parse":"save"}.

curl -b $JAR -H 'Content-Type: application/json' -X POST http://192.168.1.1/rci/ \
  -d '[{"parse":"ip host git.kreknin.site 192.168.1.43"},
       {"parse":"ip host kreknin.site 192.168.1.43"},
       {"parse":"save"}]'

Полезные команды:

  • ip host <domain> <ip> — статичная DNS-запись (hosts override); no ip host <domain> — удалить
  • save — сохранить конфиг (обязательно в конце батча)
  • (для NAT-правил в 5.x — разбираться отдельно; в 5.x GUI их кладёт в ip.static)

NAT loopback (hairpin)

Keenetic (Viva, 5.1.3) hairpin НЕ работает (проверено: из LAN внешний адрес не открывается, даже после обновления OS; провайдер не виноват — WAN IP белый 195.19.90.188). Рабочее решение — DNS-override на роутере (записи host выше): клиенты LAN резолвят git.kreknin.site192.168.1.43 напрямую. Годится для любого числа сервисов (общий traefik).

Gotchas

  • Старый /api/auth (digest) и /api/rci/* на новых прошивках не работают (отдают SPA). Путь RCI — /rci/ без /api/.
  • Кука в curl-куки-файле начинается с #HttpOnly_ — не фильтруй grep -v '^#', если хочешь её увидеть.
  • POST /rci/ с {"path": ...} (не массивом) — работает, но для чтения; для записи нужен массив parse-команд.
  • Примеры кода: gist ancientGlider/e72cdaa2…, noksa/gokeenapi (Go, CLI: routes/DNS-records/DNS-routing/WireGuard).