Skip to content

9. Services — DHCP, ACME, Zabbix/SNMP, Suricata/Wazuh

Mixed per-node / primary-only — each section says which. Get the edge routing/firewall (pages 5–8) solid first; these ride on top.

9.1 DHCP for server VLANs (primary — syncs)

Services ▸ Kea DHCP (the current OPNsense DHCP). One subnet per routed server VLAN that needs leases:

VLAN Subnet Pool (example) Gateway DNS
910 10.128.10.0/24 .50–.200 10.128.10.1 Tier-1 resolvers
930 10.128.32.0/22 carve per need 10.128.32.1 10.128.32.3/.4
931 10.128.36.0/22 carve per need 10.128.36.1 10.128.32.3/.4
940 10.128.44.0/24 mgmt hosts 10.128.44.1 Tier-1

Gateway = each VLAN's CARP VIP (.1), so leases point at the floating gateway. Enable HA/failover peer between the nodes if you want lease-state redundancy, or rely on config sync + short leases.

9.2 Split-horizon DNS (primary — syncs)

Services ▸ Unbound DNS ▸ Overrides. Add the internal service records that make the hairpin (page 6 §6.3) go away: service.pubinvest.co.uk → 10.128.x (real internal target). Public DNS keeps the public IP; internal clients resolve internal and preserve their source IP.

9.3 ACME client — GUI admin certificate (primary — syncs)

System ▸ Firmware ▸ Plugins → install os-acme-client.

  1. Services ▸ ACME Client ▸ Accounts — register (Let's Encrypt prod, your email).
  2. Challenge Types — DNS-01 against your DNS provider is cleanest for an admin cert (no inbound 80 needed); or HTTP-01 if you expose a validation path.
  3. Certificates — issue for the GUI admin FQDN.
  4. Automations — restart the GUI on renewal.
  5. System ▸ Settings ▸ Administration — set the GUI to use the issued cert.

9.4 Zabbix agent + SNMPv3 (both nodes — per-node)

Monitor both nodes over the OOB interface — never the data path, so a data-path or CARP event never reads as "host down" (§14).

  1. Install os-zabbix-agent (agent) and configure active mode pointing at <ZABBIX_IP>. Prefer agent-active so the firewall pushes (no inbound poll holes in the OOB firewall).
  2. Install os-net-snmp for SNMPv3, source-locked to <ZABBIX_IP>, for high-rate per-port counters on the X710s.
  3. Apply the FreeBSD by Zabbix agent template; then trim it (§14b):
    • Filter interface LLD — exclude ^(lo|pflog|enc|pfsync|usbus|gif|gre) and the ~8 intentionally-down spare SFP+. Keep OOB in and alert on its link-down (the rescue path is monitored — page 8).
    • Don't apply SNMP and agent to the same metric (double graphs/triggers).
    • Point ICMP host-availability at the OOB address, not a VIP.

CARP-aware custom items (the firewall-specific metrics)

Ship as agent UserParameters. Every "is it down" item must gate on CARP role (§14d) — on the backup, stopped FRR / BACKUP VIPs / ~0 pps are normal and must not alert:

Item Source Alert (when MASTER)
CARP master/backup per VIP ifconfig \| grep carp designated master unexpectedly BACKUP; both MASTER = split-brain; neither = no gateway
pfSync health pfsync0 up + state delta vs peer iface down; large divergence
pf state table pfctl -si vs pfctl -sm > 80% of max states
BGP sessions vtysh -c 'show bgp summary json' any neighbour ≠ Established while MASTER
Suricata EVE stats: capture.kernel_drops, *.memcap_drops drops > 0 sustained; alert-rate spike
NIC HW counters sysctl dev.ixl.N.mac.rx_discards/rx_no_buffers rising
Per-core CPU kern.cp_times one hot core = RSS/NUMA imbalance
Temp/PSU/fan IPMI over OOB over-temp, PSU redundancy lost

Pair-level triggers

Split-brain (both MASTER), no-master (neither), redundancy-lost (backup down while master fine → you're a SPOF), config drift (master vs backup config revision differ).

9.5 Suricata IDS/IPS + Wazuh (both nodes — per-node config, identical)

Placement is the whole game (§11): inline IPS on WAN/DMZ only; never the server trunk.

  1. Services ▸ Intrusion Detection → enable.
  2. Interfaces: assign Suricata to WAN, WAN2, VL_DMZ only. Never SRVTRUNK — inline inspection would crush the 20G east-west/backup path, and it's already behind the zone firewall.
  3. IPS mode on, capture = netmap inline. Netmap needs LRO/TSO off on those NICs (Suricata must see un-coalesced packets) — set per-interface on tunables, offloads on everywhere else.
  4. Runmode workers, cpu-affinity pinned to one NUMA node's cores; detect.profile high; generous flow/stream memcaps (§12e).
  5. Ruleset: ET Open/Pro, prune with rule-profiling for inline throughput.
  6. EVE/alert logging → remote, ship to <WAZUH_IP> (Tier-2) — don't let logging chew the BOSS card. Configure Services ▸ Syslog to forward EVE JSON to <SYSLOG_IP>/<WAZUH_IP>.

Action on the firewall (§ your requirement)

Two automated layers:

  • Inline drop — Suricata IPS drops matching traffic in real time at the WAN/DMZ edge.
  • Wazuh active-response → block alias — Wazuh decodes the Suricata EVE feed and pushes offender IPs into an OPNsense alias (Firewall ▸ Aliases, e.g. wazuh-blocklist) referenced by a block rule on WAN. Point Wazuh's active response at the OPNsense API (a scoped API key) so confirmed offenders are blocked fleet-fast without a human in the loop.

HA & IDS

Suricata runs on both nodes but only the master inspects live traffic. Keep rulesets identical (do the config the same on both nodes) so a failover doesn't change security posture. Zabbix watches Suricata health (drops, running); the alerts live in Wazuh — don't turn Zabbix into an IDS console (§14f).