PUF, the Portable UNIX Firewall

Trevor Schroeder

I'll huff and I'll puff and I'll blow your house in!

-The Big Bad Wolf

UNIX has traditionally been the platform of choice for users wanting robust yet flexible IP networking. In recent years IP masquerading has become very desirable as more people have multiple machines from which they wish to access the Internet while fewer of these people have the luxury of allocating subnets to their dial-up links.

The Portable UNIX Firewall (PUF) is a portable masquerading IP firewall. It provides a service previously only available through FreeBSD's PPP daemon, the Linux kernel-level masquerading firewall, or Sun's SunScreen product. Leveraging established technology such as Berkeley sockets and libpcap, PUF requires approximately 50 lines of code to port it to a new platform. Additionally, PUF resides entirely in userspace, requires no kernel modifications, and may be run on a machine also acting as a ``normal'' router. These things have simply been unavailable previously.


Introduction

This paper describes, in some detail, the theory and operation of PUF and masquerading firewalls in general. It assumes that the reader has a grasp of the structure of the Internet. This paper should not be considered a technical guide, a functional specification, or anything more than an introduction to PUF and the subject of IP masquerading.


Why Do We Care?

More and more people have small networks at home or in remote locations. Frequently these people are forced to share one dialup Internet link among all their machines. There are only a few ways to do this effectively.

The Internet Service Provider can provide the home network with an entire subnet. This allows one computer to act as a router and route traffic between the LAN and the Internet. There is no compromise in this case. Unfortunately, very few, if any, service providers will do this for free and in the case of corporate installations, using a subnet for each dialup link rapidly exahausts the available IP address pools.

Each machine on the remote network can dialup when it needs to use the Internet. While very effective and easy to implement, this means that there can also be no more than one machine on the Internet at one time.

One machine can run proxy servers and all the other machines can use those proxies. This is an excellent option in terms of performance. Frequently proxy servers will cache content as well, providing instant response when the data is accessed for a second time. Unfortunately, this requires that applications running on the clients understand how to use the proxy.

One machine can act as a masquerading firewall. This is probably the best solution if the dialup line only has one IP address rather than an IP subnet. Additionally, this method can be used in conjunction with proxy servers to increase performance for those applications capable of using them.


What Is IP Masquerading?

Figure 1 illustrates the concept behind IP masquerading. The firewall has two or more network interfaces, similar to a regular router. One interface is on the LAN side and one is on the WAN side. All hosts on the LAN side use host G as their default gateway. When a LAN host initiates a connection to a remote host, the firewall proxies the connection. In this way, it appears that all traffic is coming from host H, the only globally known address. It is then the responsibility of the firewall to maintain mappings between IP sessions established from address H and IP sessions established on the LAN.

This is similar to the operation of NAT or a SOCKS proxy server with the exception that a masquerading firewall requires only one IP address, as opposed to NAT, and is transparent to clients, as opposed to SOCKS.

The firewall takes a number of steps necessary to make the session established between H and a remote host appear, on the LAN, as if it were established between one of the LAN hosts and the remote host.

Figure 1The concept of IP masquerading


Why PUF?

The user looking for IP masquerading previously had three options: they may use the masquerading firewall built into the Linux kernel, they may use the userland PPP daemon for FreeBSD, or they may use the SunScreen product from Sun. All of these solutions have advantages and disadvantages.

  1. Linux Firewall The Linux masquerading firewall is good and getting better all the time. It's also free. However, IP masquerading is built into the Linux kernel. This means that in order to upgrade the firewall it is necessary to recompile the kernel and restart the system. This is very problematic if the firewall is used for anything other than firewalling. It also limits the operating system choice to Linux.
  2. FreeBSD Firewall The FreeBSD PPP daemon does a very nice job as well. However, the WAN must be be on the other side of PPP interface, so it is rather limited in terms of flexibility. This solution also limits the operating system choice to FreeBSD.
  3. SunScreen Sun's SunScreen product provides masquerading support as well as a whole host of other options. However, the product is very expensive and requires Sun hardware (in some case, a dedicated machine). SunScreen runs only on SPARC-based computers.

PUF resides entirely in userland meaning that it can be modified, improved, started, and stopped all without recompiling the kernel or even shutting down the system. Furthermore, it is, as the name implies, extremely portable. There are a great many UNIXes that may support PUF eventually. It already supports Linux and DEC ULTRIX. This means that the user's choice of one flavor of UNIX versus another isn't influenced by the lack of availability of masquerading support.

In all fairness though, all is not roses. There are some significant disadvantages to the PUF architecture. Perhaps the most notable of these is the performance drawback of executing outside the kernel. Kernel level firewalls have access to all the goodies inside the kernel and can be much more efficient with packet translation since they have all the information that may not be available to user level processes. The constant system calls can also impact performance negatively as costly switches between kernel and user mode are required. However, processor is cheap and tests have shown that, at least in the case of dialup Internet access, the performance impact is negligable.


