Ir al contenido

API de configuración de red

Los endpoints /network gestionan la red propia del DTVSOL Super Router: puertos físicos, bonds, direcciones, VLAN, ruta predeterminada y rutas estáticas. La configuración almacenada reside en la base de datos del router (el documento network); dtvsold genera a partir de ella un único archivo netplan (/etc/netplan/90-dtvsol.yaml). Estas son las llamadas que usa la pestaña Settings del monitor.

La autenticación, el formato de errores y los códigos de estado se describen en la descripción general de la API.

Cada solicitud se registra junto con quién la hizo. Los cuerpos de POST pueden incluir un campo opcional by: el nombre del usuario del monitor (letras, dígitos y _ . @ -, como máximo 64 caracteres). El registro muestra entonces monitor <by> (api <caller-ip>); sin él, api <caller-ip>.

  • Primero lea. GET /network devuelve una version (un hash corto del documento de red almacenado).
  • Planifique (simulación). POST /network/plan con los cambios y esa version indica qué cambiaría, muestra el diff de netplan y enumera todo lo que impide el cambio. No se modifica nada.
  • Aplique. POST /network/apply guarda el nuevo documento, guarda una versión de configuración, respalda el directorio de netplan, escribe el archivo netplan, lo verifica con netplan generate y ejecuta netplan apply. Luego activa un temporizador de reversión de 120 segundos.
  • Confirme o revierta. Si POST /network/confirm no llega dentro de 120 s, se restaura el respaldo y el documento almacenado. POST /network/rollback hace eso de inmediato. El estado pendiente sobrevive a un reinicio: un router que se apaga y enciende mientras un apply espera se revierte cuando arranca el daemon.
  • Versión obsoleta → 409. Si el documento almacenado cambió desde que usted lo leyó (otro administrador, la CLI), plan y apply responden 409 con "the network configuration changed since the page read it: read it again" (la configuración de red cambió desde que la página la leyó: léala de nuevo) y la version actual. apply exige version; plan solo la verifica cuando usted la envía.
  • Un apply a la vez. Mientras un apply espera su confirmación, otro apply responde 409 ("a change is waiting for its confirm (N s left): confirm or roll it back first" — hay un cambio esperando confirmación; confírmelo o reviértalo primero).
  • Protección contra cortes de acceso. Se rechazan los cambios que eliminarían la dirección de una sesión SSH, la dirección de escucha de la API o (cuando usted la envía como local) la dirección por la que llegó quien hace la llamada.

Las operaciones de VLAN, direcciones y protección (vlan-*, ip-*, protect-*, pf-*, f2b-unban, antispoof-*, cgnat-set) surten efecto de inmediato. No están cubiertas por el temporizador de reversión y no verifican version; en su lugar, todo lo que podría dejar al router sin acceso se rechaza antes de ejecutar nada (409 con una lista refused).

La configuración de red almacenada y el kernel lado a lado: cada interfaz tal como la tiene el kernel, cada dirección y su origen, las VLAN de servicio, la ruta predeterminada y las rutas estáticas, las diferencias entre la configuración y el kernel (drift) y cualquier apply que esté esperando su confirmación. Solo lectura.

Ventana de terminal
curl -s http://ROUTER-IP:8880/network -H "X-API-Key: YOUR_API_KEY"
{
"ok": true,
"generated": "2026-09-28 10:15:02",
"managed": true,
"version": "3f9a1c0d2b7e4a55",
"config": {
"ports": [{"name": "eno1", "mac": "aa:bb:cc:00:00:01", "mtu": 1500, "up": true}],
"bonds": [{"name": "bond0", "members": ["eno2", "eno3"], "mode": "802.3ad",
"params": {"lacp-rate": "fast", "mii-monitor-interval": 100}}]
},
"uplinks": ["eno1"],
"interfaces": [
{"name": "eno1", "kind": "port", "mac": "aa:bb:cc:00:00:01", "mtu": 1500, "up": true,
"carrier": true, "master": null, "parent": null, "vid": null, "protocol": null,
"bond_mode": null, "speed_mbps": 10000, "driver": "ixgbe",
"addresses": ["XXX.XXX.XXX.2/24"], "configured": true, "owner": "network",
"shapes": null, "uplink": true},
{"name": "vlan100", "kind": "vlan", "parent": "bond0", "vid": 100, "protocol": "802.1Q",
"addresses": ["100.64.0.1/22"], "configured": false, "owner": "vlans", "uplink": false}
],
"addresses": [
{"iface": "eno1", "cidr": "XXX.XXX.XXX.2/24", "family": 4, "source": "network",
"configured": true, "live": true, "dynamic": false}
],
"service_vlans": [
{"iface": "v400.101", "olt": "olt-1", "pon": "0/1/0", "svlan": 400, "cvlan": 101,
"ipv4": "100.64.8.1/24", "ipv6": null}
],
"routes": {
"default_kernel": [{"to": "default", "via": "XXX.XXX.XXX.1", "dev": "eno1", "protocol": "static", "metric": null}],
"static": []
},
"drift": ["vlan vlan100: 10.2.0.1/24 configured, not live"],
"pending": null
}

