There are two major reasons why you might want to use packet filtering implementations on general-purpose computers. First, you may want to use a general-purpose computer as a router (either providing only packet filtering, or as a single-box firewall that provides both packet filtering and proxying). In this case, you are using the general-purpose computer to provide the same sort of packet filtering services that a router would provide. Second, you may be using the general-purpose computer as a bastion host, and you may want to use packet filtering on the computer as a security measure to protect the computer itself.
Earlier Linux kernels used a filtering system called ipfw (which was a port of a BSD filtering system) and a configuration utility called ipfwadm. ipchains is a new filtering system, which provides more functionality than ipfw. ipchains allows you to convert configuration files from ipfwadm to ipchains.
The filtering performed by ipchains is done entirely in the kernel, and it requires only a single external utility to initialize the filtering rules. This means that it is possible to build a complete Linux filtering system that will fit on a single 1.44 MB floppy disk. The Linux Router Project is doing exactly this (see Appendix A, "Resources", for more information about the Linux Router Project).
Linux also has a facility called masquerading, which is used with ipchains to provide network address translation for both TCP and UDP. Masquerading keeps track of TCP connection state and supports timeout-based UDP requests and responses. Because it must be used with packet filtering, it can be considered a dynamic packet filtering system. In addition to providing straightforward network address translation for simple TCP and UDP protocols, Linux masquerading allows additional kernel modules to be loaded for more complicated protocols (for instance, FTP and RealAudio, which require reverse TCP connections or additional UDP ports).
There are three standard chains, called the input, output, and forward chains. All packets coming in to the machine are passed through the input chain, and all packets going out of the machine are passed though the output chain. The forward chain is used for packets that need to be sent to a different network interface from the one they were received on. Thus, if a packet is received for the machine, it's matched against the input chain; if the machine generates a packet, it's matched against the output chain. If the machine is acting as a router and gets a packet addressed to some other machine, the packet will be matched against all three chains.
The standard chains each have a default policy, which is applied when no rules match. It is also possible to create additional, user-defined, chains. If no rules match when checking a user-defined chain, processing will continue at the point where the chain was called.
The conditions in a rule can be based on any of the following:
Whether the packet is a TCP start-of-connection packet.
The network interface. This is the interface the packet came in on for the input chain and the destination interface for the output and forward chains.
A rule can also make a log entry, which contains information about the action that was taken, the time, and a summary of the packet headers. Logging is performed by syslog.
The IP address of the firewall is used in communicating with remote services. For simple protocols, masquerading alters only IP header information, including IP addresses, port numbers, and TCP sequence and acknowledgment numbers. Masquerading uses the IP address of the host doing the masquerading as the externally visible address, and maps the port number into one from a pool of 4096 ports starting at 61000. This fixed allocation of ports does limit Linux masquerading to 4096 simultaneous TCP connections and 4096 UDP ports. At the time of writing, Linux kernels allocate only ports less than 32768, so the ports used for masquerading will never conflict with ports used for other purposes.
Linux masquerading is also capable of dealing with more complicated protocols, such as FTP or RealAudio, which might require reverse TCP connections or additional UDP ports. Support for new protocols can be added by dynamically loading new kernel modules.
This is best explained by describing how the masquerading module for FTP works. As we discuss in Chapter 17, "File Transfer, File Sharing, and Printing", FTP is a tricky protocol to support through a firewall because it normally involves a connection from the server to the client. An FTP client opens a control channel to a desired FTP server. At the point where data is to be transferred, the client issues a PORT command that contains the client IP address and a port number the client expects to receive the data on. The FTP server uses this information to open a new TCP connection to the client in order to transfer the data.
For masquerading to work, it must intercept the PORT command from the client. The FTP masquerading module does this by listening to the commands sent over all FTP control channels. When it sees a PORT command, it does two things; first, it sets up a temporary port on the masquerading host, which is forwarded to the port the client specified. Next, it rewrites the IP packet containing the PORT command with the IP address of the firewall and the temporary port. When an incoming connection to the temporary port is made, it is forwarded to the client. Figure 8-7 describes this process.
We also recommend that you turn on fragment reassembly. See Chapter 4, "Packets and Protocols ", for information on IP fragmentation and why this is important.
asquerading is included as a standard part of Linux 2.1 and 2.2 kernel source code. It does need to be enabled when the kernel is compiled, and it also depends on the Linux firewalling code. The kernel compile-time option for enabling Linux masquerading is CONFIG_IP_MASQUERADE=Y.
In order to use all of the facilities of ipchains and masquerading, you will also need the ipchains and ipmasqadm commands used to define the filtering and masquerading rules.
ipchains rules are built incrementally; when the machine boots, it installs the rules in order, so there will be a brief period while it is initializing when the chain is not fully built, and the default policy will be used before the end of the chain has been configured. If the default policy is to accept packets, you may accept packets that you would otherwise have denied. You should therefore put in an initial explicit default policy that denies packets.
One tempting way to avoid this problem is to build the chains before you actually configure the network interfaces (if you can't receive the packets, there's no need to worry about what you do with them). In most situations, this won't work because rules will be rejected if they refer to network interfaces that haven't been configured. If you have a configuration of the kind we recommend, you will have to configure the network interface before you can build the chains you are actually going to use. Thus, you will end up using two bootup scripts for the ipchains configuration. The first script will initialize default deny policies for each chain; the second will load the rules you wish to use. When combined with the network interface configuration scripts, this will result in the following three-stage process:
Load the real ipchains rules you're going to use.
When masquerading is operating, the standard Unix netstat program does not list masqueraded ports. This means that the machine will be accepting packets for ports that don't show up when you run netstat, which may be disconcerting to experienced network administrators.
ipfilter uses a list of rules contained in a single configuration file. Unlike ipchains, ipfilter checks all rules in sequence, and the last rule that successfully matches determines the fate of a packet. This can be a great source of confusion. Imagine a filtering configuration file containing only the following rules:
This will pass all packets because the second rule is the last rule that matches. Fortunately an ipfilter rule can specify the "quick" keyword, which if the rule matches, will terminate the rule checking at that point. The following rules would block all traffic:block in all pass in all
Rules may be arranged into groups, which allows you to make more complicated configurations quite easily. A group has a head rule, which is checked to determine whether the rest of the rules in the group are executed. If the group is executed, the rules in it are handled in the normal way. At the end of the group, processing continues at the next line.block in quick all pass in all
The conditions in a rule can be based on any of the following:
The source and destination IP addresses. Addresses can be specified as a variable-length subnet (for example 192.168.8.0/22) or a network address with a mask, and negation is allowed (you can specify "all addresses except those that match this address and mask").
Process the packet, keeping state information to make sure that all TCP packets are part of a valid TCP conversation, with appropriate settings of SYN and ACK and appropriate sequence numbers.
ipchains is much stronger as a network address translation system. The network address translation functionality provided by ipfilter is minimal and is not dynamically updatable. ipchains is also provided as part of Linux, so that it doesn't require separate integration.
ipfilter provides filtering capabilities that ipchains does not (allowing you to filter on IP options and providing more flexible handling of TCP options, for instance), and it is more flexible about the responses it gives to blocked packets. Its packet duplication features are useful for feeding packets to intrusion detection systems.
The architecture of ipchains makes it much easier to extend than ipfilter, so it's likely that the extra ipfilter features will eventually show up in ipchains. However, ipchains is relatively tightly integrated with the Linux kernel, which will slow down its spread to other operating systems.
[20]See Section 14.1, "Remote Procedure Call (RPC)", for more information about PPTP.
This packet filtering is extremely minimal, and there are very few situations where it's possible to use it. It is useful for machines that are using PPTP, or that are bastion hosts providing single services like HTTP. Some of the problems with it are not immediately obvious and are frequently unpleasant surprises to people trying to use this packet filtering:
Windows 2000 provides packet filtering in a third place as part of its implementation of IPsec (IPsec is discussed further in Chapter 14, "Intermediary Protocols"). This packet filtering is comparable to the Routing and Remote Access Service filtering for Windows NT 4, except that it is possible to combine filters into sets (allowing you to mix allow and deny rules), and a rule can apply four possible actions:
Request IPsec protections on all packets that match, but accept them if IPsec is not available.
Ironically, the most powerful packet filtering package that Microsoft makes available for Windows NT is actually part of Microsoft's Proxy Server. While it still does not provide all of the features that a packet filtering router would provide, it does include alerting and logging options, specification of port ranges, and filtering of fragments. As of this writing, a new version of Proxy Server is due out shortly, and it is expected to have still more packet filtering features.