OPNsenseXV · DMZ ArchitectureDMZ services and isolation
Triple-homed firewall — WAN, DMZ, LAN interfaces and the routing decisions
What you'll learn
- Configure the three interfaces of a triple-homed firewall
- Trace a packet through the firewall between any two of the three interfaces
- Apply the rule sets that govern each interface
- Recognise the production traps of three-interface operation
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 triple-homed firewall has three interfaces: WAN, DMZ, and LAN. Each interface has its own IP, its own rule set, and its own role in the routing decisions the firewall makes. The discipline of operating three interfaces is that each interface’s ruleset must be reasoned about independently, the routing table must be consistent across all three, and the default-deny posture must be applied on every interface.
This lesson covers how the triple-homed firewall routes between interfaces, the rule sets that govern each interface, and the production traps that come from operating three interfaces on one firewall.
The three interfaces
A triple-homed firewall has:
- WAN interface (
igb0). Connects to the Internet. The IP is the firewall’s public IP (or behind an ISP gateway with NAT). Inbound traffic from the Internet arrives here. - DMZ interface (
igb2). Connects to the DMZ switch. The IP is the gateway for the DMZ subnet. Public-facing services live on this subnet. - LAN interface (
igb1). Connects to the LAN switch. The IP is the gateway for the LAN subnet. Internal users, servers, and infrastructure live on this subnet.
The three interfaces each have a different subnet, a different IP, and a different role. The firewall is the routing point for every inter-interface packet.
$ ifconfig igb0 igb1 igb2 2>/dev/null | grep -E '^[a-z]|inet [0-9]'igb0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
inet 198.51.100.1 netmask 0xffffffe0 broadcast 198.51.100.31
igb1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
inet 192.0.2.1 netmask 0xffffff00 broadcast 192.0.2.255
igb2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
inet 203.0.113.1 netmask 0xffffff00 broadcast 203.0.113.255Illustrative output
The three interfaces are up and have distinct subnets. The operator can route between them.
The routing table
The routing table for a triple-homed firewall has three connected routes plus a default route:
$ netstat -rn | grep -v '::' | head -10Routing tables
Internet:
Destination Gateway Flags Netif Expire
default 198.51.100.2 UGS igb0
127.0.0.1 link#4 UH lo0
192.0.2.0/24 link#6 UC igb1
198.51.100.0/27 link#5 UC igb0
203.0.113.0/24 link#7 UC igb2Illustrative output
The four routes (three connected, one default) cover every destination. The firewall can reach every IP on every subnet it is attached to, and every Internet destination via the default route.
Packet flow: Internet to DMZ
A packet from the Internet destined for the public web server in the DMZ:
Internet client 203.0.113.50:54321 → WAN IP 198.51.100.1:443 → DMZ web server 203.0.113.10:443
- Packet arrives on
igb0(WAN). Source IP = Internet client, destination IP = firewall WAN IP. - PF evaluates rules on
igb0. The auto-generated rule from the port-forward permits TCP from any to any on port 443. - NAT redirection. PF rewrites the destination from firewall WAN IP to DMZ web server IP. The destination port is preserved (443 → 443).
- State created. PF creates state tracking both the original and the rewritten addresses.
- Routing decision. The kernel consults the routing table. The rewritten destination IP
203.0.113.10matches the connected route onigb2. - PF evaluates rules on
igb2(DMZ). For state-matched traffic, this evaluation is skipped. For new flows on the DMZ interface, the rules apply. - Packet exits on
igb2. The frame is delivered to the DMZ web server.
The return traffic follows the same path in reverse: web server → firewall DMZ interface → state match → NAT reverse → WAN interface → Internet.
Packet flow: LAN to DMZ
A packet from a LAN host (e.g. an operator) to a DMZ server for administrative purposes:
LAN host 192.0.2.50:54321 → firewall LAN IP 192.0.2.1 → DMZ server 203.0.113.10:22
- Packet arrives on
igb1(LAN). Source IP = LAN host, destination IP = DMZ server IP. - PF evaluates rules on
igb1. A specific rule permits the operator’s host to reach the DMZ server on TCP 22 (SSH). State is created. - Routing decision. The kernel consults the routing table. The destination
203.0.113.10matches the connected route onigb2. - Packet exits on
igb2. The frame is delivered to the DMZ server.
The source IP is preserved (the LAN host’s IP), and the destination IP is the DMZ server. No NAT is applied because the traffic is between two RFC 1918 subnets.
Packet flow: DMZ to LAN (denied)
A packet from a compromised DMZ host trying to reach a LAN host:
DMZ host 203.0.113.50:54321 → firewall DMZ IP 203.0.113.1 → LAN host 192.0.2.50:22
- Packet arrives on
igb2(DMZ). Source IP = DMZ host, destination IP = LAN host. - PF evaluates rules on
igb2. The default deny on the DMZ interface blocks the packet. No state is created. - PF logs the dropped packet. With logging enabled, the firewall log shows the drop.
- No routing decision. The packet is dropped before the kernel makes a routing decision.
The default deny on the DMZ interface is the foundation of the segregation. Without it, the compromised DMZ host can reach the LAN.
The rule sets per interface
WAN interface rules
The WAN interface sees inbound traffic from the Internet. The rules:
| Order | Action | Source | Destination | Port | Description |
|---|---|---|---|---|---|
| 1 | pass | any | DMZ web server | 80, 443 | Public HTTP/HTTPS |
| 2 | pass | any | DMZ mail server | 25, 587 | Public SMTP |
| 3 | pass | any | DMZ DNS server | 53 | Public DNS |
| 4 | block | any | RFC 1918 | any | Block bogons (RFC 1918 from Internet) |
| 5 | block | any | any | any | Default deny |
Rules 1-3 are auto-generated from port-forwards. Rule 4 blocks traffic destined to RFC 1918 addresses (which should never appear as destinations on the WAN interface — the Internet does not route to private IPs). Rule 5 is the default deny.
DMZ interface rules
The DMZ interface sees traffic from DMZ hosts. The rules:
| Order | Action | Source | Destination | Port | Description |
|---|---|---|---|---|---|
| 1 | pass | DMZ servers | firewall DMZ IP | 53 | DMZ hosts using firewall DNS |
| 2 | pass | monitoring agent | DMZ servers | various | Monitoring scrapes |
| 3 | pass | DMZ servers | any | 80, 443 | Outbound for updates, OCSP |
| 4 | block | DMZ subnet | LAN subnets | any | DMZ cannot reach LAN |
| 5 | block | any | any | any | Default deny |
Rules 1-3 permit the specific flows the DMZ needs. Rule 4 explicitly blocks DMZ-to-LAN traffic (defense in depth on top of the default deny). Rule 5 is the catch-all.
LAN interface rules
The LAN interface sees traffic from LAN hosts. The rules:
| Order | Action | Source | Destination | Port | Description |
|---|---|---|---|---|---|
| 1 | pass | LAN subnet | firewall LAN IP | 80, 443 | LAN hosts using firewall GUI (if exposed on LAN) |
| 2 | pass | LAN subnet | firewall LAN IP | 22 | LAN hosts using firewall SSH (if exposed on LAN) |
| 3 | pass | LAN subnet | DMZ jump hosts | 22 | Operators reaching bastion |
| 4 | pass | LAN subnet | any | any | Outbound Internet (default LAN rule) |
| 5 | block | any | any | any | Default deny |
Rules 1-2 permit LAN access to the firewall itself (if exposed). Rule 3 permits operators to reach the bastion. Rule 4 is the default LAN rule. Rule 5 is the default deny.
Production patterns
Three patterns cover most triple-homed deployments.
Pattern 1: Single firewall, three physical NICs
The simplest pattern: three physical NICs, one for each interface. Production deployments often have a fourth NIC for a dedicated management VLAN.
igb0 — WAN (public IP from ISP)
igb1 — LAN (internal subnet)
igb2 — DMZ (public-facing services)
igb3 — Management (operator access)
This is the standard pattern for small and medium estates.
Pattern 2: Single firewall, trunk for LAN-side
The LAN-side uses a trunk NIC for both LAN and management. The DMZ is on a separate physical NIC.
igb0 — WAN
igb1 — Trunk for LAN + management VLANs
igb2 — DMZ
The DMZ is on a separate physical NIC because the DMZ should not share a Layer 2 segment with anything else. The trunk carries LAN-side VLANs (users, servers, management, IoT, etc.).
Pattern 3: HA pair with triple-homing on both nodes
A high-availability pair has triple-homing on both nodes. The WAN, DMZ, and LAN are all CARP-redundant.
node1.igb0 + node2.igb0 = CARP WAN VIP
node1.igb1 + node2.igb1 = CARP LAN VIP
node1.igb2 + node2.igb2 = CARP DMZ VIP
The HA pair is covered in Parts XXVI-XXIX. The triple-homing pattern is the same; the addition is CARP for IP redundancy and pfsync for state replication.
$ pfctl -s rules | awk '/^@/ {print $0}' | awk '{for(i=1;i<=NF;i++) if($i~/^on$/) print $(i+1)}' | sort | uniq -c | sort -rn 12 igb1
8 igb2
6 igb0Illustrative output
The three interfaces have different rule counts because each has different needs. The asymmetry is the right outcome.
The three-interface traps
Three traps recur in triple-homed deployments.
Trap 1: Forgetting the DMZ interface rule set
The operator writes the WAN and LAN rule sets carefully, but the DMZ interface has no rules. The default deny blocks all DMZ-to-anything traffic, including legitimate flows. The operator adds “permit any to any” on the DMZ to “fix” the issue, undoing the segregation.
The fix: write the DMZ rule set from scratch, based on what the DMZ actually needs. DNS, NTP, updates, monitoring. No permits to the LAN.
Trap 2: NAT on the wrong interface
The operator configures outbound NAT for the LAN-to-Internet flow (which is correct) and accidentally applies it to inter-interface traffic. The DMZ-to-LAN traffic gets source-rewritten, breaking the LAN’s ability to identify the DMZ host in logs.
The fix: outbound NAT applies to traffic leaving the WAN interface. Inter-VLAN and inter-interface traffic (LAN ↔ DMZ) does not get outbound NAT unless explicitly configured.
Trap 3: Bogons on the WAN
The operator forgets to block RFC 1918 sources on the WAN interface. An attacker can send packets with RFC 1918 source IPs to the firewall, hoping the firewall logs them or processes them. The firewall should drop these packets at the WAN interface.
The fix: a block rule on the WAN for RFC 1918 sources, plus a similar rule for other bogons (the multicast ranges, the reserved ranges). OPNsense has a built-in “bogons” alias that can be used.
Summary
- A triple-homed firewall has three interfaces (WAN, DMZ, LAN) each with its own IP, subnet, and rule set.
- The routing table has three connected routes plus a default route. The kernel routes between interfaces based on the destination IP.
- Every interface needs its own rule set. The default deny is at the bottom of every rule set.
- Three production traps: forgetting the DMZ rule set, applying outbound NAT to inter-interface traffic, and not blocking bogons on the WAN.
Knowledge check · 4 questions
Q1. A triple-homed firewall has interfaces igb0 (WAN), igb1 (LAN), igb2 (DMZ). A packet from a LAN host arrives on igb1 with destination 203.0.113.10 (DMZ server). The routing table shows 203.0.113.0/24 via igb2. The DMZ rule set has no explicit rules. What happens?
Q2. A DMZ interface with no explicit rules allows all traffic by default.
Q3. Which of the following are valid patterns for a triple-homed firewall? Select all that apply.
Q4. A triple-homed firewall has a default LAN rule permitting LAN subnet to any. A packet from a DMZ host arrives on igb2 destined for a LAN host. The DMZ rules have no explicit rule permitting or blocking the traffic. What happens?
Passing score: 75%. Answers are checked in this browser.