FreeBSD Stable Release 6.0 Installer  Guide



NAT stands for Network Address Translation. To those familiar with Linux, this concept is called IP Masquerading; NAT and IP Masquerading are the same thing. One of the many things the IPF NAT function enables is the ability to have a private local area network (LAN) behind the firewall sharing a single ISP assigned IP address to the public Internet.

You ask why would someone want to do this. ISP’s normally assign a dynamic IP address to their non-commercial users. Dynamic means the IP address can be different each time you dial in and logon to your ISP, or for cable and DSL modem users when you power off and then power on your modems you can get assigned a different IP address. This IP address is how you are known to the public Internet.

Now lets say you have 5 PC’s at home and each one needs Internet access. You would have to pay your ISP for an individual Internet account for each PC and have 5 phone lines.

With NAT you only need a single account with your ISP, then cable your other 4 PC’s to a switch and the switch to the NIC in your FBSD system which is going to service your LAN as a gateway. NAT will automatically translate the private LAN IP address for each separate PC on the LAN to the single public IP address as it exits the firewall bound for the public Internet. It also does the reverse translation for returning packets.

NAT is most often accomplished without the approval, or knowledge, of your ISP, and in most cases is grounds for your ISP terminating your account if found out. Commercial users pay a lot more for their Internet connection and usually get assigned a block of static IP addresses which never change. The ISP also expects and consents to their commercial customers using NAT for their internal private LANs.

There is a special range of IP addresses reserved for NATed private LAN IP addresses.

According to RFC 1918, you can use the following IP ranges for private nets which will never be routed directly to the public Internet.

Start IP    - Ending IP
Start IP  - Ending IP
Start IP - Ending IP


NAT rules are loaded by using the ipnat command. Typically the NAT rules are stored in /etc/ipnat.rules. See man ipnat(1) for details.

When changing the NAT rules after NAT has been started, make your changes to the file containing the NAT rules, then run the ipnat command with the –CF flags to delete the internal in use NAT rules and flush the contents of the translation table of all active entries.

ipnat –CF –f /etc/ipnat.rules   # reload the NAT rules

ipnat -s       # Retrieve and display NAT statistics

ipnat -l       # List the internal NAT table entry mappings.

ipnat -v       # Turn verbose mode on to display information                  relating to rule processing and active rules/table entries.


NAT rules are very flexible and can accomplish many different things to fit the needs of non-commercial users with a single dynamic IP address or commercial users who have blocks of static IP address ranges assigned to them.

The rule syntax presented here has been simplified to what is most commonly used in a non-commercial environment. For a complete rule syntax description see the man ipnat page at ipnat(5) or ipnat(8).

# is used to mark the start of a comment and may appear at the end of a rule line or on its own line. Blank lines are ignored.

Rules contain keywords. These keywords have to be coded in a specific order from left to right on the line.

For standard NAT functionality, you only need a single NAT rule.

Create a file called /etc/ipnat.rules with the following line:

map dc0 -> 0.32

MAP = The keyword MAP starts the rule
dc0 = The interface name of the interface facing the public Internet = The IP address range of the private LAN
-> = Mandatory arrow symbol
0.32 = The IP address/netmask assigned by your ISP.
       The special keyword 0.32 tells ipnat to get the current public
       IP address of the interface specified on this statement and
       substitute it for the 0.32 keyword.


A packet arrives at the firewall from the LAN with a public destination. It passes through the outbound filter rules and NAT gets his turn at the packet and applies its rules top down; the first matching rule wins. NAT tests each of its rules against the packet's interface name and source IP address. When a packet's interface name matches a NAT rule then the source IP address (IE: private LAN IP address) of the packet is checked to see if it falls within the IP address range specified to the left of the arrow symbol on the NAT rule. On a match the packet has its source IP address rewritten with the public IP address obtained by the 0.32 keyword. NAT posts an entry in its internal NAT table so when the packet returns from the public Internet it can be mapped back to its original private IP address and then passed to the filter rules for processing.


To enable the IPNAT function add these statements to /etc/rc.conf

gateway_enable="YES"              # Enable as LAN gateway
ipnat_enable="YES"                # Start ipnat function
ipnat_rules="/etc/ipnat.rules"    # ipnat rules definition file



For networks that have large numbers of PC's on the LAN or networks with more that a single LAN, the process of funneling all those private IP addresses into a single public IP address becomes a resource problem that may cause problems with same port numbers being used many times across many NATd LAN PC's causing collisions. There are 2 ways to relieve this resource problem.

1. Mapping many LAN addresses into a single public address.

map dc0 -> 0.32

In the above rule the packet's source port is unchanged from the original source port. IPNAT has the special keyword "portmap" that changes the above rule into

map dc0 -> 0.32 portmap tcp/udp 20000:6000

This rule now shoehorns all the translated connections (which can be tcp, udp, or tcp/udp) into the port range of 20000 to 60000.

Additionally, we can make things even easier by using the "auto" keyword to tell ipnat to determine for itself which ports are available for use and allocate a proportional amount of them per address in your pool versus addresses being NATed:

map dc0 -> 0.32 portmap tcp/udp auto


2. Mapping many LAN addresses into a pool of static public addresses.

In large LANs there comes a point where there are just too many LAN addresses to fit into a single public IP address. Change the map rule to specify a range of public IP addresses as follows:

map dc0 -> portmap tcp/udp 20000:60000    or

map dc0 -> portmap tcp/udp auto           or

map dc0 -> portmap tcp/udp auto   or

map dc0 ->

Here is the pool of static public IP addresses assigned to you by your ISP. For ranges of IP address that do not lend themselves to that format you can specify it as for a 3 address pool.

An very common practice is to have a web server, email server, database server and domain name server each segregated to a different PC on the LAN. In this case the traffic from these servers still has to be NATed, but there has to be some way to direct the inbound traffic to the correct LAN PC's. IPNAT has the redirection facilities of NAT to solve this problem.  Lets say you have your web server on LAN address and your single public IP address is You would code the rule like this:

map dc0 port 80 -> port 80     or

map dc0 0/32 port 80 -> port 80             

or for a LAN domain server on LAN address that needs to receive public DNS info

map dc0 port 53 -> port 53 udp


FTP is a dinosaur left over from the time before the Internet, when research universities were connected with leased lines and FTP was used to share files among research scientists. This was a time when data security was not even an idea yet. Over the years the FTP protocol became buried into the backbone of the emerging Internet and its login ID & PW being sent in clear text was never changed to address new security concerns. FTP has two flavors: it can run in active mode or passive mode. The difference is in how the data channel is acquired. Passive mode is more secure as the data channel is acquired be the ordinal FTP session requester. For a real good explanation of FTP and its different modes read

NAT has a special built in FTP proxy option which can be specified on the NAT map rule. It can monitor all outbound packet traffic for active or passive FTP start session requests and dynamically create temporary filter rules containing only the port number really in use for the data channel. This eliminates the security risk FTP normally exposes the firewall to from having large ranges of high order port numbers open. You specify the map rule like this:

map dc0 -> 0/32 proxy port 21 ftp/tcp
map dc0 -> 0/32 proxy port 21 ftp/tcp
map dc0 -> 0/32

The first rule handles all FTP traffic for the private LAN.
The second rule handles all FTP traffic from the gateway.
The third rule handles all non-FTP traffic for the private LAN.
All the non-FTP gateway traffic is using the public IP address by default so
there is no ipnat rule needed.

The FTP map rule goes before our regular map rule. All packets are tested against the first rule from the top. First, it matches on interface name, then private LAN source IP address, and then if it's an FTP packet. If all that matches then the special FTP proxy creates temporary filter rules to let the FTP session packets pass in and out in addition to also NATing the FTP packets. ALL LAN packets that are not FTP do not match the first rule and fall through to the third rule and are tested, matching on interface and source IP, then get NATed.


Only one filter rule is needed for FTP if NAT FTP proxy is used

# Allow out LAN PC client FTP to public Internet
# Active and passive modes.
pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state


Three Filter rules are needed for FTP if no NAT FTP proxy is used

# Allow out LAN PC client FTP to public Internet
# Active and passive modes.
pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state

# Allow out passive mode data channel high order port numbers
pass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state

# Active mode let data channel in from FTP server
pass in quick on rl0 proto tcp from any to any port = 20 flags S keep state

As of FBSD 4.9 which includes IPFILTER version 3.4.31 the FTP proxy works as documented during the FTP session until the session is told to close. When the close happens packets returning from the remote FTP server are blocked and logged coming in on port 21. The NAT FTP/proxy appears to remove its temporary rules prematurely, before receiving the response from the remote FTP server acknowledging the close.

A solution is to add a filter rule like this one to get rid of these unwanted log messages or do nothing and ignore the inbound error messages in your log.

block in quick on rl0 proto tcp from any to any port = 21


This FreeBSD Installer Guide is an public domain HOW-TO.  This content may be reproduced, in any form or by any means, and used by all without permission in writing from the author.