Skip to main content
RunBook Academy

OPNsenseXII · NAT Fundamentals and Outbound NATInbound NAT

1:1 NAT and bidirectional NAT — when each is appropriate

Intermediate⏱ ~12 minpfctl

What you'll learn

  • Distinguish 1:1 NAT from port forwarding
  • Configure 1:1 NAT for an inbound server
  • Explain BINAT and when it is required
  • Recognise the firewall rule implications of 1:1 NAT

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

Not yet marked complete on this device.

Port forwarding maps one external port to one internal host. 1:1 NAT maps one external IP to one internal host — every port, every protocol, every flow. The internal host appears to own the public IP for all purposes: the firewall rewrites both source and destination so the internal host is reachable on the public IP from outside, and outbound traffic from the internal host appears to come from the public IP without a separate outbound NAT rule.

This is the right tool when a single host needs a public identity — a mail server, a VPN endpoint, a game server, a host that runs many services. It is the wrong tool when only specific ports need to be exposed; port forwarding is simpler and safer.

This lesson covers 1:1 NAT, the BINAT variant for protocols that require bidirectional translation, and the firewall rules that accompany the configuration.

What 1:1 NAT actually does

A 1:1 NAT entry binds a public IP to an internal IP. PF generates two translation rules:

  1. An rdr rule on the WAN. Traffic to the public IP from any source gets the destination rewritten to the internal IP. The rewrite applies to all ports and protocols — there is no port filter.
  2. A nat rule on the internal interface. Traffic from the internal host gets the source rewritten to the public IP. This is the outbound side of the 1:1 mapping.

The combined effect: the internal host appears to own the public IP. Inbound traffic to any port arrives at the internal host. Outbound traffic from the internal host appears to come from the public IP. The internal host does not need its own outbound NAT rule; the 1:1 binding covers it.

Read-only / Safe1:1 NAT rules
$ pfctl -s nat | grep -A 1 '198.51.100.10'
rdr on igb1 inet proto any from any to 198.51.100.10 -> 192.0.2.10
nat on igb0 inet from 192.0.2.10 to any -> 198.51.100.10

Illustrative output

When 1:1 NAT is the right tool

Three situations fit 1:1 NAT cleanly:

  • A server needs a public identity. A mail server with PTR records, an HTTPS server with a dedicated IP for certificate validation, a game server with a stable public endpoint. The server’s outbound traffic needs to come from the same IP the inbound traffic arrives at, for rDNS, reputation, and TLS consistency.
  • A host runs many services. Instead of writing port forwards for ports 80, 443, 587, 993, 8080, 8443, the operator writes one 1:1 NAT entry. The trade-off is that all ports are exposed to the firewall; the firewall rules must restrict them.
  • A legacy application uses non-standard protocols or non-TCP transports. Port forwarding requires a port number. 1:1 NAT rewrites without a port filter, which works for any protocol that uses IP addresses.

When 1:1 NAT is the wrong tool

1:1 NAT is the wrong tool when only specific ports need exposure and the operator wants the firewall to drop everything else by default. In that case, port forwarding is safer: only the forwarded ports are rewritten; everything else is dropped by the implicit deny.

A common anti-pattern: “I will use 1:1 NAT and then block all the ports I do not need with firewall rules.” This works, but it is more work and easier to misconfigure than port forwarding. The default-deny model says: expose the minimum, block the rest. Port forwarding is the minimum; 1:1 NAT is everything.

BINAT: bidirectional NAT

BINAT is a 1:1 NAT variant that performs the translation in both directions for protocols that need it. The distinction matters for protocols where the source address is part of the payload — protocols like IPsec, GRE, or any application that embeds the IP address in its data stream.

For TCP and UDP, regular 1:1 NAT works fine: the IP address is in the header, PF rewrites it on the way through, and the protocol payload is unchanged. For IPsec, the IKE negotiation exchanges IP addresses in the payload; if PF only rewrites the outer header, the inner payload still references the original IP and the negotiation fails. BINAT tells PF to rewrite both the header and the payload addresses.

The implementation: BINAT is configured as a 1:1 NAT in the GUI with an option for “BINAT” mode (the GUI label varies by OPNsense version; in some versions it is a separate entry type under Firewall → NAT → 1:1).

A practical rule of thumb: use BINAT when the host runs IPsec endpoints or other protocols where the source IP is referenced in the application payload. Use regular 1:1 NAT for TCP/UDP services.

