Updated: 2022/Sep/29

Please read Privacy Policy. It's for your privacy.

IPNAT(5)                      File Formats Manual                     IPNAT(5)

       ipnat, ipnat.conf - IPFilter NAT file format

       The ipnat.conf file is used to specify rules for the Network Address
       Translation (NAT) component of IPFilter.  To load rules specified in
       the ipnat.conf file, the ipnat(8) program is used.

       For standard NAT functionality, a rule should start with map and then
       proceeds to specify the interface for which outgoing packets will have
       their source address rewritten.  Following this it is expected that the
       old source address, and optionally port number, will be specified.

       In general, all NAT rules conform to the following layout: the first
       word indicates what type of NAT rule is present, this is followed by
       some stanzas to match a packet, followed by a "->" and this is then
       followed by several more stanzas describing the new data to be put in
       the packet.

       In this text and in others, use of the term "left hand side" (LHS) when
       talking about a NAT rule refers to text that appears before the "->"
       and the "right hand side" (RHS) for text that appears after it.  In
       essence, the LHS is the packet matching and the RHS is the new data to
       be used.

       This configuration file, like all others used with IPFilter, supports
       the use of variable substitution throughout the text.

       map $nif 0/0 -> 0/32

       would become

       map ppp0 0/0 -> 0/32

       Variables can be used recursively, such as 'foo="$bar baz";', so long
       as $bar exists when the parser reaches the assignment for foo.

       See ipnat(8) for instructions on how to define variables to be used
       from a shell environment.

       Changing the source address of a packet is traditionally performed
       using map rules.  Both the source address and optionally port number
       can be changed according to various controls.

       To start out with, a common rule used is of the form:

       map le0 0/0 -> 0/32

       Here we're saying change the source address of all packets going out of
       le0 (the address/mask pair of 0/0 matching all packets) to that of the
       interface le0 (0/32 is a synonym for the interface's own address at the
       current point in time.)  If we wanted to pass the packet through with
       no change in address, we would write it as:

       map le0 0/0 -> 0/0

       If we only want to change a portion of our internal network and to a
       different address that is routed back through this host, we might do:

       map le0 ->

       In some instances, we may have an entire subnet to map internal
       addresses out onto, in which case we can express the translation as

       map le0 ->

       IPFilter will cycle through each of the 256 addresses in the address space to ensure that they all get used.

       Of course this poses a problem for TCP and UDP, with many connections
       made, each with its own port number pair.  If we're unlucky,
       translations can be dropped because the new address/port pair mapping
       already exists.  To mitigate this problem, we add in port translation
       or port mapping:

       map le0 -> portmap tcp/udp auto

       In this instance, the word "auto" tells IPFilter to calculate a private
       range of port numbers for each address on the LHS to use without fear
       of them being trampled by others.  This can lead to problems if there
       are connections being generated mire quickly than IPFilter can expire
       them.  In this instance, and if we want to get away from a private
       range of port numbers, we can say:

       map le0 -> portmap tcp/udp 5000:65000

       And now each connection through le0 will add to the enumeration of the
       port number space 5000-65000 as well as the IP address subnet of

       If the new addresses to be used are in a consecutive range, rather than
       a complete subnet, we can express this as:

       map le0 -> range
                             portmap tcp/udp 5000:65000

       This tells IPFilter that it has a range of 240 IP address to use, from to, inclusive.

       If there were several ranges of addresses for use, we can use each one
       in a round-robin fashion as followed:

       map le0 -> range
                             portmap tcp/udp 5000:65000 round-robin
       map le0 -> range
                             portmap tcp/udp 5000:65000 round-robin

       To specify translation rules that impact a specific IP protocol, the
       protocol name or number is appended to the rule like this:

       map le0 -> tcp/udp
       map le0 -> icmp
       map le0 -> gre

       For TCP connections exiting a connection such as PPPoE where the MTU is
       slightly smaller than normal ethernet, it can be useful to reduce the
       Maximum Segment Size (MSS) offered by the internal machines to match,
       reducing the likelihood that either end will attempt to send packets
       that are too big and result in fragmentation.  This is achieved using
       the mssclamp option with TCP map rules like this:

       map pppoe0 0/0 -> 0/32 mssclamp 1400 tcp

       For ICMP packets, we can map the ICMP id space in query packets:

       map le0 -> icmpidmap icmp 1000:20000

       If we wish to be more specific about our initial matching criteria on
       the LHS, we can expand to using a syntax more similar to that in
       ipf.conf(5) :

       map le0 from to ->
       map le0 from port > 1024 to ->
                    portmap 5000:9999 tcp/udp
       map le0 from ! to ->
                    portmap 5000:9999 tcp/udp

       NOTE:  negation matching with source addresses is NOT possible with map
              / map-block rules.

       The NAT code has builtin default timeouts for TCP, UDP, ICMP and
       another for all other protocols.  In general, the timeout for an entry
       to be deleted shrinks once a reply packet has been seen (excluding
       TCP.)  If you wish to specify your own timeouts, this can be achieved
       either by setting one timeout for both directions:

       map le0 0/0 -> 0/32 gre age 30

       or setting a different timeout for the reply:

       map le0 from any to any port = 53 -> 0/32 age 60/10 udp

       A pressing problem that many people encounter when using NAT is that
       the address protocol can be embedded inside an application's
       communication.  To address this problem, IPFilter provides a number of
       built-in proxies for the more common trouble makers, such as FTP.
       These proxies can be used as follows:

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

       In this rule, the word "proxy" tells us that we want to connect up this
       translation with an internal proxy.  The "port 21" is an extra
       restriction that requires the destination port number to be 21 if this
       rule is to be activated.  The word "ftp" is the proxy identifier that
       the kernel will try and resolve internally, "tcp" the protocol that
       packets must match.

       See below for a list of proxies and their relative staus.

       To associate NAT rules with filtering rules, it is possible to set and
       match tags during either inbound or outbound processing.  At present
       the tags for forwarded packets are not preserved by forwarding, so once
       the packet leaves IPFilter, the tag is forgotten.  For map rules, we
       can match tags set by filter rules like this:

       map le0 0/0 -> 0/32 proxy portmap 5000:5999 tag lan1 tcp

       This would be used with "pass out" rules that includes a stanza such as
       "set-tag (nat = lan1)".

       If the interface in which packets are received is different from the
       interface on which packets are sent out, then the translation rule
       needs to be written to take this into account:

       map hme0,le0 0/0 -> 0/32

       Although this might seem counterintuitive, the interfaces when listed
       in rules for ipnat.conf are always in the inbound , outbound order.  In
       this case, hme0 would be the return interface and le0 would be the
       outgoing interface.  If you wish to allow return packets on any
       interface, the correct syntax to use would be:

       map *,le0 0/0 -> 0/32

       A special variant of map rules exists, called map-block.  This command
       is intended for use when there is a large network to be mapped onto a
       smaller network, where the difference in netmasks is upto 14 bits
       difference in size.  This is achieved by dividing the address space and
       port space up to ensure that each source address has its own private
       range of ports to use.  For example, this rule:

       map-block ppp0 -> ports auto

       would result in being mapped to with each
       address, from to having 252 ports of its own.
       As opposed to the above use of map, if for some reason the user of
       (say) wanted 260 simultaneous connections going out, they
       would be limited to 252 with map-block but would just move on to the
       next IP address with the map command.

   Extended matching
       If it is desirable to match on both the source and destination of a
       packet before applying an address translation to it, this can be
       achieved by using the same from-to syntax as is used in ipf.conf(5).
       What follows applies equally to the map rules discussed above and rdr
       rules discussed below.  A simple example is as follows:

       map bge0 from to ->

       This would only match packets that are coming from hosts that have a
       source address matching and a destination matching  This can be expanded upon with ports for TCP like

       rdr bge0 from to any port = 25 -> port 2501 tcp

       Where only TCP packets from to port 25 will be redirected
       to port 2501.

       As with ipf.conf(5), if we have a large set of networks or addresses
       that we would like to match up with then we can define a pool using
       ippool(8) in ippool.conf(5) and then refer to it in an ipnat rule like

       map bge0 from pool/100 to any port = 25 -> port 2501 tcp

       NOTE:  In this situation, the rule is considered to have a netmask of
              "0" and thus is looked at last, after any rules with /16's or
              /24's in them, even if the defined pool only has /24's or /32's.
              Pools may also be used wherever the from-to syntax in
              ipnat.conf(5) is allowed.

       Redirection of packets is used to change the destination fields in a
       packet and is supported for packets that are moving in on a network
       interface.  While the same general syntax for map rules is supported,
       there are differences and limitations.

       Firstly, by default all redirection rules target a single IP address,
       not a network or range of network addresses, so a rule written like

       rdr le0 0/0 ->

       Will not spread packets across all 256 IP addresses in that class C
       network.  If you were to try a rule like this:

       rdr le0 0/0 ->

       then you will receive a parsing error.

       The from-to source-destination matching used with map rules can be used
       with rdr rules, along with negation, however the restriction moves -
       only a source address match can be negated:

       rdr le0 from to any ->
       rdr le0 ! from to any ->

       If there is a consecutive set of addresses you wish to spread the
       packets over, then this can be done in one of two ways, the word
       "range" optional to preserve:

       rdr le0 0/0 -> -
       rdr le0 0/0 -> range -

       If there are only two addresses to split the packets across, the
       recommended method is to use a comma (",") like this:

       rdr le0 0/0 ->,

       If there is a large group of destination addresses that are somewhat
       disjoint in nature, we can cycle through them using a round-robin
       technique like this:

       rdr le0 0/0 ->, round-robin
       rdr le0 0/0 ->, round-robin
       rdr le0 0/0 -> round-robin

       If there are a large number of redirect rules and hosts being targetted
       then it may be desirable to have all those from a single source address
       be targetted at the same destination address.  To achieve this, the
       word sticky is appended to the rule like this:

       rdr le0 0/0 ->, sticky
       rdr le0 0/0 ->, round-robin sticky
       rdr le0 0/0 -> round-robin sticky

       The sticky feature can only be combined with round-robin and the use of

       For TCP and UDP packets, it is possible to both match on the
       destination port number and to modify it.  For example, to change the
       destination port from 80 to 3128, we would use a rule like this:

       rdr de0 0/0 port 80 -> port 3128 tcp

       If a range of ports is given on the LHS and a single port is given on
       the RHS, the entire range of ports is moved.  For example, if we had

       rdr le0 0/0 port 80-88 -> port 3128 tcp

       then port 80 would become 3128, port 81 would become 3129, etc.  If we
       want to redirect a number of different ports to just a single port, an
       equals sign ("=") is placed before the port number on the RHS like

       rdr le0 0/0 port 80-88 -> port = 3128 tcp

       In this case, port 80 goes to 3128, port 81 to 3128, etc.

       As with map rules, it is possible to manually set a timeout using the
       age option, like this:

       rdr le0 0/0 port 53 -> port 10053 udp age 5/5

       The use of proxies is not restricted to map rules and outbound
       sessions.  Proxies can also be used with redirect rules, although the
       syntax is slightly different:

       rdr ge0 0/0 port 21 -> port 21 tcp proxy ftp

       For rdr rules, the interfaces supplied are in the same order as map
       rules - input first, then output.  In situations where the outgoing
       interface is not certain, it is also possible to use a wildcard ("*")
       to effect a match on any interface.

       rdr le0,* 0/0 ->

       A single rule, with as many options set as possible would look
       something like this:

       rdr le0,ppp0 port 80 ->, port 80 tcp
           round-robin frag age 40/40 sticky mssclamp 1000 tag tagged

       Whilst the above two commands provide a lot of flexibility in changing
       addressing fields in packets, often it can be of benefit to translate
       both source and destination at the same time or to change the source
       address on input or the destination address on output.  Doing all of
       these things can be accomplished using rewrite NAT rules.

       A rewrite rule requires the same level of packet matching as before,
       protocol and source/destination information but in addition allows
       either in or out to be specified like this:

       rewrite in on ppp0 proto tcp from any to any port = 80 ->
            src 0/0 dst,3128;
       rewrite out on ppp0 from any to any ->
            src 0/32 dst;

       On the RHS we can specify both new source and destination information
       to place into the packet being sent out.  As with other rules used in
       ipnat.conf, there are shortcuts syntaxes available to use the original
       address information (0/0) and the address associated with the network
       interface (0/32.)  For TCP and UDP, both address and port information
       can be changed.  At present it is only possible to specify either a
       range of port numbers to be used (X-Y) or a single port number (= X) as

       rewrite in on le0 proto tcp from any to any port = 80 ->
            src 0/0,2000-20000 dst,port = 3128;

       There are four fields that are stepped through in enumerating the
       number space available for creating a new destination:

       source address

       source port

       destination address

       destination port

       If one of these happens to be a static then it will be skipped and the
       next one incremented.  As an example:

       rewrite out on le0 proto tcp from any to any port = 80 ->
            src,5000-5999 dst,6000-6999;

       The translated packets would be:

       1st src=,5000 dst=,6000

       2nd src=,5000 dst=,6000

       3rd src=,5001 dst=,6000

       4th src=,5001 dst=,6000

       5th src=,5001 dst=,6001

       6th src=,5001 dst=,6001

       and so on.

       As with map rules, it is possible to specify a range of addresses by
       including the word range before the addresses:

       rewrite from any to any port = 80 ->
            src - dst -;

       If you'd like to send packets to a UDP socket rather than just another
       computer to be decapsulated, this can be achieved using a divert rule.

       Divert rules can be be used with both inbound and outbound packet
       matching however the rule must specify host addresses for the outer
       packet, not ranges of addresses or netmasks, just single addresses.
       Additionally the syntax must supply required information for UDP.  An
       example of what a divert rule looks ike is as follows:

       divert in on le0 proto udp from any to any port = 53 ->
            src,54 dst,5300;

       On the LHS is a normal set of matching capabilities but on the RHS it
       is a requirement to specify both the source and destination addresses
       and ports.

       As this feature is intended to be used with targetting packets at
       sockets and not IPFilter running on other systems, there is no rule
       provided to undivert packets.

       NOTE:  Diverted packets may be fragmented if the addition of the
              encapsulating IP header plus UDP header causes the packet to
              exceed the size allowed by the outbound network interface.  At
              present it is not possible to cause Path MTU discovery to happen
              as this feature is intended to be transparent to both endpoints.
              Path MTU Discovery If Path MTU discovery is being used and the
              "do not fragment" flag is set in packets to be encapsulated, an
              ICMP error message will be sent back to the sender if the new
              packet would need to be fragmented.

       This section deals with options that are available with all rules.

       purge  When the purge keyword is added to the end of a NAT rule, it
              will cause all of the active NAT sessions to be removed when the
              rule is removed as an individual operation. If all of the NAT
              rules are flushed out, it is expected that the operator will
              similarly flush the NAT table and thus NAT sessions are not
              removed when the NAT rules are flushed out.

       NOTE: Rules in ipnat.conf are read in sequentially as listed and loaded
       into the kernel in this fashion BUT packet matching is done on netmask,
       going from 32 down to 0.  If a rule uses pool or hash to reference a
       set of addresses or networks, the netmask value for these fields is
       considered to be "0".  So if your ipnat.conf has the following rules:

       rdr le0 port 80 -> 3132 tcp
       rdr le0 port 80 -> 3131 tcp
       rdr le0 from any to pool/100 port 80 -> port 3130 tcp
       rdr le0 port 80 -> 3129 tcp
       rdr le0 port 80 -> 3128 tcp

       then the rule with will match first, regardless of where it
       appears in the ordering of the above rules.  In fact, the order in
       which they would be used to match a packet is:

       rdr le0 port 80 -> 3128 tcp
       rdr le0 port 80 -> 3129 tcp
       rdr le0 port 80 -> 3131 tcp
       rdr le0 port 80 -> 3132 tcp
       rdr le0 from any to pool/100 port 80 -> port 3130 tcp

       where the first line is actually a /32.

       If your ipnat.conf file has entries with matching target fields (source
       address for map rules and destination address for rdr rules), then the
       ordering in the ipnat.conf file does matter.  So if you had the

       rdr le0 from to port 80 -> 3129 tcp
       rdr le0 from to port 80 -> 3128 tcp

       Then no packets will match the 2nd rule, they'll all match the first.

       In all of the examples above, where an IPv4 address is present, an IPv6
       address can also be used. All rules must use either IPv4 addresses with
       both halves of the NAT rule or IPv6 addresses for both halves. Mixing
       IPv6 addresses with IPv4 addresses, in a single rule, will result in an

       For shorthand notations such as "0/32", the equivalent for IPv6 is
       "0/128". IPFilter will treat any netmask greater than 32 as an implicit
       direction that the address should be IPv6, not IPv4.  To be unambiguous
       with 0/0, for IPv6 use ::0/0.

       IP Filter comes with a few, simple, proxies built into the code that is
       loaded into the kernel to allow secondary channels to be opened without
       forcing the packets through a user program.  The current state of the
       proxies is listed below, as one of three states:

       Aging - protocol is roughly understood from the time at which the proxy
              was written but it is not well tested or maintained;

       Developmental - basic functionality exists, works most of the time but
              may be problematic in extended real use;

       Experimental - rough support for the protocol at best, may or may not
              work as testing has been at best sporadic, possible large scale
              changes to the code in order to properly support the protocol.

       Mature - well tested, protocol is properly understood by the proxy;

       The currently compiled in proxy list is as follows:

       FTP - Mature
              (map ... proxy port ftp ftp/tcp)

       IRC - Experimental
              (proxy port 6667 irc/tcp)

       rpcbind - Experimental

       PPTP - Experimental

       H.323 - Experimental
              (map ... proxy port 1720 h323/tcp)

       Real Audio (PNA) - Aging

       DNS - Developmental
              (map ... proxy port 53 dns/udp { block .cnn.com; })

       IPsec - Developmental
              (map ... proxy port 500 ipsec/tcp)

       netbios - Experimental

       R-command - Mature
              (map ... proxy port shell rcmd/tcp)

       /usr/share/examples/ipf  Directory with examples.

       ipnat(4), hosts(5), ipf(5), services(5), ipf(8), ipnat(8)