So I just learned that there's two methods to doing NAT in FreeBSD. The apparently old natd + divert way, which is documented in the handbook, and the new in-kernel ipfw+nat way, that is randomly documented by Google. Is anyone ever going to update the handbook to over ipfw+NAT? The man page isn't exactly exhaustive on that topic.
Anyways, I'm at my wits' end over trying to get what should be a bog-simple NAT setup going for a wired LAN. For starters, my appliance has the following interfaces:
Interfaces: 6x GigE (em0 to em5), 1x ath0 via AR9462
WAN: em0 (SYNCDHCP)
LAN: bridge0 (em1 + em2)
WLAN: wlan0
For simplicity's sake, ignore the fact there's a WLAN interface. I've got hostapd and dhcpd all working on that interface and wifi devices connect and get an address. So once I get LAN NAT working, WLAN NAT should also just work. My ISP is a cable company, so the WAN is using SYNCDHCP to make sure there's an address assigned before the rest of the system tries to come up. Being that the interface ports are em*, I've already got all of the hardware bits, like TSO, LRO, TX/RX CSUM, etc, turned off. The bridge setup is currently using two em interfaces because I might use the other ports for span/mirroing traffic to a security appliance (not sure just yet).
I fought for a few hours with using natd + divert, but honestly didn't have a clue if I was doing that right. Then I stumbled across this post from 2017:
forums.freebsd.org
That confused me at first, until I realized that there was another NAT capability.
I fiddled with it, but could not get that example to work. I then found an older post from 2015:
forums.freebsd.org
Using that extremely simple script example, I could finally ping from my LAN out to the WAN and hit Google's quad-8 system. However, that's a terrible firewall. I tried to adapt some of the stuff from the first URL by having two NAT rules, putting check-state and the TCP/UDP/ICMP rules between the two NAT rules, and using "out xmit ${wan}". No dice.
Working script:
The bit with using 'set' I got from fwbuilder.
Non-working script:
I also have
Which I think is the right setting? And IPv4 forwarding is also enabled. As far as I can tell, there's nothing else missing. It's some misunderstanding I have with the correct order of the rules, and correct rule directionality combined with getting the NAT rules right. If I can get the non-working script working, I think it'll be fairly easy to fix the actual firewall script I've put together. Said script denys all inbound and only allows select protocols outbound, plus some antispoofing rules. Nothing terribly complicated.
Anyways, I'm at my wits' end over trying to get what should be a bog-simple NAT setup going for a wired LAN. For starters, my appliance has the following interfaces:
Interfaces: 6x GigE (em0 to em5), 1x ath0 via AR9462
WAN: em0 (SYNCDHCP)
LAN: bridge0 (em1 + em2)
WLAN: wlan0
For simplicity's sake, ignore the fact there's a WLAN interface. I've got hostapd and dhcpd all working on that interface and wifi devices connect and get an address. So once I get LAN NAT working, WLAN NAT should also just work. My ISP is a cable company, so the WAN is using SYNCDHCP to make sure there's an address assigned before the rest of the system tries to come up. Being that the interface ports are em*, I've already got all of the hardware bits, like TSO, LRO, TX/RX CSUM, etc, turned off. The bridge setup is currently using two em interfaces because I might use the other ports for span/mirroing traffic to a security appliance (not sure just yet).
I fought for a few hours with using natd + divert, but honestly didn't have a clue if I was doing that right. Then I stumbled across this post from 2017:

Solved - ipfw share internet
hello,i'am a newbie in ipfw, the scenario is this: i have a server that run 2 network interfaces,in the future it will be a squid proxy..but for now, step by step.... the lan is 192.168.50.0 (bce1) the wan if 200.xxx.xxx.xxx (bce0) so far i got this ipfw -f flush ipfw add 497 check-state...
I fiddled with it, but could not get that example to work. I then found an older post from 2015:

IPFW - IPFW Kernel NAT is not working
Please help. I have version 10.2-RELEASE with kernel NAT configured. Ping request pass to external adapter, but don't route back to internal. Internal (ue1): # tcpdump -ni ue1 | grep 5.255.255.5 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ue1...
Using that extremely simple script example, I could finally ping from my LAN out to the WAN and hit Google's quad-8 system. However, that's a terrible firewall. I tried to adapt some of the stuff from the first URL by having two NAT rules, putting check-state and the TCP/UDP/ICMP rules between the two NAT rules, and using "out xmit ${wan}". No dice.
Working script:
Code:
ipfw="/sbin/ipfw -q"
wan="em0"
lan="bridge0"
wifi="wlan0"
${ipfw} set disable 1
${ipfw} nat 1 config log if ${wan} deny_in same_ports unreg_only reset
${ipfw} add 0010 set 1 nat 1 ip from any to any via ${wan}
${ipfw} add 0020 set 1 reass all from any to any in
${ipfw} add 0030 set 1 check-state
${ipfw} add 0040 set 1 allow ip from any to any
${ipfw} set swap 0 1
${ipfw} delete set 1
The bit with using 'set' I got from fwbuilder.
Non-working script:
Code:
ipfw="/sbin/ipfw -q"
wan="em0"
lan="bridge0"
wifi="wlan0"
${ipfw} set disable 1
${ipfw} nat 1 config log if ${wan} deny_in same_ports unreg_only reset
${ipfw} add 0010 set 1 nat 1 ip from any to any in recv ${wan}
${ipfw} add 0020 set 1 reass all from any to any in
${ipfw} add 0030 set 1 check-state
${ipfw} add 0040 set 1 allow tcp from any to any out xmit ${wan} setup keep-state
${ipfw} add 0041 set 1 allow udp from any to any out xmit ${wan} keep-state
${ipfw} add 0042 set 1 allow icmp from any to any out xmit ${wan} keep-state
${ipfw} add 0050 set 1 nat 1 ip from any to any out xmit ${wan}
${ipfw} set swap 0 1
${ipfw} delete set 1
I also have
Code:
net.inet.ip.fw.one_pass=0
Last edited: