Skip to content

OPNsense

Open source firewall and router: the state of every gateway with its round-trip time and packet loss, the pf state table, interface counters and addresses, VPN tunnels, DHCP leases, the resolver, services, CARP and pending updates.

From the DumbMonit server (or its relay agent) to the device:

PortProtocolPurpose
443TCPAPI (HTTPS, default)
80TCPOnly with the HTTP protocol option

Beyond the generic charts, an OPNsense monitor shows three panels, read from what the probe stored — opening the page never queries the firewall itself:

  • WAN and gateways — the current public address of every interface that carries a gateway, then each gateway with its state in a word, its round-trip delay and its packet loss. Gateways that are down come first. This is the panel the integration exists for: on a multi-WAN firewall, the backup link takes over silently and nothing else on the network changes.
  • Traffic and state table — how many connections pf is tracking against its configured limit, then each interface with its link state, its addresses, its byte and packet counters, and its errors and drops when there are any. Then the DHCP leases, counted per server.
  • Firewall health — stopped services first, then the VPN tunnels with the number of connected peers, then CARP when the firewall is half of a pair, then the firmware (running version, what the mirror offers, packages waiting, and whether a reboot is pending), then the resolver, then the machine: uptime, load, memory, swap, network buffers, partitions and temperature sensors.

Counts only, never traffic. DumbMonit reads no firewall rule, no connection state, no client address and no host name. DHCP leases are counted, never listed; VPN sessions are counted, never named.

GET /api/routes/gateway/status writes "none" in a gateway’s status field when everything is fine — a word that on its own reads like “no information”. DumbMonit translates it to online, so the page, the series and the rules say the same thing as OPNsense’s own interface. down and force_down are the failures; loss and delay are dpinger’s warnings, and the gateway still answers.

The same call returns delay, loss and standard deviation as strings with their unit ("8.4 ms", "0.0 %"), and as "~" when the gateway has no monitor address. "~" produces one series fewer, never a zero: a gateway nobody pings does not have zero milliseconds of latency, it has none at all.

GET /api/core/firmware/status returns the result of the firewall’s last check — the one OPNsense’s own dashboard shows. DumbMonit never sends the POST form of that call, nor /api/core/firmware/check, which would send the firewall to the mirror on every measurement, from every DumbMonit installation.

A firewall that has never checked — or has just installed an update, which clears the cache — answers "status": "none", exactly as an up-to-date one does. DumbMonit tells the two apart, and until a check has run it publishes firmware_checked = 0 and nothing else: no “zero updates pending”, no “no reboot needed”. Run a check once from System → Firmware, or let the firewall’s own schedule do it.

All metrics are prefixed dumbmonit_opnsense_.

FamilyMetricsLabels
Identityversion_info (labels carry the OPNsense version, the FreeBSD version and the product line)
Machineuptime_seconds, load1/5/15, cpu_count, memory_used/total_bytes, memory_used_percent (memory includes the ZFS cache, which FreeBSD counts as used), swap_used/total_bytes, swap_used_percent (absent on a machine without swap), mbuf_used and mbuf_total (network buffer clusters in use against kern.ipc.nmbclusters), mbuf_used_percent, mbuf_failures (allocations refused since boot, a counter)
Storagedisk_used_bytes, disk_total_bytes, disk_used_percentdevice, mountpoint
Sensorstemperature_celsiussensor
Gatewaysgateway_up (0 only on down and force_down), gateway_monitored, gateway_delay_seconds, gateway_stddev_seconds, gateway_loss_percent, gateways_total, gateways_downgateway, address
Interfacesinterface_up, interface_bytes_in/out, interface_packets_in/out, interface_errors_in/out, interface_drops, interface_collisions (counters, stored raw), interface_address_info (the address of the moment, in a label)interface, device, and address for the last one
Firewallpf_states, pf_state_limit, pf_states_used_percent
DHCPdhcp_leases, dhcp_leases_activebackend (kea, isc, dnsmasq)
VPNvpn_tunnel_up, vpn_peers_total, vpn_peers_connected (WireGuard: handshake within three minutes), vpn_handshake_age_seconds (WireGuard, the most recent peer; absent while no peer has ever connected), vpn_bytes_in/out, vpn_tunnels_downkind (wireguard, openvpn, ipsec), tunnel (the WireGuard device, wg0, or the IPsec and OpenVPN description)
Resolverunbound_running, unbound_queries (a counter), unbound_cache_hit_percent
Servicesservice_running (1 or 0, one series per service the firewall lists)service
CARPcarp_enabled, carp_maintenance_mode, carp_vip_master (all absent on a firewall that is not part of a pair)interface, vhid, address
Firmwarefirmware_checked, then — only once a check has run — firmware_updates_pending, firmware_upgrade_available, firmware_reboot_required, firmware_connection_ok
Collectionup, scrape_errors, scrape_duration_seconds