PUF Operation

The operation of PUF, while conceptually very simple, turns out to be a bit more difficult in practice. In the following sections, we'll examine the operation of PUF from interception of the hardware frame to establishing and managing a TCP connection.

Hardware Frames

Since PUF must act as a default gateway (Internet router), it is important that we understand the concept of the hardware frame. This is a topology specific frame that wraps up all network traffic. For simplicity's sake we'll use ethernet as it is the most common and most easily understood network topology.

Each ethernet frame consists of a header and data (see Figure 2). The header contains three fields:

  1. Destination Address The destination address is the six byte ethernet address that this frame is intended for.
  2. Source Address The source address identifies the hardware address that originated this frame. This is important if we wish to respond to this data.
  3. Protocol The protocol field identifies the protocol of the transmission (ARP, IP, etc.).

If the protocol is IP, we strip off the ethernet headers, recording the data first, and continue on to the IP datagram processing.

Figure 2The format of an ethernet frame.

The IP Datagram

Each piece of data on the Internet is wrapped up as an IP datagram (also known as an IP packet). The IP datagram consists of two important pieces: the header, and the payload. It is the header that presents us with the most immediate problem (see Figure 3).

Figure 3the format of an IP datagram.

While we are concerned with all the fields, the ones that are most important are as follows:

  1. Identification This field provides each packet with a unique identifier and thus allows us to identify and ignore duplicate datagrams.
  2. Protocol For each protocol in the IP suite (UDP, TCP, ICMP, etc.) we must be able to identify and handle it appropriately. This field tells the receiver of a datagram which protocol is being used.
  3. Checksum The IP datagram checksum. When spoofing traffic from the remote side of a connection, this field must be calculated by the firewall.
  4. Source Address This 32 bit address identifies the Internet host that originated the datagram. Source addresses originating on the LAN should never be seen on the WAN side of the firewall since they are most likely not routeable addresses.
  5. Destination Address This 32 bit address identifies the Internet target of the IP datagram and allows the firewall to establish the WAN connection.
  6. Options and Padding These fields are optional. The IHL (Internet Header Length) will allow the firewall to determine the length of the header segment and thus the presence or absence of the options and padding fields.

In the most basic operations, PUF strips off the IP headers, sends the data to the remote host, waits for a response, and spoofs the response data onto the LAN with the appropriate IP headers. It's usually not this easy.

UDP, the Easy Protocol

Of all the protocols in the IP suite, UDP is probably the easiest protocol for us to handle. The packet header format is relatively simple (see Figure 4). After determining that the IP datagram is UDP, we strip off the IP headers and send the UDP packet on for processing.

Figure 4Format of a UDP packet.

On the whole, processing UDP is very simple. When receiving UDP traffic off the LAN, we simply take the data out of the packet, and send it, via UDP, to it's intended host from the WAN interface. All this is accomplished using standard Berkeley sockets. Since UDP ports do not have to be bound to use (unlike TCP), we don't need to trouble ourselves with changing the source or port. However, if the source port has been bound on the WAN interface, we may never hear the response.

Probably the most difficult thing about UDP is that many of the protocols that ride on UDP embed the address of the originating host within the data portion. An example of this would be talk. The BSD talk protocol contains the IP address and UDP port of the originating request within the data portion of the UDP packet. This must then be replaced with the IP address of our firewall's WAN interface. Other programs operate similarly.

ICMP, Internet Sheepdog

After UDP, ICMP is the simplest protocol. However, lest you get the wrong idea, ICMP is a relatively complex protocol. The Internet Control Message Protocol (ICMP) provides last minute routing information, traffic management, network timing and health reports among other thigsn. There are eleven different ICMP messages. Each message has one of three sets of header fields. PUF currently supports only one of these three types and may never support the other two. This ICMP message format is detailed in Figure 5.

Figure 5Format of one type of ICMP message.

This message style is the one used by ICMP's echo, echo reply, information request, information reply, timestamp, and timestamp reply messages. These messages are commonly used by hosts to verify the status (speed, reliability) of the network.

The ICMP checksum is simply a checksum of the ICMP packet and does not rely on anything from the IP header, unlike UDP and TCP. For this reason, processing these messages is simply a matter of copying the entire ICMP message and retransmitting it from the WAN interface.

TCP, Workhorse of the Internet

Without any question, TCP traffic is the most difficult to process. With a number of advanced features, TCP is very complex. In addition to this advanced feature set and unlike UDP and ICMP, the Berkeley sockets interface does not always provide low level access to TCP sessions (this feature was not present until 4.4BSD) . This means that while we have access to the raw TCP packet on the LAN side, on the WAN side we are simply given a file descriptor. That makes it the responsibility of PUF to manage the LAN side of the TCP session manually. Figure 6 shows the format of a TCP packet.

Figure 6The format of a TCP packet