Notas:

  • interfaces[].kind es port, bond, vlan, ifb, bmc (un enlace USB de administración del servidor, no un puerto del router) u other. owner indica qué parte de DTVSOL la creó: network, vlans, services, shaper, o "" para cualquier cosa que DTVSOL no haya creado.
  • addresses[].source indica dónde está configurada la dirección; kernel significa que está activa pero no configurada en ningún lugar.
  • pending es null, o {"deadline": <unix time>, "left_s": <seconds>} mientras un apply espera su confirmación.
  • managed es false cuando todavía no hay ninguna configuración de red almacenada (dtvsol netcfg import --save la crea).
  • Estado 500 con {"ok": false, "error": …} cuando no se puede leer el estado del kernel.

Simulación de un cambio de puertos/bonds: los cambios descritos en palabras, el informe y el diff de netplan, lo que lo impide, y qué direcciones desaparecerían. No se modifica nada.

Nombre En Tipo Notas
version body string Opcional aquí; si se envía y está obsoleta → 409.
ports body object name → {up, mtu, remove}. Solo los campos que cambian.
bonds body object name → {members, mode, params, mtu}. Solo los campos que cambian.
local body string Opcional: la dirección IP por la que quien llama llegó al router; se rechazan los cambios que la eliminen.
by body string Opcional: nombre del usuario del monitor para el registro.

Reglas de los campos:

  • up: true/false. mtu: 576–9216, o null para el valor predeterminado.
  • remove: true deja de gestionar un puerto (sale de la configuración). Se rechaza mientras el puerto sea miembro de un bond, tenga direcciones o tenga VLAN encima.
  • members: lista de puertos configurados, al menos uno; un miembro no puede estar en otro bond, tener direcciones ni tener VLAN.
  • mode: 802.3ad, active-backup, balance-rr, balance-xor, balance-tlb, balance-alb, broadcast.
  • params: solo lacp-rate (slow|fast, únicamente en modo 802.3ad), transmit-hash-policy (layer2, layer2+3, layer3+4, encap2+3, encap3+4) y mii-monitor-interval (0–10000); null restablece un parámetro a su valor predeterminado.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/plan \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"version":"3f9a1c0d2b7e4a55","ports":{"eno2":{"mtu":9000}},"bonds":{"bond0":{"params":{"lacp-rate":"slow"}}}}'
{
"ok": true,
"version": "3f9a1c0d2b7e4a55",
"changes": ["eno2: MTU default → 9000", "bond0: lacp-rate fast → slow"],
"report": "…the netplan file's diff and checks…",
"refused": [],
"addresses_gone": [],
"pending": false
}

Errores: 400 con {"ok": false, "error": "…", "problems": [...]} para campos no válidos, para "nothing changes" (no cambia nada), o cuando no hay ninguna configuración de red almacenada; 409 para una version obsoleta.

Aplica un cambio de puertos/bonds. El mismo cuerpo que plan, pero version es obligatoria. El cambio se valida de nuevo; si algo lo impide, no se aplica nada (400, cada motivo con el prefijo refused:). Si tiene éxito, se guarda el nuevo documento, se guarda una versión de configuración, se respalda el directorio de netplan y se activa el temporizador de reversión.

