Restricting Access with iptables

Creating a packet filter firewall requires designing a series of rules, each of which corresponds to a single call to iptables in a firewall script. In addition, you must set the default policy, which is what the chain is to do when no rule matches. Before you embark on this task, though (and at various times during your firewall development), you may want to review the present configuration.

Checking the Configuration

The iptables program responds to the -L parameter by displaying a list of the rules that make up a given table. You may optionally pass a table name by using the -t parameter. For instance, Listing 20.1 shows how to view the current filter table.

Listing 20.1: Sample Use of iptables to View Firewall Configuration

# iptables -L-t filter

Chain INPUT (policy ACCEPT)

target prot opt source destination

DROP all - 172.24.0.0/16 anywhere

Chain FORWARD (policy DROP)

target prot opt source destination

Chain OUTPUT (policy ACCEPT)

target prot opt source destination

The default table is filter, so omitting -t filter from this command produces the same output. The table summarized by this output is nearly empty; the FORWARD and OUTPUT chains have no rules, and the INPUT chain has just one rule—it drops all input from the 172.24.0.0/16 network. Although the format of information presented by iptables -L isn't exactly equivalent to what you use when you create a rule, the similarities are strong enough that you should be able to interpret the output once you know how to create rules.

Setting the Default Policy

One critically important consideration when designing a firewall is the default policy, which is what the firewall does with packets that don't match any rules in a chain. In fact, in the standard filter table, there are three default policies, one each for the INPUT, FORWARD, and OUTPUT chains. The default policy corresponds to an action that the system can take. Three options are common:

ACCEPT An ACCEPT action causes the system to accept the packet and pass it on to the next chain or system. For instance, if the INPUT chain's default policy is ACCEPT, any packet that doesn't match a rule is passed on to the target program (assuming one is using the specified port).

DROP This action causes the system to ignore the packet—to "drop it on the floor," as it were. To the system that sends the packet (which could be a remote system or a local program, depending on the chain involved), it appears that the packet was lost due to a routing error or the like.

REJECT This action is much like DROP, except that the kernel returns a code to the calling system or program indicating that the packet has been rejected. This behavior is similar to what would happen if no program were using the target port. This action requires that you compile explicit support for it into the kernel, either in the main kernel file or as a module. Unfortunately, REJECT doesn't work as a default policy, but you can use it as a target for more specific rules.

Typing iptables -L reveals the default policy, as shown in Listing 20.1—in that example, the INPUT and OUTPUT chains have a default policy of ACCEPT, whereas the FORWARD chain has a default policy of DROP. To change the default policy, you should first flush the chain of all its rules by passing the -F parameter and the chain name to iptables. You can then pass the -P parameter to iptables, along with the policy name. In both cases, you can optionally include -t and the table name:

# iptables -t filter -F FORWARD

# iptables -F INPUT

# iptables -P FORWARD DROP

# iptables -t filter -P INPUT DROP

As a general rule, the safest default policy is a closed one—that is, to use DROP. When you use such a default policy, you must explicitly open ports with firewall rules. This means that if a server is running on your computer without your knowledge, it doesn't pose a security risk because packets can't reach it and it can't send packets. Likewise, if you close outgoing ports, malicious software or individuals may not be able to launch attacks on others unless they use the protocols you've approved for use. On the other hand, a default closed policy means that you must design your firewall rules very carefully; an oversight can cause an important client or server to stop working.

Tip Although you cannot set the default policy to REJECT, you can achieve much the same end by other means. Specifically, you can insert a rule at the end of the chain that uses REJECT on all packets not matched by previous rules. If you do this, the default policy as set via the -P option toiptables becomes irrelevant. The upcoming section, "Using iptables," describes how to create individual rules.

If you want a default closed policy, you must decide between using DROP and REJECT. There are good arguments to be made in favor of both rules. DROP is the "stealthy" option. If you were to use DROP on every port and protocol, many network scanners would fail to detect your computer at all; it would appear not to exist. Of course, such an extreme policy would make the network useless; in practice, you must let some traffic through, and this frequently gives information to crackers. For instance, if a system drops everything but port-80 accesses, the cracker knows that you're running a web server (or something else) on port 80. Because computers don't normally drop packets, though, the cracker also knows that you're running a firewall with a default DROP policy. By contrast, REJECT does a poorer job of hiding your system's presence from casual scans, but once a cracker has found your system, it's less obvious that you're running a firewall.

On occasion, these different policies can have an effect on protocols. Specifically, many protocols are designed to keep trying to make connections if packets are lost. This behavior can sometimes result in connection delays for related protocols if you use a default DROP policy. For instance, a server might try contacting your computer's port 113, which is used by the ident (aka auth) server. This server provides information about who on your system is making connection requests to servers, the goal being to provide a trail in log files to help track abuse back to its source. (TCP Wrappers can also use an ident server as an authorization tool.) If your system uses an INPUT chain DROP rule on port 113, the result can be connection delays if a remote server tries to use your ident server. Of course, you can overcome such problems on a case-by-case basis by adding ordinary rules to the offending chain, overriding the default DROP rule with a REJECT rule, or perhaps even an ACCEPT

Tip If your computer has two network interfaces but it should not function as a router, use a DROP default policy on the FORWARD chain. Doing so will prevent the computer from functioning as a router, even if you inadvertently configure it to forward packets in another way.

Using iptables

To add a rule to a chain, you call iptables with a command like this: # iptables -A CHAIN selection-criteria -j TARGET

The CHAIN in this command is the chain name—INPUT, OUTPUT, or FORWARD for the filter table. The TARGET is the firewall target that's to process the packet, such as ACCEPT, REJECT, or DROP. You can also specify a LOG target, which logs information about the packet and then tries to match the next rule. Various other targets are also available; consult the iptables documentation for details.

Note The -A option appends a rule to the end of a chain. (A synonym is-append.) You can use other options, such as -D or-delete to delete a rule. Consult theiptables man page for details on this command; it's far more complex than I can present in just a few pages.

The tricky part of this command is in the selection-criteria component. You can specify many different criteria to match different features of a packet. If you specify more than one criterion, all of them must match in order for a rule to apply. Some of the possible criteria are listed here:

--protocol or-p You can filter based on the type of low-level protocol used. Options are tcp, udp, icmp, and all. With the exception of all (which matches all protocols), these options match the like-named low-level TCP/IP protocols.

--sport or-source-port All TCP and UDP traffic comes from programs that are linked to particular ports—that is, source ports. Every TCP or UDP packet includes the source port number, and you can match a rule on this information. For instance, to match all traffic from web servers running on the standard port (80), you specify -sport 80. You can also specify a range of ports by separating the port numbers by colons, as in -sport 1024:65535, which matches all ports between 1024 and 65,535, inclusive.

Warning It's possible to run servers on nonstandard ports, so filtering based on this information may not be perfectly reliable. Nonetheless, most servers do run on their standard ports, so such filters can be partially effective. Most clients run on unpredictable port numbers, so filtering based on client port numbers usually isn't practical.

--dport or--destination-port Just as TCP and UDP packets have embedded source ports, they include destination ports. You can filter based on this information, just as you can with source ports.

--source or-s This option filters based on the source IP address. You can provide either a single IP address or a network address and matching netmask specified as the number of bits, as in 172.24.17.0/24.

--destination or-d Just as you can filter based on the source IP address, you can filter based on the recipient IP address. The form of the specification is the same as for the -source option.

--in-interface or-I For computers with multiple network interfaces, you can filter based on the input interface name, such as eth1 or pppO. This option works with the INPUT and FORWARD chains, but not with the OUTPUT chain.

-out-interface or-o The output interface specification works much like the input interface option, but it matches outgoing traffic destined for a particular interface. This option works with the FORWARD and OUTPUT chains, but not with the INPUT chain.

Tip All Linux computers use a loopback or localhost interface, identified as lo, for certain local network activity. You can create a filter using this feature to enable your system to talk to itself, which is necessary for certain tools, such as X servers and print queues, to work.

-state One of the more advanced iptables features (and one not present in ipfwadm or ipchains) matches based on the state of a connection—whether it's a new connection, an established one, a related packet (such as an error message), or potentially forged. To use this option, you must precede it with -m state on the same iptables command line. You can specify a state of INVALID, NEW, ESTABLISHED, or RELATED. The main intent of stateful packet inspection is to block packets that might have been forged (that is, ones that would match INVALID). You can also try blocking NEW connections to ports that aren't used by servers; this practice can foil users from running unauthorized servers on your system or network.

Note This rule list is not complete. Consult the iptables man page for information on more matching criteria.

