Blocking incoming forged packets, as discussed previously, is just about the only common use of filtering solely by address. Most other uses of packet filtering involve filtering by service, which is somewhat more complicated.
From a packet filtering point of view, what do the packets associated with particular services look like? As an example, we're going to take a detailed look at Telnet. Telnet allows a user to log in to another system, as if the user had a terminal directly connected to that system. We use Telnet as an example because it is fairly common, fairly simple, and from a packet filtering point of view representative of several other protocols such as SMTP and NNTP . We need to look at both outbound and inbound Telnet service.
For detailed discussions of the packet filtering characteristics of other protocols, see Chapter 8 .
Let's look first at outbound Telnet service, in which a local client (a user) is talking to a remote server. We need to handle both outgoing and incoming packets. ( Figure 6.8 shows a simplified view of outbound Telnet.)
The outgoing packets for this outbound service contain the user's keystrokes and have the following characteristics:
The incoming packets for this outbound service contain the data to be displayed on the user's screen (for example, the "login:" prompt) and have the following characteristics:
Note the similarities between the header fields of the outgoing and incoming packets for Telnet. The same addresses and port numbers are used; they're just exchanged between source and destination. If you compare an outgoing packet to an incoming packet, the source and destination addresses are exchanged, and the source and destination port numbers are exchanged.
Why is the client port - the source port for the outgoing packets, and the destination port for the incoming packets - restricted to being greater than 1023? This is a legacy of the BSD versions of UNIX , to which almost all UNIX networking code can trace its origins. BSD UNIX reserved ports from 0 to 1023 for local use only by root. These ports are normally used only by servers, not clients. (The major exceptions are the BSD "r commands" like rcp and rlogin , as we'll discuss in Chapter 8 .) Other operating systems, even those that have no concept analogous to a privileged root user, e.g., Macintosh and MS-DOS systems, have followed this convention. When client programs need a port number for their own use, and any old port number will do, the programs are assigned a port above 1023.
The incoming packets for the inbound Telnet service contain the user's keystrokes and have the following characteristics:
The outgoing packets for this inbound Telnet service contain the server responses (the data to be displayed for the user) and have the following characteristics:
Again, note the similarities between the relevant headers of the incoming and the outgoing packets: the source and destination addresses are exchanged and that the source and destination ports are exchanged.
The following table illustrates the various types of packets involved in inbound and outbound Telnet services.
Note that Y and Z are both random (from the packet filtering system's point of view) port numbers above 1023.
If you want to allow outgoing Telnet, but nothing else, you would set up your packet filtering like this:
Making filtering decisions based on source port is not without its risks. There is one fundamental problem with this type of filtering: you can trust the source port only as much as you trust the source machine.
Suppose you mistakenly assume the source port is associated with a particular service. Someone who is in control of the source machine, e.g., someone with root access on a UNIX system (or anyone at all with a networked PC ), could run whatever client or server they wanted on a "source port" that you're allowing through your carefully configured packet filtering system. Furthermore, as we've discussed above, you can't necessarily trust the source address to tell you for certain what the source machine is; you can't tell for sure if you're talking to the real machine with that address, or to an attacker who is pretending to be that machine.
What can you do about this situation? You want to restrict the local port numbers as much as possible, regardless of how few remote ports you allow to access them. If you only allow inbound connections to port 23, and if port 23 has a Telnet server on it that is trustworthy (a server that will only do things that a Telnet client should be able to tell it to do), it doesn't actually matter whether the program that is talking to it is a genuine Telnet client or not. Your concern is to limit inbound connections to only ports where you are running trustworthy servers, and to be sure that your servers are genuinely trustworthy. Chapter 8 discusses how you can achieve these ends for various services.
Because many services use random ports above 1023 for clients, and because some services use ports above 1023 for servers, you will often need to accept inbound packets for ports that might have untrustworthy servers on them. In TCP , you can accept inbound packets without accepting inbound connections by requiring the ACK bit to be set. With UDP , you have no such option, because there is no equivalent to the ACK bit. Fortunately, very few protocols used across the Internet are UDP -based.