Team LiB
Previous Section Next Section

iptables and Network Firewalls

In this section, we build on the last section's dive into iptables and use it to introduce dual-homed network firewalls. Entire books have been written on the complexities of this subject, so you'll find enough to get you going. We focus on the basic configuration of such firewalls, as well as offer some help on troubleshooting existing installations.

When securing an entire network with iptables instead of just a single server, you need to think in different terms. Whereas a firewall on a single server accepts and rejects packets for applications on that machine, when you set up a network NAT-based firewall you are basically configuring a type of security-based network router, which performs functions such as Network Address Translation, state tracking, and port/address forwarding. Some people even use Linux NAT firewalls to handle tasks like web/FTP proxying, bandwidth throttling, and Quality of Service (or QoS) controls.

Note 

Network Address Translation, or NAT, is the technology used on a network gateway, router, or firewall that allows it to translate network addresses and usually also track sessions between networks with SPI. Such devices in the commercial world are usually configured for the enterprise with routable IP ranges on the outside and nonroutable IP address ranges on the inside. This is a very secure arrangement, as nothing from the untrusted outside interface will be allowed through the firewall unless it has been requested by an IP on the inside or otherwise explicitly permitted via NAT by the firewall. Some people refer to this configuration as a type of Transparent TCP Proxy Router. See www.ipprimer.com/nat.cfm for more information on NAT theory.

Earlier in this chapter, we described iptables as the outer layer of network security, followed by TCP wrappers and then by individual daemon configuration files. In this dual-homed routing firewall configuration the layout is somewhat different. Figure 11-6 shows a simplified view of this concept. Note that this figure does not indicate actual packet flow, but simply illustrates an idea.

Click To expand
Figure 11-6: In a NAT routing firewall configuration, iptables forms a boundary between networks.

As you see in this figure, when configured as a NAT routing firewall, iptables forms a security boundary between internal and external networks. The firewall in this figure is set up so that all connections going through the firewall are translated between interfaces automatically. And since it is state based, it is session/protocol sensitive.

If you have the hardware for this configuration and are going to assemble it, be sure that you stop iptables, and delete the iptables file before continuing. You don't want any other settings interfering with what you're working on. Use these commands to stop iptables and list the filter table:

# /etc/init.d/iptables stop
Flushing firewall rules:                                   [ OK ]
Setting chains to policy ACCEPT: filter                    [ OK ]
Unloading iptables modules:                                [ OK ]
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

If you want to check the NAT table before beginning work as well, issue this command:

   # iptables -L -t nat

Caution 

Even if you're working on a Red Hat or Fedora Core box, never use the Red Hat graphical firewall configuration tool (redhat-config-securitylevel) to build dual-homed systems. It is not intended for building hardened network NAT firewalls.

Building Firewall Rules

In the previous section, we showed you how to build the "filter" table using the packet flow from input and output chains into the default RH-Firewall -1-INPUT chain. In this section, as we begin to work with packets flowing from one network and being routed to another, it's easier to work with the "nat" table and its related chains.

Manually Entering and Saving Rules

Now that you've backed everything up, it's time to start adding your own rules to the existing configuration. In this example, we'll show you how to do it by hand so that you'll be able to follow along no matter what version of Linux you're using. At the end, we'll save the configuration so that it's usable on a Red Hat-based system; if you're using another Linux distribution, save your commands out to a file and use that new file as your iptables firewall startup script.

Note 

Under Red Hat Linux and Fedora Core, when you manually enters iptable commands directly from the command line tool iptables, you need to then save them out to /etc/sysconfig/iptables with the iptables-save command:

   # iptables-save > /etc/sysconfig/iptables

or

   # /etc/init.d/iptables save

Be aware that your settings will look slightly different when they are saved through this method, but they'll be organized and separated in a logical manner, and you will lose any commenting that you previously had.

Setting up NAT/PAT

The "nat" table can be configured for SNAT (Source NAT), and DNAT (Destination NAT), packet modifying or mangling. This means that anything from a specified IP address can be mangled (rewritten) to appear as if it comes from another location using SNAT. Likewise, anything destined for a specified IP address can be mangled and sent to a different IP or port under DNAT. This concept is often called port/IP mapping or Port Address Translation (PAT).

Tip 

