Testing firewall rules continuously with Zabbix: what should — and shouldn't — be reachable

Testing firewall rules continuously with Zabbix: what should — and shouldn't — be reachable

Table of Contents

Network segmentation looks great on the diagram: the DMZ can’t reach the database VLAN, office workstations can’t reach server management interfaces, backups are reachable only from the backup server. Then a year passes. Someone adds a temporary “any-any” rule to debug an issue. A firewall migration converts policies slightly differently. A new VLAN is created by copying an old one.

Nobody re-tests the rules, so nobody knows whether the segmentation still exists. Auditors (and NIS2) increasingly ask exactly that question.

The idea behind this template is simple: write down the expected connectivity, and let Zabbix test it all the time — from the places that matter.

Template: custom-zabbix-templates/port-reachability — Zabbix 7.0+, uses the standard Zabbix agent.

Two lists, two kinds of alerts

You link the template to a host that has a Zabbix agent — a server in a given network segment — and fill in two macros:

{$TCP_CHECKS}      = srv1:22,web01:443,db01:5432
{$NOT_TCP_CHECKS}  = db01:3306,mgmt-sw01:22,internal:8080
  • {$TCP_CHECKS} — ports that should be reachable from this host. If one goes down, you get “Port … is unreachable (should be reachable)”. That’s a broken service path: the service died, or a firewall change cut it off.
  • {$NOT_TCP_CHECKS} — ports that should NOT be reachable from this host. If one starts answering, you get “Port … is reachable (should NOT be reachable)”. That’s a segmentation leak: a rule is too broad, or a service was exposed where it shouldn’t be.

Both triggers have Average severity. The latest data shows each pair with its expected state, so it also works as living documentation of what talks to what.

How it works

  1. A Script discovery rule (JavaScript) parses both CSV macros into host:port pairs, each tagged as reachable or not_reachable. It runs every hour ({$TCP_DISCOVERY_INTERVAL}).
  2. For every pair, an item net.tcp.port[host,port] is created. It’s an active agent check: the agent on the monitored host itself tries to open a TCP connection — so the test runs from that network segment, through the same firewalls real traffic would cross. Default interval 5 minutes ({$TCP_CHECK_INTERVAL}).
  3. LLD overrides enable only the matching trigger for each pair: “should be reachable” for the first list, “should NOT be reachable” for the second.

Change a macro, and at the next discovery the checks are added or removed automatically.

Setup

  1. Make sure the host runs a Zabbix agent with active checks enabled (ServerActive= pointing to your Zabbix server or proxy).
  2. Import the template (Data collection → Templates → Import, template_port_reachability.yaml) and link it to the host.
  3. Set the macros {$TCP_CHECKS} and/or {$NOT_TCP_CHECKS} on the host. Host names must be resolvable from the agent; IP addresses work too.
  4. Wait for the discovery (up to an hour) or run it manually: open the discovery rule and click Execute now.

Where to put the probes

One template, many vantage points. A practical layout:

Probe host Should be reachable Should NOT be reachable
Web server in the DMZ app server API, DNS, NTP database ports, AD/LDAP, management network
Office workstation VLAN (small VM) file server, intranet, mail server SSH/RDP, hypervisor and switch management, backup server
Backup server every protected host’s agent port —
Guest Wi-Fi (Raspberry Pi) internet (e.g. 1.1.1.1:443) everything internal

The should NOT list is the valuable part. It turns your segmentation policy into tests — when someone’s “temporary” rule opens the database to the DMZ, you know within five minutes, not at the next audit.

Note

net.tcp.port only checks whether a TCP connection can be opened. It doesn’t test UDP, and it doesn’t tell you whether the application behind the port works. For service health use web scenarios or application templates; use this one for reachability and segmentation.

Summary

  • Two macros: ports that must be reachable, and ports that must not.
  • Checks run from the agent’s host, so they test the real network path through your firewalls.
  • Alerts for broken service paths and for segmentation leaks.
  • Put small probe hosts in each important segment and your firewall policy becomes continuously tested.

Designing network segmentation or managing Fortinet firewalls? Talk to us.

comments powered by Disqus

Related Posts

Monitoring HPE Managed PDUs in Zabbix: power, outlets, breakers and rack sensors

Monitoring HPE Managed PDUs in Zabbix: power, outlets, breakers and rack sensors

A PDU is the least glamorous box in the rack — until a breaker trips and half the servers lose one power supply, or a new server pushes a phase over its limit and the whole rack goes dark. Managed PDUs measure all of this. The data just needs to end up somewhere people actually look.

Read More
Traefik 4xx/5xx errors in Zabbix without Prometheus

Traefik 4xx/5xx errors in Zabbix without Prometheus

Traefik sits in front of a lot of applications: as a Docker reverse proxy, as a Kubernetes ingress controller, or as an edge router on a single VM. That makes it the best place to see whether your applications are healthy from the user’s point of view — every failed request passes through it.

Read More
Monitoring disk health on VMware ESXi with smartctl

Monitoring disk health on VMware ESXi with smartctl

Standalone ESXi hosts and small vSphere clusters often run on local SATA or SAS disks — in a homelab, a branch office, or a backup host. When one of those disks starts to fail, you want to know about it from your monitoring, not from a datastore that suddenly goes read-only.

Read More