The firewall rule that goes with 1:1 NAT

The firewall rule that allows inbound traffic to a 1:1 NAT’d host:

  • Interface: WAN
  • Direction: in
  • Protocol: TCP, UDP, ICMP, or any (as needed)
  • Source: any (or restricted as needed)
  • Destination: the public IP (not the internal IP — the firewall rewrites before the rule)
  • Destination port: specific ports or any (as needed)
  • Action: pass

The destination in the rule is the public IP, not the internal one. The rule is evaluated after DNAT, but the GUI presents the pre-DNAT destination for matching. OPNsense generates the underlying PF rule correctly: the filter sees the post-DNAT destination (the internal IP), and the rule written against the public IP translates internally to the right match.

Read-only / Safe1:1 NAT firewall rules
$ pfctl -s rules | grep '198.51.100.10' | head -5
@101 pass in quick on igb1 inet proto tcp from any to 198.51.100.10 port = https
@102 pass in quick on igb1 inet proto tcp from any to 198.51.100.10 port = smtp
@103 pass in quick on igb1 inet proto tcp from any to 198.51.100.10 port = submission
@104 pass in quick on igb1 inet proto icmp from any to 198.51.100.10 icmp-type echoreq

Illustrative output

A worked example

The requirement: expose a mail server at 192.0.2.10 on a public IP 198.51.100.10. The server runs HTTPS (443), SMTP (25), and submission (587). ICMP echo is allowed for diagnostic ping.

Step 1: alias the public IP to the WAN interface. Under Interfaces → WAN, add 198.51.100.10 as an IP alias.

Step 2: create the 1:1 NAT entry under Firewall → NAT → 1:1: external IP 198.51.100.10, internal IP 192.0.2.10, destination “any” (the rule applies regardless of destination port).

Step 3: create the firewall rules on the WAN interface: TCP/443 to 198.51.100.10, TCP/25 to 198.51.100.10, TCP/587 to 198.51.100.10, ICMP echo to 198.51.100.10.

Step 4: verify with pfctl -s nat and pfctl -s rules that the rdr, nat, and pass rules are present.

Step 5: from an external host, curl https://198.51.100.10 and confirm the mail server responds. The packet flow: external → WAN → rdr (198.51.100.10 → 192.0.2.10) → filter pass → LAN → server.

When 1:1 NAT conflicts with outbound NAT

A 1:1 NAT entry generates an outbound NAT rule for the internal host. If the operator has a separate outbound NAT rule for the same internal host (e.g. a Manual-mode rule translating 192.0.2.0/24 to WAN-A), the two rules conflict. PF evaluates them in order; the first match wins. The 1:1 NAT rule typically appears above the manual outbound rule (because 1:1 entries are generated as part of the NAT configuration), and the 1:1 translation wins.

If the operator wants the manual outbound rule to apply (e.g. to translate to a different WAN IP), the 1:1 entry must be removed or reordered.

Summary

  • 1:1 NAT maps a public IP to an internal IP, rewriting all ports and protocols bidirectionally.
  • Use 1:1 NAT when a host needs a public identity, runs many services, or uses protocols that port forwarding cannot handle.
  • Use port forwarding (not 1:1 NAT) when only specific ports need exposure. 1:1 NAT exposes everything; the firewall rules must restrict.
  • BINAT is a 1:1 NAT variant for protocols where the source IP appears in the payload (IPsec, GRE).
  • Every 1:1 NAT entry is paired with explicit firewall rules. The 1:1 entry does not, by itself, allow traffic.
  • Do not mix 1:1 NAT with port forwarding on the same public IP. Choose one model per public IP.

Knowledge check · 4 questions

  1. Q1. A mail server at 192.0.2.10 needs to be reachable on a public IP 198.51.100.10 for SMTP (25), submission (587), and HTTPS (443). The operator wants the cleanest configuration. Which approach is correct?

  2. Q2. A 1:1 NAT entry in OPNsense automatically allows all inbound traffic from the Internet to the public IP, regardless of firewall rules.

  3. Q3. Which of the following are valid use cases for 1:1 NAT? Select all that apply.

  4. Q4. An IPsec VPN endpoint at 192.0.2.20 needs a public IP for IKE negotiations. IKE embeds the source IP in the payload. Which NAT approach is required?

Passing score: 75%. Answers are checked in this browser.