Pular para o conteúdo

API de configuração de rede

Os endpoints /network gerenciam a rede própria do DTVSOL Super Router: portas físicas, bonds, endereços, VLANs, rotas padrão e estáticas. A configuração armazenada fica no banco de dados do roteador (o documento network); o dtvsold gera a partir dela um único arquivo netplan (/etc/netplan/90-dtvsol.yaml). São as chamadas que a aba Settings do monitor usa.

Autenticação, formato de erro e códigos de status estão descritos na visão geral da API.

Toda requisição é registrada no log com quem a fez. Os corpos POST podem trazer um campo opcional by: o nome do usuário do monitor (letras, dígitos e _ . @ -, no máximo 64 caracteres). O log então mostra monitor <by> (api <caller-ip>); sem ele, api <caller-ip>.

  • Leia primeiro. GET /network retorna uma version (um hash curto do documento de rede armazenado).
  • Planeje (simulação). POST /network/plan com as alterações e essa version diz o que mudaria, mostra o diff do netplan e lista tudo o que impede a alteração. Nada é tocado.
  • Aplique. POST /network/apply salva o novo documento, salva uma versão da configuração, faz backup do diretório do netplan, grava o arquivo netplan, verifica-o com netplan generate e executa netplan apply. Em seguida arma um temporizador de rollback de 120 segundos.
  • Confirme ou reverta. Se POST /network/confirm não chegar em até 120 s, o backup é restaurado e o documento armazenado volta ao anterior. POST /network/rollback faz isso imediatamente. O estado pendente sobrevive a um reboot: um roteador desligado e religado enquanto um apply aguarda é revertido quando o daemon inicia.
  • Versão desatualizada → 409. Se o documento armazenado mudou desde que você o leu (outro administrador, a CLI), plan e apply respondem 409 com "the network configuration changed since the page read it: read it again" e a version atual. apply exige version; plan só a verifica quando você a envia.
  • Um apply por vez. Enquanto um apply aguarda sua confirmação, outro apply responde 409 ("a change is waiting for its confirm (N s left): confirm or roll it back first").
  • Proteção contra perda de acesso. Alterações que removeriam o endereço de uma sessão SSH, o endereço de escuta da API ou (quando você o envia como local) o endereço pelo qual o chamador chegou são recusadas.

As operações de VLAN, endereço e proteção (vlan-*, ip-*, protect-*, pf-*, f2b-unban, antispoof-*, cgnat-set) têm efeito imediato. Não são cobertas pelo temporizador de rollback e não verificam version; em vez disso, tudo o que poderia deixar o roteador inacessível é recusado antes de qualquer execução (409 com uma lista refused).

A configuração de rede armazenada e o kernel lado a lado: cada interface como o kernel a tem, cada endereço e de onde ele vem, as VLANs de serviço, as rotas padrão e estáticas, as diferenças entre configuração e kernel (drift) e qualquer apply aguardando confirmação. Somente leitura.

Janela do 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
}

Observações:

  • interfaces[].kind é port, bond, vlan, ifb, bmc (um link USB de gerenciamento do servidor, não uma porta do roteador) ou other. owner diz qual parte do DTVSOL a criou: network, vlans, services, shaper, ou "" para tudo o que o DTVSOL não criou.
  • addresses[].source é onde o endereço está configurado; kernel significa que ele está ativo, mas não configurado em lugar nenhum.
  • pending é null, ou {"deadline": <unix time>, "left_s": <seconds>} enquanto um apply aguarda sua confirmação.
  • managed é false quando ainda não há configuração de rede armazenada (dtvsol netcfg import --save a cria).
  • Status 500 com {"ok": false, "error": …} quando o estado do kernel não pode ser lido.

Simulação de uma alteração de porta/bond: as alterações em palavras, o relatório e o diff do netplan, o que a impede e quais endereços desapareceriam. Nada é alterado.

Nome Em Tipo Observações
version body string Opcional aqui; se enviada e desatualizada → 409.
ports body object name → {up, mtu, remove}. Apenas os campos que mudam.
bonds body object name → {members, mode, params, mtu}. Apenas os campos que mudam.
local body string Opcional: o endereço IP pelo qual o chamador chegou ao roteador; alterações que o removam são recusadas.
by body string Opcional: nome do usuário do monitor para o log.

Regras dos campos:

  • up: true/false. mtu: 576–9216, ou null para o padrão.
  • remove: true deixa de gerenciar uma porta (ela sai da configuração). Recusado enquanto a porta for membro de um bond, tiver endereços ou tiver VLANs sobre ela.
  • members: lista de portas configuradas, pelo menos uma; um membro não pode estar em outro bond, ter endereços nem ter VLANs.
  • mode: 802.3ad, active-backup, balance-rr, balance-xor, balance-tlb, balance-alb, broadcast.
  • params: apenas lacp-rate (slow|fast, somente no modo 802.3ad), transmit-hash-policy (layer2, layer2+3, layer3+4, encap2+3, encap3+4) e mii-monitor-interval (0–10000); null volta um parâmetro ao seu padrão.
Janela do 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
}

Erros: 400 com {"ok": false, "error": "…", "problems": [...]} para campos inválidos, para "nothing changes" ou quando não há configuração de rede armazenada; 409 para uma version desatualizada.

Aplica uma alteração de porta/bond. Mesmo corpo que plan, mas version é obrigatória. A alteração é validada novamente; se algo a impedir, nada é aplicado (400, cada motivo com o prefixo refused:). Em caso de sucesso o novo documento é salvo, uma versão da configuração é salva, é feito backup do diretório do netplan e o temporizador de rollback é armado.

Nome Em Tipo Observações
version body string Obrigatória; deve coincidir com a versão atual, senão 409.
ports body object Como em plan.
bonds body object Como em plan.
local body string Opcional: o endereço do chamador a proteger.
by body string Opcional: nome do usuário do monitor para o log.
Janela do 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 é um horário Unix. Erros: 400 (inválido, nada muda, recusado), 409 (version desatualizada, ou outro apply aguardando confirmação), 500 se o próprio apply falhou — os arquivos netplan são restaurados e o documento armazenado volta ao anterior ("the apply failed; the configuration is as it was").

Nenhum campo no corpo é necessário (by é opcional).

Janela do 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 com ok: false quando nenhum apply está aguardando ("no apply is waiting for a confirm").

Desfaz imediatamente o apply em espera, sem esperar o temporizador.

Janela do 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 com ok: false quando nada está aguardando ("no apply is waiting: nothing to roll back") ou o rollback falhou.

Para todas as operações de VLAN, exceto vlan-add, a VLAN precisa existir na configuração; caso contrário, 404 (no VLAN "…" in the configuration).

Desativar ou excluir é recusado (409) quando: uma rota padrão (ativa ou configurada) sai pela VLAN; a VLAN tem o endereço de uma sessão SSH, o endereço de escuta da API ou o endereço local do chamador; ou outras interfaces rodam sobre ela.

O que desativar ou excluir uma VLAN recusaria e o que derrubaria. Não altera nada.

Nome Em Tipo Observações
name body string Nome da interface VLAN, p. ex. vlan100.
action body string delete, ou qualquer outro valor para uma verificação de desativação.
local body string Opcional: o endereço do chamador a proteger.
Janela do 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"
]
}

O mesmo que POST /vlans (veja VLANs, IP e rotas).

Nome Em Tipo Observações
parent body string Interface pai, p. ex. bond0.
vlan_id body integer 1–4094.
protocol body string 802.1ad para QinQ; qualquer outro valor é 802.1Q.
ip body string Endereço/prefixo IPv4 opcional.
ipv6 body string Endereço/prefixo IPv6 opcional.
label body string Rótulo opcional.
serve body boolean false para um link simples (sem DHCP/net6/PD). Padrão true.
Janela do 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": ""
}

O status HTTP é 200 em caso de sucesso; em caso de falha, é o código do erro subjacente (400–599).

Nome Em Tipo Observações
name body string Nome da interface VLAN.
reason body string Motivo opcional, guardado com a VLAN.
local body string Opcional: o endereço do chamador a proteger.
Janela do 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 quando recusado (veja acima).

Nome Em Tipo Observações
name body string Nome da interface VLAN.
Janela do 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"}
Nome Em Tipo Observações
name body string Nome da interface VLAN.
local body string Opcional: o endereço do chamador a proteger.
Janela do 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 quando recusado (veja acima). Execute antes vlan-check com "action":"delete" para ver o impacto.

Uma alteração de endereço é recusada (409) quando a interface é uma VLAN de serviço (seus endereços pertencem aos serviços), quando o endereço foi concedido por DHCP em vez de configurado, quando é o endereço de uma sessão SSH, da API ou o endereço local do chamador, ou quando o gateway da rota padrão é alcançado por ele. Uma adição é recusada apenas para uma VLAN de serviço; uma exclusão, em qualquer desses casos.

O que excluir um endereço recusaria e o que afetaria. Não altera nada.

Nome Em Tipo Observações
iface body string Nome da interface, p. ex. vlan100.
ip body string Endereço com prefixo, p. ex. 100.64.0.1/22.
local body string Opcional: o endereço do chamador a proteger.
Janela do 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"
]
}

O mesmo que POST /ip (veja VLANs, IP e rotas).

Nome Em Tipo Observações
iface body string Porta, bond ou VLAN.
ip body string Endereço com prefixo.
Janela do 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}

Status HTTP 200 em caso de sucesso; 409 para uma VLAN de serviço.

Nome Em Tipo Observações
iface body string Nome da interface.
ip body string Endereço com prefixo.
local body string Opcional: o endereço do chamador a proteger.
Janela do 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 quando recusado (veja acima).

Estes endpoints chamam as mesmas funções que /protect, /pf, /fail2ban, /antispoof e /cgnat (veja Proteção e CGNAT e anti-spoofing); somente os campos listados são aceitos. O status HTTP é o da função subjacente (por exemplo, 201 para uma adição).

Nome Em Tipo Observações
network body string Endereço ou CIDR, p. ex. XXX.XXX.XXX.0/24.
comment body string Opcional.
Janela do 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 rede inválida, 409 já permitida.

Recusado (409) para 127.0.0.1 (sempre permitido) e quando o próprio endereço do chamador (client) é permitido apenas por esta entrada — removê-la deixaria o chamador sem acesso.

Nome Em Tipo Observações
network body string A entrada a remover.
client body string Opcional: o endereço IP do chamador, para a verificação de perda de acesso.
Janela do 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 quando a entrada não existe.

Nome Em Tipo Observações
proto body string tcp (padrão) ou udp.
public_ip body string IPv4 público opcional; vazio significa qualquer.
public_port body integer 1–65535.
client_ip body string Endereço IPv4 interno.
client_port body integer 1–65535.
comment body string Opcional.
Janela do 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 inválido, 409 já existe um redirecionamento para esse proto/public_ip:port.

Nome Em Tipo Observações
proto body string tcp (padrão) ou udp.
public_ip body string Como foi adicionado (vazio para qualquer).
public_port body integer Como foi adicionado.
Janela do 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 quando nenhum redirecionamento corresponde.

Nome Em Tipo Observações
ip body string O endereço bloqueado.
Janela do 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 inválido, 500 quando o desbloqueio falhou.

Somente enabled, mode, log e exempt são repassados; pelo menos um é obrigatório.

Nome Em Tipo Observações
enabled body boolean Liga ou desliga o anti-spoofing.
mode body string strict ou dynamic.
log body boolean Registra no log os pacotes descartados.
exempt body array Redes (CIDR) nunca verificadas.
Janela do 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 quando não há nada a definir, ou para um booleano, modo ou rede isenta inválidos.

Nome Em Tipo Observações
iface body string Interface VLAN, p. ex. vlan100.
mode body string strict, dynamic, off ou default (segue o modo global).
Janela do 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 nome de interface ou modo inválido.

Somente os campos abaixo são repassados.

Nome Em Tipo Observações
enabled body boolean Ativar exige uma iface WAN válida e um pool não vazio.
iface body string Interface WAN.
pool body array/string Pool de IPv4 públicos.
port_min body integer Padrão 1024.
port_max body integer Padrão 65535.
block_size body integer Portas por assinante; padrão 2048.
exempt body array Redes (CIDR) não traduzidas.
Janela do 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 ao ativar sem uma interface WAN ou pool válidos, ou com uma rede isenta inválida.

Os endpoints /network não têm forma /api?action=. As operações subjacentes também estão disponíveis por seus próprios recursos REST (/vlans, /ip, /protect, /pf, /fail2ban, /antispoof, /cgnat) e suas formas na API de ações, documentadas nessas páginas. O equivalente na CLI de apply/confirm/rollback é dtvsol netcfg apply | confirm | rollback.

Este site foi escrito com a ajuda de IA e revisado pela nossa equipe.