IP Masquerading Code Follow-up

This is a follow-up article to the author's “IP Masquerading with Linux” in Linux Journal Issue 27.
Some Considerations

The ipfwadm command, as mentioned, is used to set up the forwarding rules for masquerading. It's also used for creating the firewall and accounting rules also supported by the Linux kernel. While we won't worry about that aspect here, it should be noted that firewall administration and IP masquerading can be tightly coupled depending upon what task you are attempting.

As well as setting the rules, ipfwadm allows you to view the current status of any masqueraded connections. For example, the command:

# ipfwadm -M -l -n

gives the following output:

IP masquerading entries
prot expire   source       destination    ports
udp  03:31.50    1110 (61009) -53
udp  03:36.67    1112 (61011) -53
tcp  14:06.91   1304 (61016) -80
tcp  14:07.17   1303 (61015) -80
tcp  14:05.62   1302 (61014) -80
tcp  01:44.79  1301 (61013) -23
The -M option is used for masquerading administration and is only used with the -l or -s options. The -l option provides the selected (in this case, masquerading) list. As you can see, the output listing shows the originating port number and the masqueraded port number in parentheses going to the destination port. Our traffic shows three DNS queries, three HTTP connections and a TELNET connection currently established.

The expire column pertains to the timers associated with masquerading. A masqueraded packet will have an expiration time if no further traffic is seen. TCP connections have two timers. The first one for the masqueraded connection and the second one for when the FIN segment is received. Each of these timers can be set with the -s option of ipfwadm. TCP connections have a default timeout value of 15 minutes and UDP, a timeout value of 5 minutes. You can change the values by giving a command such as:

# ipfwadm -M -s 1200 60 120

This command signals that TCP connections expire after 20 minutes of inactivity, a 1 minute expiration after receiving the FIN segment and 2 minutes for UDP entries. The default values will, in most cases, work well.

When I added the rule to masquerade the network, I could have indicated which interface masqueraded traffic would be sent and received. I could have extended the command as follows:

ipfwadm -F -a m -S \
        -D -W ppp0

ppp0 is the interface name for the address. While this name is optional for our example, it becomes necessary to give it if the masquerading machine has more than one internal network connection. For example, suppose deathstar had two Ethernet connections for networks and Without the -W option, traffic between the two internal networks would also be masqueraded causing a great deal of confusion.

I chose to deny all packets that were to be forwarded as my default policy using the command:

ipfwadm -F -p deny

You are allowed to set up the default policy as masquerade:

# ipfwadm -F -p masquerade
This command masquerades all connections going out and those coming in. In other words, if a host on the network external to the masquerading machine sets up a route to the internal network, they can send packets and set up connections (even ping) to internal machines. The danger is clear—your network is no longer hidden.

A certain problem did arise with the 2.0.30 kernel and ipfwadm. The IP masquerading code includes entries in the /proc/net/ip_masquerade file for ICMP as shown in Listing 2. ipfwadm has a problem with this and will give the following error:

# ipfwadm -M -l -n
IP masquerading entries
ipfwadm: unexpected input data
Try ipfwadm -h for more information.

This problem will be taken care of in the near future.

One last option to ipfwadm that I find useful is the -o option, which turns on kernel-level debugging for matched packets according to rules set by ipfwadm. Note however, this option is only effective when the kernel option for CONFIG_IP_FIREWALL_VERBOSE is selected.


As we've noted, some protocols are simply incompatible with the basic concept of masquerading. Support exists for a few of the more popular ones—FTP, CUSeeMe, VDOLive, IRC and Quake. A few applications/protocols still exist that are not supported by the 2.0.30 distribution. These include talk, the “R” programs such as rsh or rlogin, Mplayer and other games.

A great replacement for the “R” programs is ssh (Secure Shell). It functions as a direct replacement for rsh, rlogin and rcp, as well as support for X11 sessions. Its main provision is for secure communications and strong authentication; however, since it is TCP based, it works quite well with masqueraded hosts. This program is highly recommended for remote communications in general.

IP Masquerading does a very good job of hiding the internal network. If it is hidden, no one can get to you, right? Maybe this isn't a particularly desirable situation. Incoming connections can make sense for resources such as a web server, anonymous FTP server or e-mail. It could be that your Linux host could function for all of these services, and more than likely you would want to proxy incoming mail anyway. If you have a requirement for an internal web server, a couple of programs are available to forward or redirect traffic bound from the external host to an internal host. The simplest is the redir program updated by Nigel Metheringham and available from sunsite.unc.edu:/pub/Linux/system/Network/daemons/redir-0.7.tar.gz. redir is a TCP port redirector that resides on your masquerading host waiting for connections on a port and redirected to an internal server. A simple example to redirect HTTP and log all connections is:

# redir --syslog 80 80 &

You can also start redir from inetd for more convenience.

Every once in a while I'll have X terminals redirected from machines on the outside sent to “yoda” internally (when I'm not running ssh). I typically have X running on “deathstar”, so I use ports above 6000 for the redirection. For example, I set up the redirection in this way:

# redir --syslog 6001 6000 &

And on the external host I would send the xterm display to port 6001.

xterm -display &
You wouldn't want to open this up to everyone, so it's probably a good idea to implement a couple of firewall rules about incoming traffic to the masquerading host to restrict who could connect to you or start redir from inetd and use something like tcpd to restrict connections.

For UDP traffic there are a few programs available to redirect traffic from external to internal hosts. udpspoof (http://www.america.com/~chrisf/web/udpspoof.c) and udprelay (ftp://ftp.wang.com/pub/fitz/udprelay-0.2.tar.Z) are good ones. Probably the most popular though is ipautofw, which is generic enough to handle both TCP and UDP traffic. It is implemented in the Linux kernel as a part of the 2.0.30 kernel, and it is also a command interface to set up auto-forwarding rules. It's available from ftp://ftp.netis.com/pub/members/rlynch/ipautofw.tar.gz.

The ipautofw command sets rules in the /proc/net/ip_autofw file to automatically forward packets for masqueraded hosts. For example, in order to handle Real Audio traffic before the kernel module was implemented, you could use ipautofw to give the command:

ipautofw -A -r udp 6970 7170 -c tcp 7070

This associated a TCP control connection (-c<\!s>7070) with a range of return UDP packets, ports 6970 through 7170 inclusive.

Now, suppose we had that web server behind our masquerading host. We could add an auto-forwarding entry such as

# ipautofw -A -r tcp 80 80 -h

This command forwards HTTP requests to yoda ( However, ipautofw is only able to fulfill one request at a time. As long as a masquerade entry exists for that connection, all other connection requests are sent TCP “resets” until the timer expires. This is not a good scenario for a web server.

Redirecting traffic to more than one host is another problem with masqueraded redirections. Many sites have multiple web servers internally and use them to load balance the traffic. None of the utilities I've listed so far support this situation.