IPsec#
2 operations. Roles, error format and pagination are common to the whole API — see the REST API overview.
Authentication
Use a named bearer token. Every endpoint except POST /api/v1/auth/login,
POST /api/v1/auth/enrol and GET /api/v1/system/health requires one. A super-user creates a
token with POST /api/v1/auth/tokens; the plaintext (bngtok_…) is returned exactly once at
creation and only a SHA-256 hash is stored on the appliance, so a lost token is replaced rather
than recovered. Send it on every request:
Each token carries a fixed role (read-only, operator or super-user) and is exempt from CSRF
checks. This is the single credential you need for scripts, integrations and monitoring.
Accounts and tokens share one identity model with the appliance CLI (login.users). Repeated
authentication failures lock the account/source-IP pair out temporarily (HTTP 423 on login).
Session cookies (bundled web UI only)
The appliance also accepts an interactive session cookie, which is how the bundled web UI authenticates. It is documented for completeness — API clients should not use it. It is bound to a login session and obliges the caller to manage a CSRF token, neither of which suits automation.
POST /api/v1/auth/login with username + password (and a TOTP code when enrolled) sets the
bng_session cookie and returns a csrfToken (also available from GET /api/v1/auth/whoami).
Cookie-authenticated mutating requests (anything other than GET/HEAD/OPTIONS) must also send
that value in the X-CSRF-Token header or they are rejected with 403.
One endpoint refuses the cookie outright: GET /api/v1/metrics, the Prometheus scrape, accepts a
bearer token only, so that a scraper can never keep a login session alive.
NetavoBNG Management API v1#
IPsec#
GET /api/v1/ipsec#
IPsec peers and their security associations.
Description
One row per configured peer with its IKE SA state, rekey timers and child (ESP)
SAs including byte/packet counters and traffic selectors — the API equivalent of
swanctl --list-sas, joined with ipsec.peers so a configured peer with no SA still
appears (state DOWN). reachable: false means strongSwan could not be queried and every
state reads UNKNOWN. lastError is the manager's last apply/load failure. A peer with
configured: false is an SA whose connection has been deleted but not yet torn down.
Fleet-proxyable.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
bearerToken |
header | string | N/A | No | Named API token — the recommended credential for automation. See Authentication in the API overview. |
Responses
{
"enabled": true,
"reachable": true,
"lastError": null,
"establishedCount": 1,
"peers": [
{
"name": "partner-l2tp",
"configured": true,
"state": "ESTABLISHED",
"configuredRemote": "46.247.38.12",
"localHost": "45.84.200.69",
"remoteHost": "46.247.38.12",
"localId": "45.84.200.69",
"remoteId": "46.247.38.12",
"ikeVersion": "IKEv2",
"establishedSeconds": 4514,
"rekeyInSeconds": 9813,
"proposal": "AES_CBC-256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048",
"children": [
{
"name": "l2tp",
"state": "INSTALLED",
"mode": "TUNNEL-in-UDP",
"espProposal": "AES_CBC-256/HMAC_SHA2_256_128",
"installedSeconds": 1418,
"rekeyInSeconds": 1850,
"expiresInSeconds": 2542,
"inBytes": 10520,
"inPackets": 213,
"outBytes": 9002,
"outPackets": 215,
"localTs": [
"10.200.0.0/29"
],
"remoteTs": [
"10.200.1.1/32"
]
}
]
}
]
}
Schema of the response body
{
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "ipsec.enabled in the box configuration."
},
"reachable": {
"type": "boolean",
"description": "False when strongSwan could not be queried; peers are then configuration only."
},
"lastError": {
"type": "string",
"description": "The manager's last apply/load failure, or null when everything is current.",
"nullable": true
},
"peers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IpsecPeerStatus"
},
"description": "Configured peers (and any SA for a connection that is no longer configured)."
},
"establishedCount": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "Peers with an established IKE SA — the number SNMP and the dashboards want.",
"format": "int32"
}
},
"description": "GET /api/v1/ipsec — the whole IPsec picture for one box.",
"example": {
"enabled": true,
"reachable": true,
"lastError": null,
"establishedCount": 1,
"peers": [
{
"name": "partner-l2tp",
"configured": true,
"state": "ESTABLISHED",
"configuredRemote": "46.247.38.12",
"localHost": "45.84.200.69",
"remoteHost": "46.247.38.12",
"localId": "45.84.200.69",
"remoteId": "46.247.38.12",
"ikeVersion": "IKEv2",
"establishedSeconds": 4514,
"rekeyInSeconds": 9813,
"proposal": "AES_CBC-256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048",
"children": [
{
"name": "l2tp",
"state": "INSTALLED",
"mode": "TUNNEL-in-UDP",
"espProposal": "AES_CBC-256/HMAC_SHA2_256_128",
"installedSeconds": 1418,
"rekeyInSeconds": 1850,
"expiresInSeconds": 2542,
"inBytes": 10520,
"inPackets": 213,
"outBytes": 9002,
"outPackets": 215,
"localTs": [
"10.200.0.0/29"
],
"remoteTs": [
"10.200.1.1/32"
]
}
]
}
]
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"example": {
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"example": {
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
}
GET /api/v1/ipsec/peers/{name}#
One peer by name.
Description
404 when no peer of that name is configured and no SA carries it.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
bearerToken |
header | string | N/A | No | Named API token — the recommended credential for automation. See Authentication in the API overview. |
name |
path | string | No | The swanctl connection name (ipsec.peers[].name). |
Responses
{
"name": "partner-l2tp",
"configured": true,
"state": "ESTABLISHED",
"configuredRemote": "46.247.38.12",
"localHost": "45.84.200.69",
"remoteHost": "46.247.38.12",
"localId": "45.84.200.69",
"remoteId": "46.247.38.12",
"ikeVersion": "IKEv2",
"establishedSeconds": 4514,
"rekeyInSeconds": 9813,
"proposal": "AES_CBC-256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048",
"children": []
}
Schema of the response body
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The swanctl connection name (ipsec.peers[].name)."
},
"configured": {
"type": "boolean",
"description": "True when the peer is in the box configuration. False means an SA for a connection\n the configuration no longer has — normally a peer just deleted."
},
"state": {
"type": "string",
"description": "The IKE SA state (ESTABLISHED, CONNECTING, …), or \"DOWN\" when there is no SA, or\n \"UNKNOWN\" when strongSwan could not be queried."
},
"configuredRemote": {
"type": "string",
"description": "The configured remote address, even when no SA exists.",
"nullable": true
},
"localHost": {
"type": "string",
"nullable": true
},
"remoteHost": {
"type": "string",
"nullable": true
},
"localId": {
"type": "string",
"nullable": true
},
"remoteId": {
"type": "string",
"nullable": true
},
"ikeVersion": {
"type": "string",
"nullable": true
},
"establishedSeconds": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int64",
"nullable": true
},
"rekeyInSeconds": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int64",
"nullable": true
},
"proposal": {
"type": "string",
"description": "The negotiated IKE proposal, e.g. AES_CBC-256/HMAC_SHA2_256_128/…/MODP_2048.",
"nullable": true
},
"children": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IpsecChildSa"
},
"description": "The child (ESP) SAs of this peer — one per configured child, normally \"l2tp\"."
}
},
"description": "One peer: its configuration and, when strongSwan is reachable, its IKE SA.",
"example": {
"name": "partner-l2tp",
"configured": true,
"state": "ESTABLISHED",
"configuredRemote": "46.247.38.12",
"localHost": "45.84.200.69",
"remoteHost": "46.247.38.12",
"localId": "45.84.200.69",
"remoteId": "46.247.38.12",
"ikeVersion": "IKEv2",
"establishedSeconds": 4514,
"rekeyInSeconds": 9813,
"proposal": "AES_CBC-256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048",
"children": []
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"example": {
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"example": {
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"example": {
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "VRF not found",
"status": 404,
"detail": "No VRF named 'wholesale-b' is configured.",
"instance": "/api/v1/vrfs/wholesale-b"
}
}
Schemas#
IpsecChildSa#
| Name | Type | Description |
|---|---|---|
espProposal |
string | null | |
expiresInSeconds |
||
inBytes |
||
inPackets |
||
installedSeconds |
||
localTs |
Array<string> | Our side of the tunnel — must cover the box's L2TP source address (doc 46 §46.2). |
mode |
string | null | Encapsulation as strongSwan reports it, e.g. TUNNEL or TUNNEL-in-UDP. |
name |
string | |
outBytes |
||
outPackets |
||
rekeyInSeconds |
||
remoteTs |
Array<string> | The peer's selectors; the data plane diverts traffic to these for encryption. |
state |
string | INSTALLED, REKEYING, … |
IpsecPeerStatus#
| Name | Type | Description |
|---|---|---|
children |
Array<IpsecChildSa> | The child (ESP) SAs of this peer — one per configured child, normally "l2tp". |
configured |
boolean | True when the peer is in the box configuration. False means an SA for a connection the configuration no longer has — normally a peer just deleted. |
configuredRemote |
string | null | The configured remote address, even when no SA exists. |
establishedSeconds |
||
ikeVersion |
string | null | |
localHost |
string | null | |
localId |
string | null | |
name |
string | The swanctl connection name (ipsec.peers[].name). |
proposal |
string | null | The negotiated IKE proposal, e.g. AES_CBC-256/HMAC_SHA2_256_128/…/MODP_2048. |
rekeyInSeconds |
||
remoteHost |
string | null | |
remoteId |
string | null | |
state |
string | The IKE SA state (ESTABLISHED, CONNECTING, …), or "DOWN" when there is no SA, or "UNKNOWN" when strongSwan could not be queried. |
IpsecStatus#
| Name | Type | Description |
|---|---|---|
enabled |
boolean | ipsec.enabled in the box configuration. |
establishedCount |
Peers with an established IKE SA — the number SNMP and the dashboards want. | |
lastError |
string | null | The manager's last apply/load failure, or null when everything is current. |
peers |
Array<IpsecPeerStatus> | Configured peers (and any SA for a connection that is no longer configured). |
reachable |
boolean | False when strongSwan could not be queried; peers are then configuration only. |
ProblemDetails#
| Name | Type | Description |
|---|---|---|
detail |
string | null | |
instance |
string | null | |
status |
||
title |
string | null | |
type |
string | null |
Security schemes#
| Name | Type | Scheme | Description |
|---|---|---|---|
| bearerToken | http | bearer | Named API token — the recommended credential for automation. See Authentication in the API overview. |
| sessionCookie | apiKey | Interactive session cookie used by the bundled web UI. Not the integration path for API clients — use a bearer token. See Authentication in the API overview. |
Tags#
| Name | Description |
|---|---|
| IPsec |