Nombre En Tipo Notas
version body string Obligatoria; debe coincidir con la versión actual, de lo contrario 409.
ports body object Igual que en plan.
bonds body object Igual que en plan.
local body string Opcional: la dirección de quien llama, que se debe proteger.
by body string Opcional: nombre del usuario del monitor para el registro.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/apply \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"version":"3f9a1c0d2b7e4a55","ports":{"eno2":{"mtu":9000}},"local":"XXX.XXX.XXX.2","by":"admin"}'
{
"ok": true,
"rc": 0,
"pending": 1790430302123,
"deadline": 1790430422,
"text": "…configuration version 42…\napplied. Confirm within 120 s: dtvsol netcfg confirm — else it is put back (…)\n",
"changes": ["eno2: MTU default → 9000"]
}

deadline es una hora Unix. Errores: 400 (no válido, no cambia nada, rechazado), 409 (version obsoleta, u otro apply esperando su confirmación), 500 si el apply en sí falló — se restauran los archivos netplan y el documento almacenado ("the apply failed; the configuration is as it was" — el apply falló; la configuración quedó como estaba).

No se necesitan campos en el cuerpo (by es opcional).

Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/confirm -H "X-API-Key: YOUR_API_KEY"
{"ok": true, "text": "confirmed: the network stays as applied (the old files: …)\n", "rc": 0}

400 con ok: false cuando no hay ningún apply en espera ("no apply is waiting for a confirm" — ningún apply espera confirmación).

Deshace el apply en espera de inmediato, en lugar de esperar al temporizador.

Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/rollback -H "X-API-Key: YOUR_API_KEY"
{"ok": true, "text": "rolled back (by hand): netplan as it was (…)\nthe network configuration is as it was before the change\n", "rc": 0}

400 con ok: false cuando no hay nada en espera ("no apply is waiting: nothing to roll back" — ningún apply en espera; nada que revertir) o la reversión falló.

Para todas las operaciones de VLAN excepto vlan-add, la VLAN debe existir en la configuración; de lo contrario, 404 (no VLAN "…" in the configuration — la VLAN no está en la configuración).

Una desactivación o eliminación se rechaza (409) cuando: una ruta predeterminada (activa o configurada) sale por la VLAN; la VLAN contiene la dirección de una sesión SSH, la dirección de escucha de la API o la dirección local de quien llama; o hay otras interfaces funcionando sobre ella.

Qué impediría desactivar o eliminar una VLAN y qué dejaría fuera de servicio. No modifica nada.

Nombre En Tipo Notas
name body string Nombre de la interfaz VLAN, p. ej. vlan100.
action body string delete, o cualquier otro valor para una verificación de desactivación.
local body string Opcional: la dirección de quien llama, que se debe proteger.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/vlan-check \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"vlan100","action":"delete"}'
{
"ok": true,
"name": "vlan100",
"refused": [],
"impact": [
"its address 100.64.0.1/22 stops",
"DHCP stops serving vlan100",
"its DHCP networks, NAT pool and port forwards are deleted with it"
]
}

Igual que POST /vlans (consulte VLAN, IP y rutas).

Nombre En Tipo Notas
parent body string Interfaz padre, p. ej. bond0.
vlan_id body integer 1–4094.
protocol body string 802.1ad para QinQ; cualquier otro valor es 802.1Q.
ip body string Dirección/prefijo IPv4 opcional.
ipv6 body string Dirección/prefijo IPv6 opcional.
label body string Etiqueta opcional.
serve body boolean false para un enlace simple (sin DHCP/net6/PD). Predeterminado true.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/vlan-add \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"parent":"bond0","vlan_id":100,"ip":"100.64.0.1/22","label":"OLT 1"}'
{
"ok": true, "code": 201,
"message": "VLAN vlan100 created on bond0 (100.64.0.1/22)",
"name": "vlan100", "parent": "bond0", "vlan_id": 100, "protocol": "802.1Q",
"ip": "100.64.0.1/22", "ipv6": ""
}

El estado HTTP es 200 si tiene éxito; si falla, es el código del error subyacente (400–599).

Nombre En Tipo Notas
name body string Nombre de la interfaz VLAN.
reason body string Motivo opcional, que se guarda con la VLAN.
local body string Opcional: la dirección de quien llama, que se debe proteger.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/vlan-disable \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"vlan100","reason":"OLT maintenance"}'
{
"ok": true, "code": 200, "message": "VLAN vlan100 disabled", "name": "vlan100",
"enabled": false, "disabled_at": "2026-09-28 10:20:00", "reason": "OLT maintenance",
"took_offline": ["…"],
"kept": "delegation range, subnet blocks, NAT pool, port forwards, routes, client reservations and addresses — all restored by: dtvsol vlan enable vlan100"
}

409 cuando se rechaza (consulte más arriba).

Nombre En Tipo Notas
name body string Nombre de la interfaz VLAN.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/vlan-enable \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"vlan100"}'
{"ok": true, "code": 200, "message": "VLAN vlan100 enabled", "name": "vlan100"}
Nombre En Tipo Notas
name body string Nombre de la interfaz VLAN.
local body string Opcional: la dirección de quien llama, que se debe proteger.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/vlan-delete \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"vlan100"}'
{"ok": true, "code": 200, "message": "VLAN vlan100 deleted", "name": "vlan100"}

409 cuando se rechaza (consulte más arriba). Ejecute primero vlan-check con "action":"delete" para ver el impacto.

Un cambio de dirección se rechaza (409) cuando la interfaz es una VLAN de servicio (sus direcciones pertenecen a los servicios), cuando la dirección fue asignada por DHCP en lugar de configurada, cuando es la dirección de una sesión SSH, de la API o la dirección local de quien llama, o cuando la puerta de enlace de la ruta predeterminada se alcanza a través de ella. Un add se rechaza solo para una VLAN de servicio; un delete, en cualquiera de estos casos.

Qué impediría eliminar una dirección y a qué afectaría. No modifica nada.

Nombre En Tipo Notas
iface body string Nombre de la interfaz, p. ej. vlan100.
ip body string Dirección con prefijo, p. ej. 100.64.0.1/22.
local body string Opcional: la dirección de quien llama, que se debe proteger.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/ip-check \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan100","ip":"100.64.0.1/22"}'
{
"ok": true,
"refused": [],
"impact": [
"the clients of vlan100 whose gateway is 100.64.0.1 lose it",
"100.64.0.1/22 is taken off vlan100 now and from its configuration"
]
}

Igual que POST /ip (consulte VLAN, IP y rutas).

Nombre En Tipo Notas
iface body string Puerto, bond o VLAN.
ip body string Dirección con prefijo.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/ip-add \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan100","ip":"100.64.4.1/24"}'
{"ok": true, "code": 201, "message": "IP 100.64.4.1/24 added to vlan100", "persisted": true}

Estado HTTP 200 si tiene éxito; 409 para una VLAN de servicio.

Nombre En Tipo Notas
iface body string Nombre de la interfaz.
ip body string Dirección con prefijo.
local body string Opcional: la dirección de quien llama, que se debe proteger.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/ip-delete \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan100","ip":"100.64.4.1/24"}'
{"ok": true, "code": 200, "message": "IP 100.64.4.1/24 removed from vlan100"}

409 cuando se rechaza (consulte más arriba).

Estas llaman a las mismas funciones que /protect, /pf, /fail2ban, /antispoof y /cgnat (consulte Protección y CGNAT y anti-spoofing); solo se aceptan los campos indicados. El estado HTTP es el de la función subyacente (por ejemplo, 201 para un add).

Nombre En Tipo Notas
network body string Dirección o CIDR, p. ej. XXX.XXX.XXX.0/24.
comment body string Opcional.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/protect-add \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"network":"XXX.XXX.XXX.0/24","comment":"NOC"}'
{"ok": true, "code": 201, "message": "Network XXX.XXX.XXX.0/24 allowed",
"networks": [{"network": "XXX.XXX.XXX.0/24", "comment": "NOC", "added": "2026-09-28 10:30:00"}]}

400 red no válida, 409 ya permitida.

Se rechaza (409) para 127.0.0.1 (siempre permitida) y cuando la dirección propia de quien llama (client) está permitida únicamente a través de esta entrada — quitarla dejaría a quien llama sin acceso.

