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 |