Interface counters are stored raw, as counters: wrap them in rate() to get throughput. Doing it that way means a firewall reboot shows as a gap, not as a spike of several gigabytes per second.

gateway_up is 1 for a gateway that is not monitored at all, because there is nothing to say otherwise; gateway_monitored is what distinguishes the two. A gateway with no monitor address produces neither a delay nor a loss series.

A firewall that is not part of a high-availability pair has no CARP virtual address, and no CARP series at all. That is a firewall with no cluster, not a degraded cluster: no rule can fire.

WireGuard, OpenVPN, IPsec, Unbound and Kea are plugins. A firewall that does not have one answers 404, which is neither a collection error nor an authentication error: one metric fewer, and nothing in the interface.

Built-in rules that apply: Monitor unreachable, Internet gateway down, Gateway losing packets, Gateway slow, Firewall state table filling up, Firewall network buffers exhausted, VPN tunnel down, Firewall resolver stopped, Firewall core service stopped, Firewall too hot, Firewall left in CARP maintenance mode, Firewall reboot pending, Firewall updates pending. Notifications name the gateway, tunnel, service or sensor concerned.

The steps below are the ones the notice next to the form shows. The principle: a group with only the status privileges DumbMonit needs, a user that never logs in, and an API key that belongs to neither of your own accounts. This exact group was checked against every call DumbMonit makes, on OPNsense 26.1.

  1. System → Access → Groups → Add: name the group as follows.

    dumbmonit
  2. In that group, under Assigned Privileges, add the privileges listed below.

  3. System → Access → Users → Add: name the user as follows, generate a password, and make it a member of that group.

    dumbmonit
  4. Edit the user, click + under API keys, and save the downloaded file: it holds the key and the secret, shown only once.

  5. In DumbMonit, enter the firewall address (192.168.1.1 or fw.lan:8443), the key as API key and the secret as API secret.

  • Lobby: Dashboard — System, memory, disks, state table (required)
  • System: Gateways — Gateway state, delay and loss
  • Status: Interfaces — Link state and counters
  • Status: Services — Stopped services
  • System: Firmware — Pending updates and reboot
  • Interfaces: Virtual IPs: Status — CARP state
  • Services: Unbound (MVC) — Resolver
  • Services: DHCP: Kea(v4) — Leases, if you use Kea
  • Services: Dnsmasq DNS/DHCP: Settings — Leases, if you use Dnsmasq
  • VPN: WireGuard: Status — WireGuard tunnels
  • Status: OpenVPN — OpenVPN tunnels
  • Status: IPsec — IPsec tunnels
  • Diagnostics: Logs: Firewall: Live View — Only for the live firewall map option

Vendor documentation: https://docs.opnsense.org/development/how-tos/api.html

A privilege you leave out costs exactly the metrics it carries, nothing else; only Lobby: Dashboard is required. OPNsense has no read-only variant of some of them: Status: Services also allows starting and stopping a service, System: Firmware also allows starting an update, and the Unbound, Kea and Dnsmasq privileges also cover their settings. DumbMonit only ever reads, but to limit what a leaked key could do, restrict the group’s source networks to the address of the DumbMonit host, and never grant All pages.

The firewall is never asked to check for updates: DumbMonit reads the result of the check OPNsense runs on its own schedule, or that you start from System → Firmware.

Address: 192.168.1.1, fw.lan, fw.lan:8443, [fd00::1] or a full URL. The https scheme and port 443 are added if missing.

Some privileges cover more than one call. Lobby: Dashboard carries the system information, time, memory, disk, swap, network buffer and temperature endpoints and the state table; Status: Interfaces carries the interface overview with its counters and addresses. A privilege you leave out costs exactly the metrics it carries: the probe still succeeds, and scrape_errors stays at zero, because a 403 on an optional call is read as “this account may not see that”, not as a failure. Only Lobby: Dashboard is required: without it the probe cannot even read the firewall’s name and version, and reports an authentication error.

OPNsense 25.7 renamed its API paths from systemResources to system_resources. Both spellings still answer, but the privileges compare the path letter for letter: on 25.7 and later a restricted key gets 403 on the old spelling, and on 25.1 on some of the new ones. DumbMonit asks for the current spelling first and falls back to the other on a 403, so the same group works on either side of the rename.

