MonkeyBrains.net/~rudy/example Random examples

  Setting up ipnat  
High performance NAT: ipnat
I set up natd with ipfw/divert on a FreeBSD box, and the machine crumpled like a cheap tin can (the CPU maxed out). 10Mbps is too much for natd. What to do? Use ipnat!

The difference is this:

  • natd is a userland process which uses a bunch of overhead while communicating with the kernel
  • ipnat is loaded into the kernel and runs REAL fast. [man ipnat]
    ipl is the kernel module which makes the /dev/ipnat device [man ipl]
Now, the same box acts like it is made of titanium! Here is the graphed output of ipnat -s:

Configure

First off, you need to set your machine to run ipnat and to act as a gateway.
Put this stuff in your /etc/rc.conf file:
   gateway_enable="YES"
   ipfilter_enable="YES" 
   ipnat_enable="YES"
   ipnat_rules="/etc/ipnat.rules"
   
Now you need an ipnat.rules file... here is a sample one:
### ---------------------------------------------------------------------
#   Sample /etc/ipnat.rules by MonkeyBrains.net
#   Sat Mar 11 19:10:12 PST 2006
#
#   Load this like: 
#    ipnat -C -f /etc/ipnat.conf 
#    /etc/rc.d/ipnat start  (will delete active sessions...)
#   
### ---------------------------------------------------------------------

### ---------------------------------------------------------------------
### Example inbound ports for web servers
### Replace 'fxp0' with your external ethernet device.
### ---------------------------------------------------------------------

 rdr fxp0 69.22.154.11/32 port 80 -> 10.1.1.2 port 80 tcp 
 rdr fxp0 69.22.154.12/32 port 80 -> 10.1.1.3 port 80 tcp 
 rdr fxp0 69.22.154.13/32 port 80 -> 10.1.1.5 port 80 tcp 
 
 rdr fxp0 69.22.154.11/32 port 443 -> 10.1.1.2 port 443 tcp 
 rdr fxp0 69.22.154.12/32 port 443 -> 10.1.1.3 port 443 tcp 
 rdr fxp0 69.22.154.13/32 port 443 -> 10.1.1.5 port 443 tcp 
 
 rdr fxp0 69.22.154.11/32 port 22 -> 10.1.1.2 port 22 tcp 
 
### ---------------------------------------------------------------------
### Example Outgoing Mapping 
### All out going requests from the internal 10.1.1.0/24 network
### will appear to be coming from 69.22.154.14
### ---------------------------------------------------------------------

 map fxp0 10.1.1.0/24 -> 69.22.154.14/32

### ---------------------------------------------------------------------
### Example Round Robin load balancer 
### ---------------------------------------------------------------------

 # www.monkeybrains.net  69.22.154.65
 rdr fxp0 69.22.154.65/32 port 80 -> 10.1.101.65 port 80 tcp round-robin
 rdr fxp0 69.22.154.65/32 port 80 -> 10.1.102.65 port 80 tcp round-robin
 rdr fxp0 69.22.154.65/32 port 80 -> 10.1.103.65 port 80 tcp round-robin
All set? Use the /etc/rc.d/ scripts to launch ipnat or, just reboot to see if you have the settings correct (do this cautiously if you are ont on the console!).

Tune - Maximum Number of Active Sessions

The first time I set up ipnat, the NAT router stopped accepting new connections (until an existing one timed out) at 30,000 mappings. You can use ipnat -s to view the current number of mapppings.
   # ipnat -s
   mapped  in      105990558       out     100799549
   added   13276971        expired 0
   no memory       0       bad nat 731
   inuse   24837
   rules   34
   wilds   0  
   

How many connections is your ipnat tuned for? You can check! Use this ipf command (note the 30000):

   # ipf -T list | grep nattable
   ipf_nattable_sz min 0x1 max 0x7fffffff  current 2047
   ipf_nattable_max        min 0x1 max 0x7fffffff  current 30000
   
Those numbers are WAY low. You have two options at this juncture: the HARD way and the EASY way.
  • The HARD way is to recompile ipfilter:
    /usr/src/sys/modules/ipfilter && make clean
    make -DLARGE_NAT depend && make -DLARGE_NAT && make install

    I actually haven't tried this, but it should work. Actually, this method looks easy ;)
  • The EASY way is to set some variables when starting ipfilter.
    Set the following in your /etc/rc.conf:
    ipfilter_enable="YES"
    ipfilter_rules="/etc/ipf.rules"
    ipfilter_flags="-D -T ipf_nattable_sz=10009,ipf_nattable_max=300000 -E"
    ipnat_enable="YES"
    ipnat_rules="/etc/ipnat.rules" 
    
    After changing /etc/rc.conf, restart ipfilter (/etc/rc.d/ipfilter restart).

Now, you are tuned to handle 300,000 NAT Mappings! you can run ipnat -l to view all the ipnat rules and all the active sessions.

Tune - Lowering Timeouts

In conjunction with raising the maximum active sessions, try lowering the TCP timeouts for the NAT sessions. That will raise the number of Maximum Active Sessions you can handle per time period. Change your ipfilter_flags setting to this:
ipfilter_flags="-D -T ipf_nattable_sz=10009,ipf_nattable_max=300000,\ fr_tcptimeout=180,fr_tcpclosewait=60,fr_tcphalfclosed=7200,fr_tcpidletimeout=172800 -E"

The active sessions will timeout quicker, and the number of inuse sessions will go down. This will allow you to run more bandwidth through your NAT router!

Tune - Raise the number of rules in ipnat.rules

I don't have more than 127 mappings in my /etc/ipnat.rules. If you do, you will need to up some more ipf tuneables... you could up your ipf_natrules_sz and ipf_rdrrules_sz to 1023 (yes, in your rc.conf file). If you recompiled ipfilter with the -DLARGE_NAT flag, you don't need to do this.

View your current limits: ipf -T list | grep rules_sz