NAT
Table of Contents >> Optional Protocols
Contents
Description
The point of NAT is to free a network from certain limitations of IP such as the requirement for each machine to have a fixed unique address. It is primarily used when there is only one IP address to be shared by several machines, or there are multiple IP addresses that need to be flexibly assigned to multiple machines (either the machines change often or the set of IP addresses may change).
This module enables the Treck TCP/IP stack to become a NAT Router, which acts as a link between public and private networks. Resources inside the private network (clients and servers) are identified differently on the two networks. A common example is a home or office LAN with a private addressing scheme, and the public Internet with publicly assigned IP addresses.
| NAT is not a security feature and is not a substitute for a firewall. A NAT router should only be used between networks of equal trust levels. |
All initialization of a NAT router implementation of the Treck stack is first done just as if the there were no NAT feature and the stack were acting as a transparent router. This includes functions like tfUseEthernet(), tfAddInterface() and tfOpenInterface().
| Please make sure to configure the stack to allow IP Forwarding as described in the IP forwarding section of Configuring_IP_Forwarding_and_IP_Fragmentation. |
Then the NAT configuration functions are called. First, tfNatConfig() is called on each public interface. Then, different functions are called depending on the type of NAT implementation.
Configuration Macros
TM_USE_NAT_PRIVATE_CLIENT
The Inner Server NAT rules (as given by tfNatConfigInnerUdpServer(), or tfNatConfigInnerTcpServer(), or tfNatConfigInnerFtpServer()), allow access to a private server. By default data inbound to the server must occur first, in order for the rules to generate a trigger, and for the mapping to occur. In some cases it might be desirable to send outbound data from the inner server first. Define the TM_USE_NAT_PRIVATE_CLIENT macro in your trsystem.h to enhance the inner server support so that data flow can be initiated from either side (public, or private).
#define TM_USE_NAT_PRIVATE_CLIENT
TM_NAT_Q_IP_FRAGMENT
By default, a fragmented datagram will successfully be transformed using the NAT rules only if the first fragment is received first. However fragment ordering cannot be guaranteed. Define the TM_NAT_Q_IP_FRAGMENT in your trsystem.h, to allow correct NAT translation of a fragmented datagram regardless of the fragments' ordering.
#define TM_NAT_Q_IP_FRAGMENT
One IP address
The two types of resources when there is only one public IP address to work with are NAPT and Inner Servers. Several machines can access a public network through a NAT router using a single public IP address. This is technically NAPT, the "P" refers to the tricks of port number translation that are used to distinguish several processes on several machines inside the private network.
Normally, TCP and UDP port numbers distinguish several processes but only on one machine. tfNatConfigNapt() assigns a range of synthetic port numbers to a public address on a public NAT interface. NAT draws from those ports to support every TCP and UDP connection that crosses the stack between private and public networks (actually between a public network and any other).
NAT connections are timed out based on traffic. (See NAT_NTRTTL_...constants in <trmacro.h>.)
Default timeouts are:
Incomplete TCP connections 1 minute Completed TCP connections 24 hours Terminated TCP connections 1 minute unmade FTP PORT connections 5 minutes UDP DNS queries 1 minute non-DNS UDP queries 5 minutes ICMP packets with identifier 5 minutes
NAPT only supports connections initiated outbound (private client, public server). In order for a server on the private network to be accessible to a client on the public network in a NAPT environment, an Inner Server must be configured. There are three types of Inner Servers, TCP, FTP and UDP. In each case, an inner private IP address and port number are associated with an outer public IP and port. Clients on the public network call the public values. NAT translates this traffic to the private server's values. NAPT and Inner Server support only TCP and UDP traffic.
Multiple IP addresses
The two types of resources in this environment are Static and Dynamic public IP address assignments. A Static assignment associates one public IP address at a time with one private address, permanently. A Dynamic assignment does so automatically, as needed. New dynamic address associations are initiated only by outbound TCP SYN packets or by any outbound packets of another protocol (for example UDP DNS or ICMP Ping).
A Dynamic assignment expires when no packets have crossed for a certain amount of time (default 15 minutes, TM_NTRTTL_DYNAMIC in <trmacro.h>). Expired Dynamic associations become available for use by other private parties. As individual TCP and UDP sessions are not tracked on a Dynamic assignment, the timeout does not discriminate connection status or traffic type.
Static assignments would be useful for servers on the inside network or for users who require consistent full-featured access to the public network.
Dynamic and Static assignments support almost all IP traffic including TCP, UDP, and ICMP.
Mixing
Some mixing of the two schemes is possible. For example, you can configure static associations after a NAPT interface is configured if you have multiple IP's (though of course you are using only one for NAPT). Be sure to call tfNatConfigStatic() only after tfNatConfigNapt().
Forwarding of IP Multicast Data
Treck supports a subset of the requirements described in RFC 5135, IP Multicast Requirements for a NAT and a NAPT. To support the IGMPv3 forwarding requirements, a host must implement an IGMPv3 router, which Treck does not currently support. Treck NAT supports forwarding of UDP and IGMPv1/v2 packets, as described in RFC 5135.
By default, Treck NAT will not forward IP multicast packets across the private/public boundary. To change this behavior, you must first enable the code that implements the feature by uncommenting the following compile time macro in your trsystem.h.
#define TM_IP_MCAST_FORWARD
To allow forwarding of Administratively Scoped IP Multicast (RFC 2365), uncommenting the following compile time macro in your trsystem.h. By default, Treck NAT treats IP multicast addresses 239.0.0.0 to 239.255.255.255 as link local only.
#define TM_IP_MCAST_ALLOW_ADMIN_FORWARD
When the supporting code is enabled as described above, you can then globally enable the IP multicast forwarding feature by using the tfSetTreckOptions() TM_OPTION_IP_MCAST_FORWARD option, as follows. When this option is 0, which is the default, IP multicast forwarding is disabled for all interfaces.
errorCode = tfSetTreckOptions(TM_OPTION_IP_MCAST_FORWARD, 1);
Use the tfInterfaceSetOptions() TM_DEV_OPTIONS_MCAST_FORWARDING option as shown below to enable IP multicast forwarding on an interface and, more importantly, identify the inner interface to be used for multicast forwarding. The inner interface will be paired with the public interface you specify in tfNatConfig() or tfNatConfigNapt(). Without the following call on the inner interface, NAT multicast forwarding will not happen. You can also call this function to enable/disable multicast forwarding on a public interface, but the code will recognize it as public assuming you have made a prior call to tfNatConfig() on the interface.
byteVal = 1; errorCode = tfInterfaceSetOptions(innerInterfaceHandle, TM_DEV_OPTIONS_MCAST_FORWARDING, &byteVal, sizeof(byteVal));
If you are calling tfNatConfigNapt(), the following code is not needed. Otherwise, use the tfInterfaceSetOptions() TM_DEV_OPTIONS_MCAST_FORW_ADDR option to specify the public address to use for IP multicast forwarding (when a multicast packet from an inner host gets forwarded to the outside, Treck needs to change the source address in the IP header to be an public address). When tfNatConfig() is called, the first configured address on the public interface will become the default public address for IP multicast forwarding.
ttUserIpAddress ipAddr; /* ... set ipAddr to some value ... */ errorCode = tfInterfaceSetOptions(outerInterfaceHandle, TM_DEV_OPTIONS_MCAST_FORW_ADDR, &ipAddr, sizeof(ttUserIpAddress));
Finally, flag TM_DEV_IP_FORW_MCAST_ENB should be specified when calling tfNgConfigInterface() to enable multicast forwarding for each of the private and public interfaces. Note that this does not identify the inner NAT multicast interface in the same way that tfInterfaceSetOptions(..., TM_DEV_OPTIONS_MCAST_FORWARDING, ...) does.
An example of the use of NAT IP multicast forwarding can be found in txnat.c in the examples directory of your Treck installation.
Ping
Ping, using ICMP echo, is supported via Static and Dynamic IP address associations. Outbound Ping will also work on NAPT configurations that is a private client pinging a public server. Inner servers cannot be pinged however. If one were to try one would only ping the NAT router via its public interface. So this would not detect whether the inner server was up or not, just that the NAT router were up.
TraceRoute
UNIX traceroute (or Windows tracert) uses unsolicited UDP datagrams and ICMP error messages to detect routing pathways. It will work over static and dynamic connections in either direction and NAPT in the outbound direction. One cannot thoroughly TraceRoute to an inner server however, just to the NAT router, as with Ping.
FTP Servers
This NAPT implementation goes to athletic lengths to accommodate FTP servers either outside or inside (as much as any other server is supported inside). Special handling is made of every outbound FTP PORT command and PASV reply 227. NAT translates the private IP addresses and port numbers in those messages into public values.
Proxy or 3rd party FTP transfers are not supported. Non-PORT, non-PASV transfers are not supported. (UNIX "sendport" turned off.)
FTP transfers involving server port numbers other than the standard ports 21 and 20 are not supported (e.g. by entering the client command "open <host> <port>").
Private IP Addressing
The following IP addresses should be used for private networks when connected by a NAT router to the public Internet. They have been reserved specifically for this purpose by RFC 1918 "Address Allocation for Private Internets".
10.0.0.0 - 10.255.255.255 16 million class A addresses 172.16.0.0 - 172.31.255.255 1 million class B addresses 192.168.0.0 - 192.168.255.255 64 thousand class C addresses
Using other addresses may result in conflicts the NAT router can't resolve.
Triggers
The basis of this implementation of NAT is the "trigger" object. Each ttNatTrigger instance represents some possibility of interception of an incoming or outgoing packet. Every packet that comes in or out of a public NAT interface is scrutinized by all current triggers. There are several types of triggers (see TM_NTRTYPE_... in <trmacro.h>), each looking at different aspects of packets. Also, triggers are either permanent or temporary, the duration depending on type, traffic, and timing.
Some triggers recognize new TCP connections and "spawn" other triggers that live for the duration of those connections. Those session triggers look at addresses and ports. Some translate packets based on IP address alone. All permanent triggers are configured by API calls.
As the trigger list is a LIFO linked list, triggers configured or spawned *later* detect packets *earlier*, and so take precedence.
Public vs. Private
Each "public" NAT interface maintains a linked list of triggers (ttDevice.devNatTriggerHead). A "private" interface is simply one that is not public. No transformations are needed on private interfaces. The task of the NAT software is to make a public NAT interface appear private to the rest of the TCP/IP stack. Internally, NAT is associated only with the interface to the public network.
The business of each public NAT interface involves public and private addresses and ports. The system on which the stack is running is known by the public information on that exernal public network, and by the private information by the TCP/IP stack and other internal private networks.
Reference Implementation
txnat.c implements a NAT Router with a private Ethernet and a public dialup PPP connection to the public Internet.