Many of these options are used in pairs that match packets traveling in opposite directions. You must remember that most networking connections involve two-way communications. One side sends a packet or a stream of packets to the other side, and the second side replies. Therefore, with a default DENY policy, it's not enough to simply unblock, say, packets directed at your web server (with the -destination-port and possibly other options) on your INPUT chain. You must also unblock packets coming from the web server (with the -source-port and possibly other options) on the OUTPUT chain. If you reverse the chains with which these rules are associated, you affect the ability of clients to communicate.

A Sample Configuration

The options described in the preceding section may seem complex, and indeed they enable you to create a sophisticated set of firewall rules. In order to better understand these rules, consider Listing 20.2, which shows a simple firewall rule set as a bash script. (Chapter 4, "Mastering Shells and Shell Scripting," describes shell scripts in more detail.) This script is a very minimal script that might be run on a workstation or server. Aside from flushing and setting the default policy, this script doesn't touch the FORWARD chain. To configure a router as a firewall, you'd have to create rules for the FORWARD chain reflecting the types of traffic you want to allow to pass between networks.

Listing 20.2: A Sample iptables Firewall Script

#!/bin/bash iptables -F INPUT iptables -F FORWARD iptables -F OUTPUT

iptables-P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP

# Let traffic on the loopback interface pass iptables -A OUTPUT -d 127.0.0.1 -o lo -j ACCEPT iptables -A INPUT -s 127.0.0.1 -i lo -j ACCEPT

# Let DNS traffic pass iptables -A OUTPUT -p udp -dport 53 -j ACCEPT iptables -A INPUT -p udp -sport 53 -j ACCEPT

# Let clients' TCP traffic pass iptables -A OUTPUT -p tcp -sport 1024:65535 -m state \

-state NEW,ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp -dport 1024:65535 -m state \ -state ESTABLISHED,RELATED -j ACCEPT

# Let local connections to local SSH server pass iptables -A OUTPUT -p tcp -sport 22 -d 172.24.1.0/24 -m state \

-state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp -dport 22 -s 172.24.1.0/24 -m state \ -state NEW,ESTABLISHED,RELATED -j ACCEPT

Listing 20.2 begins with a series of six calls to iptables that flush the firewall rule chain and set the default policy. These lines ensure that when you run this script, you won't add to an existing rule set, which could bloat the chains, thereby degrading performance and causing unexpected effects. The remaining lines are broken into four parts, each of which has two iptables calls. These parts set rules relating to specific types of traffic:

Loopback Interface Traffic The two lines that refer to 127.0.0.1 allow the computer to communicate with itself over the loopback interface (lo). The references to 127.0.0.1 and the associated -d and -s parameters are arguably a bit paranoid; anything coming over the lo interface should come from this address.

DNS Queries Most systems rely on a Domain Name System (DNS) server to translate hostnames to IP addresses. In order to keep this system working, you must enable access to and from remote DNS servers, which run on UDP port 53. The DNS rules in Listing 20.2 are actually rather permissive, because they enable traffic to or from any DNS server to pass. In theory, a miscreant could run something other than a DNS server on UDP port 53 to use this rule to bypass your security. In practice, though, such abuse would be unlikely to work, because it would require something other than DNS on the local system to use the oddly configured external client or server. If you like, you could add IP address restrictions to these lines to improve the security.

Client Traffic The next two calls to iptables create a broad set of acceptance conditions. Network clients generally use high TCP ports—those numbered between 1024 and 65535. These rules, therefore, open those ports to access in both directions, but with a twist: These rules use stateful packet inspection to ensure that NEW packets are allowed only on outgoing connections. The omission of the NEW state from the INPUT chain means that a server run on a high port (as an ordinary user might try in an attempt to get around your system's security) won't be able to accept connections. Both rules also omit the INVALID state, which can reduce the chance of a miscreant intercepting and "hijacking" an established connection.

Local SSH Server Traffic The final two calls to iptables open a hole in the firewall to enable local computers to make connections to the SSH server. This server runs on port 22, so traffic to and from that port and originating from or destined to the local (172.24.1.0/24) network is accepted. As with the client traffic rules, these rules employ stateful inspection as an added precaution. INVALID packets are rejected in both directions, and NEW packets are accepted only on input packets.

Many firewall scripts define variables that contain the host machine's IP address and the address for the local network, and then they refer to these variables, rather than using them directly, as Listing 20.2 does. This practice greatly simplifies changing the script if your IP address changes or if the script is to run on multiple computers.

Team LIB

1 previous

Team LIB

^ previous

0 0

Post a comment