If you aren't running a Red Hat-based Linux and you don't want to mess with manually configuring NAT/PAT, you might consider running a simple boot-time iptables setup script. There are a number of these firewall scripts available on the Internet. Some of the basic versions are designed for single-homed firewalls, like KISS, while others have advanced multihomed features. Advanced Policy Firewall, for example, offers dshield.org blocklist support, simple configuration, management scripts, and a very nice cross-distribution modular design. See the Firewall Resources section at the end of the chapter for more information.

The remainder of this section shows how to create a dual-home network firewall iptables config file that does the following:

  1. Sets up Port Address Translation for web (80), SMTP (25), and "Ident" so that all web and incoming e-mail will get routed to our web/e-mail server (10.1.1.1).

  2. Keeps internal LAN broadcast traffic (in 10.1.1.*) from being processed on the firewall or looping back in on itself.

  3. Sets up internal LAN-based masquerading and forwarding for the "nat" table for internal traffic (eth0/10.1.1.* as in Figure 11-6) going out over ethl (external Internet) so that it adopts the external IP address of the firewall (192.168.128.1).

  4. Enables packet forwarding in iptables for eth0 (internal LAN) to be sent to the "nat" table so the last step works.

  5. DROPs Syn, invalid, and unclean packets hitting the external or unstrusted (eth1) interface.

  6. Sets up a default DROP policy (default rule) for any unmatched packets in the FORWARD chain.

  7. Allows SSH access to the firewall itself from the internal LAN (for administrator access from inside).

  8. Allows pings of the firewall.

  9. DROPs everything else on the INPUT chain.

  10. Applies some final security/logging settings.

  11. And sets up IPv4 forwarding in the kernel so that this will all work.

You must be logged in as root to run the following commands. As you see each group of commands, simply type them in without the comments, in order, and only once. If you mess up use iptables-save or iptables -L to display your settings, starting over or inserting/deleting entries as needed.

We used the Debian Linux nat-fw-up firewall scripts as a reference while writing this chapter. You can see the whole script at www.thing.dyndns.org/debian/iptables.htm.

The first commands to enter in your chain will configure DNAT-based port mapping, or PAT. These commands send all incoming web, e-mail, and identification traffic requests to the web/e-mail server machine:

# iptables -A PREROUTING -t nat -p tcp -i eth1 --dport 80 -j DNAT --to
10.1.1.1
# iptables -A PREROUTING -t nat -p tcp -i eth1 --dport 25 -j DNAT  --to
10.1.1.1
# iptables -A PREROUTING -t nat -p tcp -i eth1 --dport 113 -j DNAT --to
10.1.1.1

With these commands, you'll be working with the PREROUTING chain in the "nat" table. These rules will affect only traffic coming in from the external eth1 interface on ports 80 (http), 25 (smtp), and 113 (identification). All requests will be mangled and redirected to the web/e-mail server at 10.1.1.1 on the same ports. With these settings in place, any external user can hit the firewall's IP address and get web or e-mail services from an internal server.

Tip 

You can do this with almost any service on any server that's on your internal network. You can even mangle requests to multiple internal IP addresses to do round-robin load balancing.

The next command is a safeguard that prevents internal traffic from looping back in on itself. With this command, anything coming from eth0, going through the nat/PREROUTING chain, and heading back to the 10.1.1.0 network will be dropped rather than rattling around in a loop:

# iptables -A PREROUTING -t nat  -i eth0 -d 10.1.1.0/24 -j DROP

Next, set up the masquerading and forwarding rules that allow all internal network hosts to assume the identity of the firewall's external IP address. Issue the command

# iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o eth1 -j MASQUERADE

to set up the nat/POSTROUTING chain. Any internal IP addresses that are output to the eth1 interface will now be masqueraded as the external address.

Next, issue this command:

# iptables -A FORWARD -i eth0 -j ACCEPT

Traffic coming from the trusted internal network over the eth0 interface will be let out through nat/POSTROUTING to the untrusted external network.

Note 

The FORWARD chain is a special type of chain. It passes packets outside the normal filtering, mangling, and local processing routines, and sends them directly to the "nat" table's postrouting chain. FORWARD effectively moves a packet past NAT to another interface.

The next set of commands will clean up known "dirty" packets that will inevitably hit the firewall:

# iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j DROP
# iptables -A FORWARD -m state --state INVALID -j DROP
# iptables -A FORWARD -m unclean -j DROP

These commands keep the packets from passing the firewall, since they are not legitimate requests for services or data.

Now, issue the command that defines the DROP policy for the filter/FORWARD chain. This command sets the default FORWARD chain's DROP policy, which is a critical security element of a good firewall:

   # iptables -P FORWARD DROP

The next step is to define general settings for expected traffic. The following commands will allow SSH connections (at this point, only for internal eth0 connections to the firewall itself), return ESTABLISHED/RELATED packets, and permit outgoing NEW connections from the local and trusted interfaces (lo and eth0):

# iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -m state --state NEW -i ! eth1 -j ACCEPT

The final entry in the filter/INPUT chain is to allow pings and DROP everything else that has made it this far down the chain. You may or may not want to allow pings to your machine. If not, don't use the first of these commands:

# iptables -A INPUT -p icmp -s 0/0 --icmp-type echo-request -j ACCEPT
# iptables -P INPUT DROP

Apply Security Settings

Now that the basic operational rules have been set, it's time to apply some security settings. In this section, we'll configure logging and lock out intrusion attempts like Denial of Service attacks and port scans.

First, let's set up simple FORWARD chain logging based on matched FORWARD packet frequency (three/minute). For tracking down people who are scanning you, use the following commands:

   # iptables -A FORWARD -m limit --limit 3/m -j LOG
   # iptables -A FORWARD -j LOG

In order to stop DoS attacks, use these commands to block ping floods:

# iptables -A FORWARD -p tcp --syn -m limit -j ACCEPT
# iptables -A FORWARD -p tcp --tcp-flags SYN.ACK.FIN.RST RST -m limit
# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit

Caution 

Before you can use the FORWARD functions that you set up, you'll need to turn on IPv4 forwarding in the kernel. We describe this process in the Troubleshooting iptables section later in the chapter. If you don't turn this function on, none of these settings will work, and no data will flow through your firewall. This is one of the most often overlooked problems with new firewall setups.

You're almost done! Take a step back and look at the whole set of rules that you've created using the tool iptables-save:

# iptables-save
# Generated by iptables-save v1.2.8 on Sun Feb 15 14:19:40 2004
#filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [42:5145]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i ! eth1 -m state --state NEW -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A FORWARD -i eth0 -j ACCEPT
-A FORWARD -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW -j DROP
-A FORWARD -m state --state INVALID -j DROP
-A FORWARD -m unclean -j DROP
-A FORWARD -m limit --limit 3/min -j LOG
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit -limit
    3/hour -j ACCEPT
-A FORWARD -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK RST -m limit --limit
    3/hour
-A FORWARD -p icmp -m icmp --icmp-type 8 -m limit --limit 3/hour COMMIT
# Completed on Sun Feb 15 14:19:40 2004
# Generated by iptables-save v1.2.8 on Sun Feb 15 14:19:40 2004
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [8:460]
:OUTPUT ACCEPT [8:460]
-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j DNAT
    --to-destination 10.1.1.1
-A PREROUTING -i eth1 -p tcp -m tcp --dport 25 -j DNAT
    --to-destination 10.1.1.1
-A PREROUTING -i eth1 -p tcp -m tcp --dport 113 -j DNAT
    --to-destination 10.1.1.1
-A PREROUTING -d 10.1.1.0/255.255.255.0 -i eth0 -j DROP
-A POSTROUTING -s 10.1.1.0/255.255.255.0 -o eth1 -j MASQUERADE
COMMIT
# Completed on Sun Feb 15 14:19:40 2004

Note 

You may use the iptables -L or /etc/init.d/iptables status commands to get information instead of using iptables-save as shown here, but these other forms do not show interface information. Use iptables-save to get output that looks like what you'd see in your /etc/sysconfig/iptables file.

If this is accurate and you're ready to use it, you can save these configurations out to /etc/sysconfig/iptables with the command

   # iptables-save > /etc/sysconfig/iptables

or

   # /etc/init.d/iptables save

As long as you've set iptables to run in the appropriate runlevels, these changes will now persist when you reboot. Check the runlevels with the following command:

# chkconfig --list iptables
iptables     0:off   1:off   2:on   3:on   4:on   5:on   6:off


Tip 

