Configuring the iptables firewall

By default, Linux includes a firewall, iptables. This firewall should automatically be available on most (if not all) flavors of Linux. In this little activity, we'll set up a firewall on our Linux system. This should work fine regardless of which of the major distributions you use, but I'll call out anything that may be distribution specific. Before we get started though, I'll recommend that you play with this on a test machine, such as a VM or something you have physical access to. If you're using SSH, you may get disconnected when we enable the firewall, though I'll provide these steps in an order that hopefully, shouldn't drop your connection. Having a dedicated test machine to play around with is a good idea anyway.

With that out of the way, let's get started. Unfortunately, by default, iptables is wide open. It's so open, in fact, that it blocks nothing. To see this for yourself, issue iptables -L as root. Your output will probably look like this:

Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)

What you're seeing here are three chains of iptables, each corresponding to input, output, and forwarding. If you haven't configured this yet (and your distribution doesn't offer any default configuration), you'll likely see the default policy for each being ACCEPT, which means exactly what it sounds like: it allows everything.

One of the first rules I like to implement is to allow for SSH:

# iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT

With this command, we're appending a new rule (-A) to our INPUT chain on the interface eth0 using TCP and accepting traffic from dport (destination port) 22. If you changed your SSH port earlier, be sure to adjust this command accordingly. Also, if your interface is not eth0, change that too. Of course, our firewall allows anything anyway, since we've never changed the default policy. If you recall, it accepts everything by default. Let's change that with the following commands:

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

Now, if we view the output of iptables -L, we should see the default policy is DROP on everything and SSH is allowed.

However, there's one problem—we can't do anything else. We're no longer able to install packages. Actually, we're unable to do anything on the Internet at all. For example, try pinging Google. You won't be able to. If you've followed along, we set our default policy to DROP and it really does mean DROP. No traffic is currently allowed to or from the server unless it's SSH. In order to restore networking, we'll need to allow a few more things. First, let's allow DNS, which utilizes port 53:

# iptables -I INPUT -s 10.10.96.0/22 -p udp --dport 53 -j ACCEPT
# iptables -I OUTPUT -s 10.10.96.0/22 -p udp --dport 53 -j ACCEPT

Here, we're allowing port 53, but only for our internal 10.10.96.0/22 network. Note that DNS uses UDP, so we included -p udp into our command. It goes without saying, but adjust the 10.10.96.0/22 portion for whatever your network scheme is.

At this point, we're still a bit more locked down on our system than we would like. For example, we have DNS now, but we wouldn't be able to browse the Internet without allowing ports 80 and 443. Let's take care of that next.

# iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -i eth1 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -o eth1 -p tcp --dport 443 -m state --state ESTABLISHED -j ACCEPT

From this point forward, you should be able to browse the Internet on this machine and access it via SSH, though other ports and services shouldn't be accessible. If the machine in question is a router, you might want to configure port forwarding as well. Here's an example of port forwarding:

# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 65254 -j DNAT --to-destination 10.10.96.10

In this example, we're forwarding traffic received on port 65254 to 10.10.96.10. This example is useful if you have something like SSH available on a port other than 22 and would like to be able to access a computer (in this case, 10.10.96.10) using that port. The server will now forward traffic it receives on that port to that computer. This uses the concept of PREROUTING, which handles incoming packets and is able to reassign them via NAT. In this case, we're using the firewall to create a NAT rule to send this traffic to the appropriate place.

If the server you're setting up this firewall on is destined to become a router, you'll want to enable routing between interfaces as well. We took care of that from a Linux level in the last chapter, but since we configured the firewall to DROP everything by default, we can no longer do that. To continue to route between interfaces, we'll need to enable routing within our firewall as well. To do that, we can use the following commands:

# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -A FORWARD -i eth1 -j ACCEPT

In the previous command, we're allowing routing between interfaces eth0 and eth1. Adjust the previous commands to fit your distribution's network interface naming scheme so that it will fit your environment. We're also using POSTROUTING, which in terms of iptables is another word for outgoing traffic.

Another change that may be useful is allowing ping. With our configuration so far, ICMP ping packets are blocked. If you ping your server, you won't get a response. We can re-enable ping responses via the following commands. Be sure to change the IP address to match that of your server:

# iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -d 10.10.96.1 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# iptables -A OUTPUT -p icmp --icmp-type 0 -s 10.10.96.1 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT

If for some reason you've made a mistake or if you'd like to start this activity again, issue the following commands to flush (reset) the iptables firewall:

# iptables –flush

Note that this won't undo your default policy, which you can explicitly set to ACCEPT if you'd like to undo everything we've done so far. We can set each table to it's default (ACCEPT) with the following commands:

# iptables -P INPUT ACCEPT
# iptables -P FORWARD ACCEPT
# iptables -P OUTPUT ACCEPT

We choose DROP for our default policy because in this mode, the firewall does not respond to the sending host with a status when rejecting traffic. In a sense, it's almost as if packets are sent to an endless black hole when a policy is set to DROP. This is a good thing, because miscreants can use the response they get back from the server to better target their attacks. It's best for them to get no response at all.

So, feel free to play around with iptables until you've gotten to a point where you are able to perform all the tasks that you normally were able to perform. Once you have a working and well-tested firewall, it's time to save the configuration. Otherwise, all this hard work would be lost when you reboot. Use the following command to save your firewall configuration:

# iptables-save > /etc/iptables.rules

To import these rules, we can use the following command:

# iptables-restore < /etc/iptables.rules

You'll probably want these changes restored automatically every time the system boots. Both Debian and CentOS have their own ways to accomplish this. Here are the methods in which to save the rules.

In Debian, first save the rules as we did before:

iptables-save > /etc/iptables.rules

Next, create the following file:

/etc/network/if-pre-up.d/iptables

Inside that file, place the following text:

#!/bin/sh
 /sbin/iptables-restore < /etc/iptables.rules

In CentOS, execute the following command:

# iptables-save > /etc/sysconfig/iptables

From this point onwards, your firewall rules should persist each time you reboot the server.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset