Testing firewall rules continuously with Zabbix: what should — and shouldn't — be reachable
- Monitoring , Security
- April 2, 2026
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
- A Script discovery rule (JavaScript) parses both CSV macros into
host:portpairs, each tagged asreachableornot_reachable. It runs every hour ({$TCP_DISCOVERY_INTERVAL}). - 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}). - 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
- Make sure the host runs a Zabbix agent with active checks enabled (
ServerActive=pointing to your Zabbix server or proxy). - Import the template (Data collection → Templates → Import,
template_port_reachability.yaml) and link it to the host. - 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. - 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.