You don't use ipnat with ipfw. ipnat is part of IPFilter.
The bare minimum rules you need for NAT to work are:
Code:
#!/bin/sh
natd -same_ports -use_sockets -dynamic -interface rl0
ipfw add divert natd ip from any to me in recv rl0
ipfw add allow ip from any to <privatesubnet> in recv rl0
ipfw add allow ip from any to <privatesubnet> out xmit rl1
ipfw add allow ip from <privatesubnet> to any in recv rl1
ipfw add divert natd ip from <privatesubnet> to any out xmit rl0
ipfw add allow ip from me to any out xmit rl0
The natd command-line will use the IP of the rl0 interface, and the
dynamic keyword will make sure that the process is always current, in case the IP changes.
The keyword
natd gets translated to the default natd port of 8668. If you use a different port in the natd command (-port <whatever>), then you put that number into the ipfw divert rule.
The keyword
me gets dynamically translated to "any IP that I am currently listening on", so that if the IP of the public interface changes (due to dhclient updates) the rules will continue to work.
The rules above can be simplified, but I find making the rules as exact and specific as possible, with separate rules for traffic coming in (in public, out private NIC) and going out (in private, out public NIC) makes it easier to understand what's going on as the packets go through the firewall.
Oh, and I don't use /etc/rc.conf to enable/configure the firewall rules. I find it a lot easier to write custom scripts that take care of everything natd/ipfw related. You can point the firewall_script option in rc.conf to the custom script, or write a custom rc.d wrapper for it (which is what we do).