Skip to content

Instantly share code, notes, and snippets.

@pcjunk
Last active March 1, 2025 15:29
Show Gist options
  • Select an option

  • Save pcjunk/caf0694d8082875422f13c310e3e86b6 to your computer and use it in GitHub Desktop.

Select an option

Save pcjunk/caf0694d8082875422f13c310e3e86b6 to your computer and use it in GitHub Desktop.
Minimal NAT64 /etc/ipfw.rules
IPV4_HOST="__IPV4_HOST__"
IPV6_HOST="__IPV6_HOST__"
IPV4_NAT="__IPV4_NAT__/32"
NAT64_HOST="__NAT64_HOST__"
NAT64_NETWORK="__NAT64_NETWORK__"
LOG=${LOG:+log}
# Flush
ipfw -q flush
ipfw -q nat64lsn NAT64 destroy
# Create nat64 instance
ipfw nat64lsn NAT64 create log prefix4 ${IPV4_NAT} prefix6 64:ff9b::/96
# Allow established connections
ipfw add check-state
# Allow incoming icmp echo-requests (keep-state to allow icmp from nat64)
ipfw add allow ${LOG} icmp from any to ${IPV4_HOST} icmptypes 8 keep-state
ipfw add allow ${LOG} icmp from any to ${IPV4_NAT} icmptypes 8 keep-state
# Allow incoming SSH/DNS (IPv4)
ipfw add allow ${LOG} ip4 from any to ${IPV4_HOST} 22 keep-state
ipfw add allow ${LOG} ip4 from any to ${IPV4_HOST} 53 keep-state
# Enable NAT64 - tag matched packets to skip host rules
ipfw add nat64lsn NAT64 ${LOG} tag 64 ip6 from ::1 to 64:ff9b::/96 in
ipfw add nat64lsn NAT64 ${LOG} tag 64 ip6 from ${IPV6_HOST} to 64:ff9b::/96 in
ipfw add nat64lsn NAT64 ${LOG} tag 64 ip6 from ${NAT64_NETWORK} to 64:ff9b::/96 in
ipfw add nat64lsn NAT64 ${LOG} ip4 from any to ${IPV4_NAT} in
# Allow outgoing IPv4 (keep-state to skip nat64 but avoid nat64 tagged packets)
ipfw add allow ${LOG} ip4 from ${IPV4_HOST} to any keep-state not tagged 64
# Allow all (log)
ipfw add allow log all from any to any
# Set NAT64 route
route -6 del 64:ff9b::/96
route -6 add 64:ff9b::/96 ::1
# Ensure direct output is disabled
sysctl net.inet.ip.fw.nat64_direct_output=0
IPV4_HOST="__IPV4_HOST__/32"
IPV6_HOST="__IPV6_HOST__/128"
IPV4_NAT="__IPV4_NAT__/32"
NAT64_HOST="__NAT64_HOST__/128"
NAT64_NETWORK="__NAT64_NETWORK__"
LINK_LOCAL="fe80::/64,ff02::/8"
SERVICES="22,53"
LOG=${LOG:+log}
# Flush
ipfw -q flush
ipfw -q nat64lsn NAT64 destroy
# Create nat64 instance
ipfw nat64lsn NAT64 create log prefix4 ${IPV4_NAT} prefix6 64:ff9b::/96
# Allow established connections
ipfw add check-state
# Allow incoming icmp echo-requests (keep-state to allow icmp from nat64)
ipfw add allow ${LOG} icmp from any to ${IPV4_HOST},${IPV4_NAT} icmptypes 8 keep-state
# Allow incoming IPv4 services (keep state to skip nat64)
ipfw add allow ${LOG} ip4 from any to ${IPV4_HOST} ${SERVICES} keep-state
# Enable NAT64 - tag matched packets to skip host rules
ipfw add nat64lsn NAT64 ${LOG} tag 64 ip6 from ::1,${IPV6_HOST},${NAT64_NETWORK} to 64:ff9b::/96 in
ipfw add nat64lsn NAT64 ${LOG} tag 46 ip4 from any to ${IPV4_NAT} in
ipfw add allow ${LOG} ip from any to any tagged 64,46
# Allow outgoing IPv4 (keep-state to skip nat64 but avoid nat64 tagged packets)
ipfw add allow ${LOG} ip4 from ${IPV4_HOST} to any keep-state not tagged 64
# Allow incoming/outgoing icmp6
ipfw add allow ${LOG} icmp6 from any to any
# Allow incoming IPv6 services
ipfw add allow ${LOG} ip6 from any to ${IPV6_HOST},${LINK_LOCAL} ${SERVICES} keep-state
# Allow IPv6
ipfw add allow ${LOG} ip6 from ${IPV6_HOST},${NAT64_NETWORK} to any keep-state
ipfw add allow ${LOG} ip6 from any to ${NAT64_NETWORK},${LINK_LOCAL} keep-state
# Deny all (always log)
ipfw add deny log all from any to any
# Set NAT64 route
route -6 del 64:ff9b::/96
route -6 add 64:ff9b::/96 ::1
# Ensure direct output is disabled
sysctl net.inet.ip.fw.nat64_direct_output=0
@spmzt
Copy link

spmzt commented Mar 1, 2025

Thanks! not tagged 64 was awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment