NAT

AiFw supports six NAT types — SNAT, DNAT (port forwarding), Masquerade, 1:1 BiNAT, NAT64, and NAT46. NAT46 is unusual on consumer firewall distributions and lets you front legacy IPv4 clients onto an IPv6-only network. All NAT rules compile into the dedicated aifw-nat anchor and never touch the system pf config.

Quickstart

In the Web UI, go to Firewall → NAT → Add rule. Pick the NAT type, the interface the rule applies to, optional protocol/source/destination filters, and the redirect target.

Create a port forward (DNAT) for inbound HTTPS to an internal host:

curl -X POST https://aifw.local/api/v1/nat \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nat_type": "dnat",
    "interface": "em0",
    "protocol": "tcp",
    "src_addr": "any",
    "dst_addr": "any",
    "dst_port": "443",
    "redirect": { "address": "192.168.1.10", "port": "443" },
    "label": "fwd-https"
  }'

DNAT rules automatically receive a NAT-reflection companion so reply traffic from the internal host routes back through the firewall (no asymmetric routing).

Then reload to push to pf:

curl -X POST https://aifw.local/api/v1/reload \
  -H "Authorization: Bearer $TOKEN"

CLI

aifw nat add --type snat --interface em0 --src 192.168.1.0/24 --redirect 203.0.113.1
aifw nat add --type dnat --interface em0 --proto tcp --dst-port 80 \
             --redirect 192.168.1.10 --redirect-port 8080
aifw nat list
aifw nat remove <uuid>

API endpoints

Method Endpoint Description
GET /api/v1/nat List all NAT rules
GET /api/v1/nat/{id} Get one rule
GET /api/v1/nat/pf-output Show the rendered pf NAT syntax
POST /api/v1/nat Create a rule
PUT /api/v1/nat/{id} Update a rule
DELETE /api/v1/nat/{id} Delete a rule
PUT /api/v1/nat/reorder Reorder NAT rules by UUID array

NAT types

SNAT — source NAT

Rewrite the source address on outbound traffic to a fixed public IP. Use when you have a single static public address and need explicit, deterministic source addressing rather than the dynamic interface address.

{ "nat_type": "snat", "interface": "em0",
  "src_addr": "192.168.1.0/24", "dst_addr": "any",
  "redirect": { "address": "203.0.113.1" } }

DNAT — destination NAT / port forwarding

Forward inbound traffic on the WAN to an internal host. Compiles to a pf rdr rule plus an automatic reflection companion so replies route back through the firewall.

{ "nat_type": "dnat", "interface": "em0", "protocol": "tcp",
  "dst_addr": "any", "dst_port": "443",
  "redirect": { "address": "192.168.1.10", "port": "443" } }

DNAT rules require either dst_port or a port on the redirect target.

Masquerade

Dynamic source NAT using whichever address the WAN interface currently holds. The default for most home/SOHO setups where the WAN gets a DHCP-assigned public IP. The redirect address is ignored — pf uses (<iface>) and follows the interface address as it changes.

{ "nat_type": "masquerade", "interface": "em0",
  "src_addr": "192.168.1.0/24", "dst_addr": "any",
  "redirect": { "address": "any" } }

BiNAT — 1:1 NAT

Bidirectional 1:1 mapping between an internal address and an external address. Compiles to a single binat rule that handles both inbound and outbound translation.

{ "nat_type": "binat", "interface": "em0",
  "src_addr": "192.168.1.10", "dst_addr": "any",
  "redirect": { "address": "203.0.113.10" } }

NAT64

Translate IPv6 source traffic into IPv4 destination traffic. Pair with a DNS64 resolver (the rDNS resolver has a dns64 toggle) so IPv6-only clients can still reach IPv4 destinations.

{ "nat_type": "nat64", "interface": "em0",
  "src_addr": "64:ff9b::/96", "dst_addr": "any",
  "redirect": { "address": "203.0.113.1" } }

NAT46

Translate IPv4 source traffic into IPv6 destination traffic. Front legacy IPv4 clients onto an IPv6-only backend network. NAT46 is uncommon on most firewall distros — AiFw exposes it as a first-class rule type.

{ "nat_type": "nat46", "interface": "em0",
  "src_addr": "any", "dst_addr": "any",
  "redirect": { "address": "2001:db8::1" } }

Configuration

Field Default Notes
Anchor name aifw-nat NAT rules live in their own anchor, separate from filter rules
protocol any NAT applies regardless of L4 protocol unless you scope it
Reflection (DNAT) always on A second nat rule is auto-generated so replies route back through the firewall
label optional NAT rules don’t accept the pf label keyword; AiFw stores the label for UI display only

See also

Last updated: