What does a real-world Stateful Firewall ruleset look like, and what fields does it use beyond simple IP/port?
Real-world stateful firewall rules use named objects (not raw IPs), service groups (not raw ports), and schedules (time-based control) — making the ruleset readable and maintainable for hundreds of rules.
The Fortinet FortiGate example:
| Seq | Source | Destination | Schedule | Service | Action | NAT | Log |
|---|---|---|---|---|---|---|---|
| 15 | ebexchange | extIP_Mail1, extIP_Mail2 | always | ALL | Enable | All | |
| 16 | GdeAPP | all | always | ALL | Enable | UTM | |
| 17 | Intranet_DHCP_Range | Microsoft | always | HTTP, HTTPS | Enable | UTM | |
| 18 | Intranet_DHCP_Range, Local_Internet_Access | all | always | HTTP, HTTPS | Enable | All | |
| 19 | Protonet | all | always | ALL | Enable | UTM | |
| 20 | Intranet_LAN | all | always | NTP | Enable | --- |
Why named objects matter:
Compare two rules expressing the same thing:
# Without objects — unmaintainable:
allow 192.168.10.0/24 to 8.8.8.8 port 53 udp
allow 192.168.10.0/24 to 1.1.1.1 port 53 udp
allow 192.168.10.0/24 to 9.9.9.9 port 53 udp
# With objects — maintainable:
allow Intranet_LAN to DNS_Servers DNS_Service
When you add a fourth DNS server, you update the DNS_Servers object once — every rule that uses it picks up the change automatically.
The columns explained:
| Column | What it does |
|---|---|
| Source / Destination | Address objects (single IP, subnet, group, or geographic region) |
| Schedule | When the rule is active ("always", "business-hours", "weekends") |
| Service | Port/protocol object ("HTTP" = TCP/80, "HTTPS" = TCP/443) |
| Action | accept / deny / IPSec |
| NAT | Whether to translate addresses on this flow |
| Log | What level of logging (none, all, UTM events) |
The "UTM" log column:
UTM = Unified Threat Management = the FW also runs IDS/IPS, AV, web filtering on this flow. Logging at "UTM" level means "log only when a threat is detected, not every connection."
Tip: When you read a real firewall ruleset for the first time, scan the bottom of the list first — that's where the catch-all "deny all" lives. Rules above it are the explicit allows. If there's no bottom catch-all deny, the FW's default policy (configured separately) decides.
Go deeper:
Stateful firewall (Wikipedia) — connects the named-object/service ruleset to the state table that makes the decisions enforceable.