You aren't done working with your /etc/sysconfig/iptables file until you go in and add thorough comments to describe what you've done. If you don't leave comments, we bear no responsibility for the headache you'll suffer in 3 months when you try to untangle your configurations! Just remember to either use your /etc/sysconfig/iptables as your master working file, or keep a backup of your running iptables file, and anytime you reissue an /etc/init.d/iptables save that you add your commenting back in. I recommend the former over the latter.

The Final Configuration

Once you have completed all the steps, this is what your /etc/sysconfig/iptables file should look like:

# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.2.8 on Sun Feb 15 13:03:25 2004
#### MY CUSTOMIZED IPTABLE DUAL HOMED FIREWALL CONFIG ####
##############################################################
## UPDATED 2004-02-15, TWW

*nat
:PREROUTING ACCEPT [1:245]
:POSTROUTING ACCEPT [2:127]
:OUTPUT ACCEPT [2:127]
########### PORT FORWARDING ###########
## Running PAT for out web/mail server (with a polite IDENT too)
-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j DNAT
    --to-destination 10.1.1.1
-A PREROUTING -i eth1 -p tcp -m tcp --dport 25 -j DNAT
    --to-destination 10.1.1.1
-A PREROUTING -i eth1 -p tcp -m tcp --dport 113 -j DNAT
    --to-destination 10.1.1.1

######### LOOPBACK PROTECTION #########
## Don't allow internal traffic to loop back in on itself
-A PREROUTING -d 10.1.1.0/255.255.255.0 -i eth0 -j DROP
######## NAT/MASQ & TRUSTED OUT #########
## Setting up the POSTROUTING NAT/MASQUERADE
-A POSTROUTING -s 10.1.1.0/255.255.255.0 -o eth1 -j MASQUERADE
COMMIT

# Completed on Sun Feb 15 13:03:25 2004
# Generated by iptables-save v1.2.8 on Sun Feb 15 13:03:25 2004
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [10:533]
:RH-Firewall-1-INPUT - [0:0]

################# ALLOW IN ###############
## Allowing SSH, return ESTABLISHED/RELATED, and outgoing NEW conns
-A INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i ! eth1 -m state --state NEW -j ACCEPT #

############### ICMP TRAFF ###############
## Allowing pings, but DROP any/everything else
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

## If coming from the trusted network, let it out...
-A FORWARD -i eth0 -j ACCEPT

############ DROP BAD STUFF #############
## Don't allow any nasty packets to be forwarded to the inside...
-A FORWARD -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW
-j DROP
-A FORWARD -m state --state INVALID -j DROP
-A FORWARD -m unclean -j DROP

################ Logging #################
## Basic FORWARD logging based on frequency
-A FORWARD -m limit --limit 3/min -j LOG
############### DoS Attacks #############
## syn-flood protection
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit
    --limit 3/hour -j ACCEPT
## stealth port scans
-A FORWARD -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK RST -m limit
    --limit 3/hour
## ping of death
-A FORWARD -p icmp -m icmp --icmp-type 8 -m limit--limit 3/hour
COMMIT

There you are. You've just created a really nice, iptable-based, network firewall configuration that you could legitimately use in a production environment or sell to a consulting client for several hundred dollars.

Know Thyself

Everyone who puts a firewall online should configure one by hand, at the command line level, at least once or twice. If you are relying on a graphical firewall tool, you need to know how it works in order to fix it when it breaks, and some graphical tools hide the actual settings under the guise of making it easier to use. Remember, security that you don't both fully understand and fully control is just an illusion. You can use GUI tools, as long as you're able to still get under the hood and see what's really going on.

Once you know how to do it by hand at the command line, and how to peek behind the curtain to check things out once in a while, you might find that a GUI tool makes your life easier from the management side. We describe some of these GUI tools in the next section.

Caution 

Whether you continue to work with iptables by hand or use a GUI, be aware of the people who know your firewalling strategies internally. The FBI has found that 80% of all successful system cracks/hacks come from people within the organization, although the vast majority of attempts are made by outsiders. This is because insiders know more about your internal systems than anyone on the outside, including your weak points. When it comes to security, you really can't trust anyone. Many organizations even go so far as to have internal checks and balances so that no single person has the passwords to everything on a secure system. If your data is precious, know who holds the keys and don't forget about internal defenses.


Team LiB
Previous Section Next Section