One of the first tasks that should be accomplished when deploying a new server (and in reality, any new machine) is setting up a software firewall. On a Linux computer, this is accomplished using iptables. We can use the
/sbin/iptables command to manipulate our firewall, or we can directly edit the
/etc/sysconfig/iptables file. Each has their advantages, and it’s worthwhile to know how each works.
Lets start with the
iptables command. We can first flush the firewall table, so that we have a blank set of rules to start with.
[root@machine ~]# iptables -F
Next we can start adding some rules. First, lets create a rule to accept any traffic that is either already established, or traffic that is related to the established traffic.
[root@machine ~]# iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-I after our command means that we want to insert our rule. We can optionally insert it into a specific location, which we would specify after the name of the chain, but we want it at the top so we can omit the location number. The
INPUT chain is our set of incoming firewall rules. Next we will specify that we want to match the state of the connection with the
-m state flag, followed by the state we wish to match, using
--state RELATED,ESTABLISHED. Finally we say that when these conditions are met, we will jump to another specific chain or target. We could make this traffic jump to another chain that can do some extra processing, or we can just jump to one of the predefined targets. In this case, we just jump to the
ACCEPT chain, so that the traffic is accepted by the firewall, and further processing of the traffic (by iptables) is discontinued.
Next we will accept any traffic on the local interface, using the
-i lo option. It’s worth mentioning that we want to process our traffic efficiently, and these first two rules will accept the majority of traffic that we will see. This will allow iptables to accept the traffic near the top of the INPUT chain, reducing the amount of processing necessary. We’ll append next rule to our current list of rules, by replacing the
-I flag with the
[root@machine ~]# iptables -A INPUT -i lo -j ACCEPT
Now we can actually start setting up some real rules to accept traffic from the outside. What we can do for our basic server now is to accept a few ports, so that we will have outside access. First, lets accept our SSH traffic with the following command:
[root@machine ~]# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
-p tcp flag says that we want to match the TCP protocol, and the
--dport 22 tells the rule to accept traffic coming in with a destination of port 22. This rule will allow tcp connections to the SSH server on port 22. Next, let us accept two other ports.
[root@machine ~]# iptables -A INPUT -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT
Here we have accepted incoming traffic on TCP ports 80 and 443. Notice that we also needed the
-m tcp flag, in order to match our rule for the
-m multiport flag. We can also accept traffic from a specific source, providing an extra layer of security to protect any administrative ports.
[root@machine ~]# iptables -A INPUT -p tcp -s 192.168.1.50/32 --dport 10000 -j ACCEPT
This previous rule only accepts traffic on port 10000 if it has a source of 192.168.1.50/32. Notice the CIDR (Classes Inter-Domain Routing) notation. We can optionally specify a subnet to accept, with something like 192.168.1.0/24. We can also omit the CIDR subnet notation if we are only allowing access to a single IP address.
Finally, we can set the default rule for the INPUT table. This rule will be run on any traffic that hasn’t been matched by a previous rule in our chain. In this case, we want to drop any other traffic, so we only allow what we have explicitly specified. We should also drop any forwarded traffic, so nobody can try to relay traffic through us.
[root@machine ~]# iptables -P INPUT DROP [root@machine ~]# iptables -P FORWARD DROP
Finally, we want to save our work, so that our rules are persistent on reboot. On Red Hat/Fedora/CentOS, we can run the following command:
[root@machine ~]# service iptables save
The nice thing about using the
iptables command, is that we can add or remove commands on the fly, allowing us to write scripts which can modify our rules, blocking potential threats on the in real time during an attack.
We can also directly edit the
/etc/sysconfig/iptables file, so we can more easily create a set of default rules. Lets take a quick look at the file, so open it in your favorite text editor. It should look something like this:
# Generated by iptables-save v1.3.5 on Tue Mar 29 22:19:16 2011 *raw :PREROUTING ACCEPT [320:29801] :OUTPUT ACCEPT [334:46325] COMMIT # Completed on Tue Mar 29 22:19:16 2011 # Generated by iptables-save v1.3.5 on Tue Mar 29 22:19:16 2011 *nat :PREROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [2:120] :OUTPUT ACCEPT [2:120] COMMIT # Completed on Tue Mar 29 22:19:16 2011 # Generated by iptables-save v1.3.5 on Tue Mar 29 22:19:16 2011 *mangle :PREROUTING ACCEPT [320:29801] :INPUT ACCEPT [320:29801] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [334:46325] :POSTROUTING ACCEPT [334:46325] COMMIT # Completed on Tue Mar 29 22:19:16 2011 # Generated by iptables-save v1.3.5 on Tue Mar 29 22:19:16 2011 *filter :FORWARD DROP [0:0] :INPUT DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT -A INPUT -p tcp -s 192.168.1.50/32 --dport 10000 -j ACCEPT COMMIT # Completed on Tue Mar 29 22:19:16 2011
The most important parts to notice are toward the end of the file. We can see by the
:FORWARD DROP [0:0] and the
:INPUT DROP [0:0] lines that we are dropping the FORWARD and INPUT traffic by default. There are also the lines for our specific rules, which process the traffic in the INPUT chain in the order that the rules are listed. In the future we will take a look at some more advanced firewall rules, along with blocking potential threats on the fly, and making iptables do some NAT!