KeyLabelDefaultHelp
schemeProtocolhttpsHTTPS fits a firewall out of the box. HTTP only if the web interface is served in clear text.
portWeb interface port443Used if the address does not give a port.
insecure_tlsAccept an unverifiable certificatefalseOPNsense ships with a self-signed certificate by default.
request_timeout_secondsTimeout per request (seconds)15Time allowed for each API call, from 1 to 120.
gatewaysWatch the gatewaystrueReads what dpinger says about each gateway: up or down, round-trip delay and packet loss.
interfacesWatch the interfacestrueReads each interface’s link state, addresses and byte, packet, error and drop counters.
firewallWatch the state tabletrueReads how many connections pf is tracking and the configured limit.
dhcpCount the DHCP leasestrueCounts the leases the firewall is handing out, whichever server it runs. Counts only.
vpnWatch the VPN tunnelstrueReads WireGuard, OpenVPN and IPsec: which tunnels exist and which ones are up.
unboundWatch the resolvertrueReads whether Unbound is answering.
servicesWatch the servicestrueReads the list of services the firewall manages and which of them are running.
carpWatch CARPtrueReads the virtual addresses of a high-availability pair, and persistent maintenance mode.
firmwareWatch for updatestrueReads the result of the firewall’s last update check and whether a reboot is pending.
temperatureRead the temperature sensorstrueReads the CPU and board sensors the firewall exposes.
live_mapLive firewall mapfalseShows where the connections your rules block or pass come from, by country. Needs Diagnostics: Logs: Firewall: Live View.

With the live_map option on, the monitor page gets a Live map panel: where the connections your rules block or pass come from, on a world map, over the last fifteen minutes — a disc per country (dashed when most of it was blocked), short arcs travelling to the firewall as connections arrive, and the countries, rules and ports that come up most.

  • Read-only, on demand. The server reads GET /api/diagnostics/firewall/log every five seconds, only while someone has the panel open, and stops a minute after. The browser never talks to the firewall. Give the API user’s group the privilege Diagnostics: Logs: Firewall: Live View (read-only).
  • No address leaves the server. Each log line is reduced at once to its country, port, protocol, rule and action; addresses are neither stored nor sent to the browser. Fifteen minutes stay in memory (20 000 events at most), nothing is written to the database or to VictoriaMetrics.
  • Countries from a local database. The server downloads DB-IP’s free IP to Country Lite (CC BY 4.0, no account) the first time a live map needs it, keeps it in /data/geoip/, and replaces it when it is more than a month old. Lookups are local: no address is sent to any service. Private, loopback, link-local and CGNAT ranges are grouped as Local network. The panel credits IP Geolocation by DB-IP, as the licence asks. Turn the database off in Settings → Monitoring → Locations → IP geolocation: nothing is downloaded, and countries show as unknown.
  • Arcs need a location. Place the firewall on the world map (by hand, through its site, or as part of the main site); without one the discs are still drawn.
  • Motion. With reduce motion set in the system, the travelling arcs are left out; the discs and the steady arcs of the busiest countries remain.
  • A firewall polled through a relay agent has no live map: the server cannot reach its log.
SymptomLikely cause
Authentication errorThe key and the secret are swapped, or the key was deleted from the user. OPNsense shows the secret only once: if it was lost, create another key and delete the old one.
A web page instead of JSONThe API key is refused, or the account cannot reach that endpoint. OPNsense then serves its login page with a 200; DumbMonit reports it as an authentication problem rather than an unreadable answer.
Certificate errorSelf-signed certificate: install a trusted one (ACME is a plugin) or enable insecure_tls.
No gateway metrics at allThe gateways option is off, or the group lacks System: Gateways. A firewall with no gateway defined genuinely has none.
A gateway shows no delay or lossIt has no monitor address, so dpinger does not ping it. OPNsense writes ~ and DumbMonit publishes no series rather than a zero.
“Gateway down” fires for a link that worksThe monitor address is unreachable even though the link is up — a common case with an ISP that drops ICMP. Set a different monitor address in System → Gateways.
No state table metricsThe group lacks Lobby: Dashboard.
Authentication error on a key that works in a browser toolThe tool used the other spelling of the path. With a restricted key, OPNsense 25.7 and later answer 403 to systemInformation and 200 to system_information.
No update metrics except firmware_checkedThe firewall has never checked for updates, or has just installed one. Run a check from System → Firmware.
No VPN metricsThe plugin is not installed, or no tunnel is configured. A disabled IPsec connection is deliberately not reported as down.
“Firewall resolver stopped” on a firewall that resolves fineUnbound is installed but switched off because the firewall resolves with something else. Turn that rule off.
Firmware version looks out of dateThe firewall has not checked the mirror recently. DumbMonit reads the last check, it never triggers one.
scrape_errors above zeroOne optional call failed for a reason other than a missing privilege or a missing plugin — a timeout, usually. The other metrics are unaffected.