feat(backend): add OPNsense backend (#743)
Docker / Build and Push (push) Canceled after 0s
github-pages / deploy (push) Canceled after 0s
Test / make test (push) Canceled after 0s
Docker / release (push) Canceled after 0s

Manages interfaces and peers on OPNsense through the WireGuard API in
OPNsense core, so a stock appliance needs nothing installed. OPNsense
calls a tunnel a "server" and a peer on it a "client"; those map to
PhysicalInterface and PhysicalPeer.

Reads go through searchXxx because getXxx returns select fields as
{value, selected} maps that cannot be posted back to a write. Validation
failures arrive as HTTP 200 with a "result": "failed" body, so the body
is checked and not the status code.

Firewall rules are not managed, matching the pfSense backend: a new
tunnel handshakes but carries no traffic until a pass rule exists.

Alpha, and documented as such.

Signed-off-by: clark-ja <37738506+clark-ja@users.noreply.github.com>
This commit is contained in:
Jacopo Clark
2026-09-10 22:27:17 +02:00
committed by GitHub
parent 32ef6048fb
commit 7f5786f40f
14 changed files with 2855 additions and 14 deletions
@@ -44,6 +44,9 @@ func (c *ControllerManager) init() error {
return err
}
if err := c.registerOpnsenseControllers(); err != nil {
return err
}
if err := c.registerPfsenseControllers(); err != nil {
return err
}
@@ -113,6 +116,26 @@ func (c *ControllerManager) registerPfsenseControllers() error {
return nil
}
func (c *ControllerManager) registerOpnsenseControllers() error {
for _, backendConfig := range c.cfg.Backend.Opnsense {
if backendConfig.Id == config.LocalBackendName {
slog.Warn("skipping registration of OPNsense controller with reserved ID", "id", config.LocalBackendName)
continue
}
controller, err := wgcontroller.NewOpnsenseController(c.cfg, &backendConfig)
if err != nil {
return fmt.Errorf("failed to create OPNsense controller for backend %s: %w", backendConfig.Id, err)
}
c.controllers[domain.InterfaceBackend(backendConfig.Id)] = backendInstance{
Config: backendConfig.BackendBase,
Implementation: controller,
}
}
return nil
}
func (c *ControllerManager) logRegisteredControllers() {
for backend, controller := range c.controllers {
slog.Debug("backend controller registered",