The following fields are of particular importance and difficulty to the firewall:

  1. Sequence Number This represents the position of this packet in the logical TCP stream. PUF must be careful to insure that this number is valid. If it is not, the packet must be discarded.
  2. Acknowledgement Number Assume that there are two hosts, A and B. The TCP packet in question is being sent from A to B. This field identifies how much of A's TCP stream has been received by B. PUF must manage the acknowledgement number manually as well as sending the actual acknowledgements to LAN hosts.
  3. Data Offset This field identifies the length of the TCP header and subsequently can tell us whether the option Options and Padding fields are present.
  4. Flags This field is extremely important. This indicates whether a connection is being established, reset, or closed. It also indicates whether this packet is an acknowledgement. Connection, close, and reset requests all indicate that PUF must perform certain actions.
  5. Window This indicates how much data the sender of the packet is prepared to receive.

In essence, the firewall client establishes a TCP session with PUF which then manages that session while the connection to the remote host is managed by UNIX and thus is totally transparent to PUF.

WAN to LAN

So far, we've really only seen how PUF deals with traffic on the LAN in its role as a masquerading firewall. Very little attention has been given to how it handles traffic destined from the WAN to the LAN.

This is really quite simple. When a session (ICMP, UDP, TCP) has been established through the firewall, PUF makes a session entry indicating this. Simultaneously, it establishes a connection to the remote host. In the event of UDP or ICMP this has the effect of simply setting the destination for subsequent packets. In the case of TCP, a connection attempt is made. If this fails, a RESET packet is sent to the originating LAN host indicating failure. Otherwise, it proceeds with the establishment of the session by sending the appropriate SYN message. If in the course of the session the remote host closes the connection, it is the responsibility of PUF to instruct, with a series of TCP messages, the client side to close it's connection. All other data received from the WAN socket must be wrapped up with the appropriate IP and TCP headers, including proper sequence and acknowledgement numbers, and sent on its way.

WAN to LAN data transmission is generally easier than LAN to WAN transmission, especially in the case of TCP.


Status of PUF

In this section, we will simply examine the current state of PUF. The things that work are as follows:

  1. UDP In general, UDP works very well. Name services work flawlessly as does echo and NTP (Network Time Protocol) services when used over UDP.
  2. ICMP ICMP echo, info, and timestamp messages work perfectly.
  3. TCP Firewall clients can establish TCP connections, send data, and close them. Remote hosts can also close the connection without problems. PUF will also reset stale TCP sessions if necessary.

The things that don't work properly:

  1. IP IP fragmentation is not handled. PUF is going to need to defragment the IP stream prior to transmitting it to the WAN.
  2. Protocol Exceptions There is no way to handle the idiosyncracies of particular protocols yet. For example, talk, ftp, and RealPlayer will not function through PUF currently.
  3. ICMP A great deal of ICMP is unimplemented. This includes handling/transmitting ICMP host unreachable messages, source quench messages, and ICMP redirects.
  4. TCP Much of TCP is not implemented or is implemented incorrectly. PUF does not wait for acknowledgement of data, it is working ``blind.'' Because of this, when closing a connection, it will send a spurious RESET as the client tries to acknowledge the FIN request. Overall, it assumes that the LAN can be relied on to deliver data without errors and without dropped packets.
  5. ARP Address Resolution Protocol (ARP), a protocol that allows a host to discover what hardware address owns a particular IP address, does not work under Linux. A proxy ARP entry must be entered by hand.
  6. Unexpected Situations Unexpected situations are not handled correctly. For example, if PUF receives a short TCP packet, it is still processed. Processing of packet checksums and discarding those with incorrect checksums will go great lengths towards addressing these sorts of problems.


Conclusion

Despite its many shortcomings, PUF is impressive given that it implements a transparent masquerading firewall in a relatively platform independent fashion. It has been successfully used to establish connections of various protocols from multiple machines concurrently. It is in use on a daily basis and is extremely stable, requiring restarting only to put new code in place. In short, it works as advertised and there's no reason that it can not be a fully functional masquerading firewall as capable as any proprietary, non-portable, or kernel-based one.


Further Reading

The follow materials are good starting points for anyone who is interested in more technical examinations of the issues PUF must deal with:

J. Postel. RFC 768: User Datagram Protocol. USC/Information Sciences Institute, August 1980.

J. Postel. RFC 791: Internet Protocol. Defense Advanced Research Projects Agency, September 1981.

J. Postel. RFC 792: Internet Control Message Protocol. USC/Information Sciences Institute, September 1981.

J. Postel. RFC 793: Transmission Control Protocol. Defense Advanced Research Projects Agency, September 1981.

I P. Francis, K. Egevang. RFC 1631: The IP Network Address Translator (NAT). Cray Communications, NTT Software Lab; May 1994.

S. McCanne, V. Jacobson. The BSD Packet Filter: A New Architecture for User-level Packet Capture. Lawrence Berkeley Laboratory, December 1992.


[LaTeX -> HTML by ltoh]
Trevor Schroeder (tschroed@acm.org)
Last modified: Apr 5 1998