Nombre En Tipo Notas
network body string La entrada que se quitará.
client body string Opcional: la dirección IP de quien llama, para la verificación de bloqueo de acceso.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/protect-delete \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"network":"XXX.XXX.XXX.0/24","client":"XXX.XXX.XXX.10"}'
{"ok": true, "code": 200, "message": "Network XXX.XXX.XXX.0/24 removed", "networks": []}

404 cuando la entrada no existe.

Nombre En Tipo Notas
proto body string tcp (predeterminado) o udp.
public_ip body string IPv4 pública opcional; vacío significa cualquiera.
public_port body integer 1–65535.
client_ip body string Dirección IPv4 interna.
client_port body integer 1–65535.
comment body string Opcional.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/pf-add \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"proto":"tcp","public_ip":"XXX.XXX.XXX.5","public_port":8443,"client_ip":"100.64.1.20","client_port":443}'
{"ok": true, "code": 201, "message": "Port forward added",
"forward": {"proto": "tcp", "public_ip": "XXX.XXX.XXX.5", "public_port": 8443,
"client_ip": "100.64.1.20", "client_port": 443, "comment": "", "created": "2026-09-28 10:31:00"}}

400 campo no válido, 409 ya existe una redirección para ese proto/public_ip:port.

Nombre En Tipo Notas
proto body string tcp (predeterminado) o udp.
public_ip body string Tal como se agregó (vacío para cualquiera).
public_port body integer Tal como se agregó.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/pf-delete \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"proto":"tcp","public_ip":"XXX.XXX.XXX.5","public_port":8443}'
{"ok": true, "code": 200, "message": "Port forward removed"}

404 cuando ninguna redirección coincide.

Nombre En Tipo Notas
ip body string La dirección bloqueada.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/f2b-unban \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"ip":"XXX.XXX.XXX.77"}'
{"ok": true, "code": 200, "message": "Unbanned XXX.XXX.XXX.77"}

400 IP no válida, 500 cuando el desbloqueo falló.

Solo se transmiten enabled, mode, log y exempt; se requiere al menos uno.

Nombre En Tipo Notas
enabled body boolean Activa o desactiva el anti-spoofing.
mode body string strict o dynamic.
log body boolean Registra los paquetes descartados.
exempt body array Redes (CIDR) que nunca se verifican.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/antispoof-set \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"enabled":true,"mode":"strict","log":true}'
{"ok": true, "code": 200, "message": "Anti-spoofing enabled", "apply": {"…": "…"}, "status": {"…": "…"}}

400 cuando no hay nada que establecer, o por un booleano, modo o red exenta no válidos.

Nombre En Tipo Notas
iface body string Interfaz VLAN, p. ej. vlan100.
mode body string strict, dynamic, off o default (sigue el modo global).
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/antispoof-iface \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan100","mode":"dynamic"}'
{"ok": true, "code": 200, "message": "vlan100 set to dynamic", "iface": "vlan100",
"requested": "dynamic", "effective": "dynamic", "note": null, "apply": {"…": "…"}}

400 nombre de interfaz o modo no válido.

Solo se transmiten los campos siguientes.

Nombre En Tipo Notas
enabled body boolean Para activarlo se requiere una iface WAN válida y un pool no vacío.
iface body string Interfaz WAN.
pool body array/string Pool de IPv4 públicas.
port_min body integer Predeterminado 1024.
port_max body integer Predeterminado 65535.
block_size body integer Puertos por suscriptor; predeterminado 2048.
exempt body array Redes (CIDR) que no se traducen.
Ventana de terminal
curl -s -X POST http://ROUTER-IP:8880/network/cgnat-set \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"enabled":true,"iface":"eno1","pool":["XXX.XXX.XXX.0/28"],"block_size":2048}'
{"ok": true, "code": 200, "message": "CGNAT updated", "status": {"…": "…"}}

400 cuando se activa sin una interfaz WAN o un pool válidos, o con una red exenta no válida.

Los endpoints /network no tienen forma /api?action=. Las operaciones subyacentes también están disponibles mediante sus propios recursos REST (/vlans, /ip, /protect, /pf, /fail2ban, /antispoof, /cgnat) y sus formas en la API de acciones, que se documentan en esas páginas. El equivalente en la CLI de apply/confirm/rollback es dtvsol netcfg apply | confirm | rollback.

Este sitio fue escrito con ayuda de IA y revisado por nuestro equipo.