OPNsenseXV · DMZ ArchitectureDMZ services and isolation
DMZ isolated by firewall — what the DMZ can and cannot reach
What you'll learn
- Apply the DMZ isolation rule set on the DMZ interface
- Identify the specific flows the DMZ requires and the flows it must not have
- Audit the DMZ rule set for over-permissiveness
- Trace a denied packet from a DMZ host to confirm the rule that blocked it
Prerequisites
Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14
The DMZ exists to host services the Internet must reach. The corollary: the DMZ must be isolated from the LAN. The firewall rules enforce this isolation. A DMZ that can reach the LAN is not a DMZ in the security sense — it is a stepping stone to the LAN for any attacker who compromises a DMZ service.
This lesson covers what the DMZ can reach (itself, the Internet for specific purposes), what it cannot reach (the LAN, internal services), the specific rule set that enforces this isolation, and the audit patterns that catch over-permissiveness.
The DMZ isolation principle
A DMZ host, when compromised, must not be able to:
- Reach internal services (databases, file shares, internal APIs).
- Reach the management VLAN (no administrative access to the firewall itself).
- Reach user workstations (no lateral movement to user devices).
- Reach the LAN at all, except by explicit, narrow, audited flows.
A DMZ host, when legitimate, must be able to:
- Reach the Internet for software updates, OCSP stapling, certificate validation, and similar.
- Reach the firewall for DNS, NTP, and management access (from the bastion only).
- Reach the bastion for administrative access.
The isolation principle: deny by default, permit only what is needed, audit regularly.
The DMZ rule set
A complete DMZ rule set for a small estate with web, mail, and DNS:
Order | Action | Source | Destination | Port | Description
1 | pass | DMZ monitoring | DMZ servers | various | Monitoring agent scrapes
2 | pass | DMZ servers | firewall DMZ | 53 | DMZ hosts using firewall DNS
3 | pass | DMZ servers | firewall DMZ | 123 | DMZ hosts using firewall NTP
4 | pass | DMZ servers | any | 80, 443 | DMZ hosts reaching Internet (updates, OCSP)
5 | pass | bastion | DMZ servers | 22 | Bastion reaching DMZ for SSH admin
6 | pass | DMZ servers | smarthost | 25, 587 | DMZ mail server outbound (specific)
7 | block | DMZ subnet | LAN subnets | any | Explicit DMZ-to-LAN block
8 | block | DMZ subnet | mgmt VLAN | any | Explicit DMZ-to-management block
99 | block | any | any | any | Default deny
Eight rules cover the legitimate flows and explicitly block the illegitimate ones. Rules 1-6 are permits for what the DMZ needs. Rules 7-8 are explicit blocks for what the DMZ must not have. Rule 99 is the default deny.
The explicit blocks (rules 7-8) are defense in depth on top of the default deny. Even if the default deny is misconfigured, the explicit blocks catch the traffic.
What the DMZ can reach
Three categories of legitimate outbound flows from the DMZ.
Category 1: Internet services
The DMZ hosts need to reach the Internet for:
- Software updates (
pkg upgrade,apt-get upgrade, etc.). - Certificate validation (OCSP, CRL).
- Time synchronisation if the firewall NTP is not used.
- Outbound mail (mail server reaching the destination mail server).
The firewall rule: permit TCP from DMZ subnet to any on ports 80, 443 (HTTPS for updates and OCSP) and 25 (SMTP for outbound mail). Optionally restrict the destinations to specific IP ranges or FQDNs for tighter control.
Category 2: Firewall services
The DMZ hosts need to reach the firewall for:
- DNS (UDP 53 to the firewall IP).
- NTP (UDP 123 to the firewall IP).
- Logging (if the firewall is the syslog destination).
The firewall rule: permit UDP from DMZ subnet to firewall DMZ IP on ports 53 and 123.
Category 3: Bastion
The DMZ hosts need to reach the bastion for administrative access (or the bastion reaches them — both patterns are valid).
If the bastion initiates the connection (recommended), the firewall rule is “permit bastion → DMZ hosts TCP 22”. If the DMZ hosts initiate (less common, requires DMZ hosts to know the bastion IP), the rule is reversed.
$ pfctl -s rules | grep -E '^@.*igb2' | head -10@1 pass in quick on igb2 inet proto tcp from <monitoring_agent> to <dmz_servers>
@2 pass in quick on igb2 inet proto tcp from <dmz_subnet> to (igb2) port = 53
@3 pass in quick on igb2 inet proto udp from <dmz_subnet> to (igb2) port = 123
@4 pass in quick on igb2 inet proto tcp from <dmz_subnet> to any port = https
@5 pass in quick on igb2 inet proto tcp from <bastion> to <dmz_subnet> port = 22
@6 pass in quick on igb2 inet proto tcp from <mail_server> to any port = smtp
@7 block drop in quick on igb2 inet from <dmz_subnet> to <lan_subnets>
@8 block drop in quick on igb2 inet from <dmz_subnet> to <mgmt_vlan>
@99 block drop in quick on igb2 inet from any to anyIllustrative output
The compiled rules show every flow the DMZ interface permits and blocks. The audit compares this list against the documented DMZ flows.
What the DMZ cannot reach
The DMZ cannot reach:
- The LAN. All LAN subnets are blocked by rule 7. The DMZ cannot reach user workstations, internal servers, file shares, internal databases, internal APIs.
- The management VLAN. The management VLAN is blocked by rule 8. The DMZ cannot reach the firewall GUI, the firewall SSH, the bastion (if the bastion is on the management VLAN and initiates connections), or other management hosts.
- Other DMZ hosts (selectively). DMZ hosts can typically reach each other (intra-DMZ traffic is permitted by default unless explicitly blocked). For high-security DMZs, intra-DMZ traffic may also be blocked.
- The firewall itself (except for DNS, NTP, logging). The firewall IP on the DMZ is reachable only on the specific ports in rules 2-3.
The specific flows the DMZ must not have
Three categories of flows that production DMZs commonly have but should not:
Category 1: DMZ to database servers
A web server in the DMZ needs database access. The temptation: put the database in the DMZ or write a “permit DMZ → LAN database” rule.
The right pattern: keep the database on the LAN, write an explicit firewall rule permitting the DMZ web server to reach the LAN database on the database port. The rule is narrow (specific source IP, specific destination IP, specific port), not a “permit DMZ → LAN” wide rule.
Category 2: DMZ to internal monitoring
The DMZ hosts need to send metrics to the internal monitoring server. The temptation: write “permit DMZ → LAN” for the monitoring server IP.
The right pattern: write a specific rule permitting the DMZ hosts to reach the LAN monitoring server on the specific port. The rule is narrow.
Category 3: DMZ to internal package mirror
The DMZ hosts need to install software updates. The temptation: permit “DMZ → Internet” for any source (which is what rule 4 does, but the destination is broader than needed).
The right pattern: if the operator has an internal package mirror, write a specific rule permitting DMZ → LAN mirror on the mirror port. The rule is narrow and is preferred over a broad Internet rule for software updates.
Auditing the DMZ rule set
Three audit patterns.
Audit 1: List every DMZ-to-LAN rule
pfctl -s rules | grep -E 'pass.*igb2.*lan_subnet'
Every match is reviewed. The audit confirms:
- The source is a specific DMZ host, not the entire DMZ subnet.
- The destination is a specific LAN host, not the entire LAN subnet.
- The port is specific.
- The description names the application and the ticket.
If any rule has “any” in source, destination, or port (and is not the default deny), it is a finding.
Audit 2: Confirm the explicit block rules
pfctl -s rules | grep -E 'block.*igb2.*lan_subnet'
The audit confirms:
- The explicit DMZ-to-LAN block rule exists.
- The explicit DMZ-to-management block rule exists.
- The default deny is at the bottom of the rule set.
If any of these is missing, it is a finding.
Audit 3: Review the rule descriptions
Every rule should have a description that names the application, the ticket, and the owner. Rules without descriptions are findings.
$ pfctl -s rules | awk '/^@.*igb2.*pass/ {for(i=1;i<=NF;i++) if($i~/from/) print $(i+1)}' | sort -u<monitoring_agent>
<dmz_subnet>
<bastion>
<mail_server>Illustrative output
The unique sources for pass rules are four aliases or subnets, each tied to a specific purpose. The audit confirms no rule has a source broader than necessary.
Tracing a denied packet
When a DMZ host cannot reach a LAN host, the diagnostic sequence:
- From the DMZ host:
ping 192.0.2.50(or similar). - On the firewall:
tcpdump -nei igb2 host 192.0.2.50shows the ICMP echo arriving on the DMZ interface. - On the firewall:
pfctl -s rules | grep igb2shows the rules on the DMZ interface. - On the firewall: The firewall log shows the packet dropped by rule 7 (the explicit DMZ-to-LAN block) or rule 99 (the default deny).
The diagnostic confirms the packet arrived on the DMZ interface and was dropped by the DMZ rule set. The routing decision was never made because PF blocked the packet.
Summary
- The DMZ is isolated by the firewall rules on the DMZ interface. The default deny plus explicit DMZ-to-LAN and DMZ-to-management blocks are the foundation.
- The DMZ can reach the Internet for specific services, the firewall for DNS/NTP/logging, and the bastion for administration.
- The DMZ cannot reach the LAN, the management VLAN, or the firewall itself except for the specific permitted services.
- Audit the DMZ rule set for “any” sources/destinations/ports, missing explicit blocks, and missing default deny.
Knowledge check · 4 questions
Q1. You inherit a DMZ rule set with a single rule "permit DMZ subnet to LAN subnet on any port" with description "DMZ to LAN for various services". What is the most appropriate first action?
Q2. The explicit DMZ-to-LAN block rule is defense in depth on top of the default deny; either alone is sufficient.
Q3. Which of the following are valid legitimate outbound flows from a DMZ host? Select all that apply.
Q4. You run tcpdump -nei igb2 host 192.0.2.50 on the firewall and see ICMP echo requests arriving from 203.0.113.50 destined for 192.0.2.50. The packet is not leaving on igb1. What is the most likely explanation?
Passing score: 75%. Answers are checked in this browser.