Linux optimize

10 iptables rules to help secure your Linux box

Mastering iptables could take a while, but if you have a few rules to cover the basic security needs, you'll be well on your way to protecting your Linux system. Jack Wallen explains some key rules to get you started.

Mastering iptables could take a while, but if you have a few rules to cover the basic security needs, you'll be well on your way to protecting your Linux system. Jack Wallen explains some key rules to get you started.


The iptables tool is a magnificent means of securing a Linux box. But it can be rather overwhelming. Even after you gain a solid understanding of the command structure and know what to lock down and how to lock it down, iptables can be confusing. But the nice thing about iptables is that it's fairly universal in its protection. So having a few iptables rules to put together into a script can make this job much easier.

With that in mind, let's take a look at 10 such commands. Some of these rules will be more server oriented, whereas some will be more desktop oriented. For the purpose of this article, I'm not going to explain all of the various arguments and flags for iptables. Instead, I'll just give you the rule and explain what it does. For more information on the specifics of the rule, you can read the man page for iptables, which will outline the arguments and flags for you.

Note: This article is also available as a PDF download.

1: iptables -A INPUT -p tcp -syn -j DROP

This is a desktop-centric rule that will do two things: First it will allow you to actually work normally on your desktop. All network traffic going out of your machine will be allowed out, but all TCP/IP traffic coming into your machine will simply be dropped. This makes for a solid Linux desktop that does not need any incoming traffic. What if you want to allow specific networking traffic in -- for example, ssh for remote management? To do this, you'll need to add an iptables rule for the service and make sure that service rule is run before rule to drop all incoming traffic.

2: iptables -A INPUT -p tcp --syn --destination-port 22 -j ACCEPT

Let's build on our first command. To allow traffic to reach port 22 (secure shell), you will add this line. Understand that this line will allow any incoming traffic into port 22. This is not the most secure setup alone. To make it more secure, you'll want to limit which machines can actually connect to port 22 on the machine. Fortunately, you can do this with iptables as well. If you know the IP address of the source machine, you can add the -s SOURCE_ADDRESS option (Where SOURCE_ADDRESS is the actual address of the source machine) before the --destination-port portion of the line.

3: /sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

This will allow all previously initiated and accepted exchanges to bypass rule checking. The ESTABLISHED and RELATED arguments belong to the --state switch. The ESTABLISHED argument says, "Any packet that belongs to an existing connection," and the RELATED argument says, "Any packet that does not belong to an already existing connection but is related to an existing connection." The "state machine" of iptables is a means for iptables to track connections with the help of the kernel level "conntrack" module. By tracking connections, iptables knows what connections can be allowed and what can't. This reduces the amount of work the administrator has to do.

Here's how state works. If the local user initiates a connection, that packet (to that connection) is set as NEW in the prerouting chain. When the local user gets a return packet, the state is changed to ESTABLISHED in the prerouting chain. So when a state is set as ESTABLISHED, it can be allowed with the right iptables rule.

4: iptables -N LOGDROP

With this handy chain, iptables will log all dropped packets. Of course, this is only part of the chain. To complete it, you need to add the follow two rules: iptables -A logdrop -J LOG and iptables -A logdrop -J DROP. Now all matching packets (in this case, anything that has been dropped) will be added to the logdrop chain which will log them and then drop them.

5: iptables -t nat -A PREROUTING -i WLAN_INTERFACE -p tcp --dportPORTNUMBERS -j DNAT --to-destination DESTINATION_IP

When you need to route packets from external sources to specific ports on specific internal machines, this is what you want to do. This rule takes advantage of network address translation to route packets properly. To suit your needs, the WLAN_INTERFACE must be changed to the WLAN interface that bridges the external network to the internal network, the PORTNUMBERS must be changed, and DESTINATION_IP must be changed to match the IP address of the destination machine.

6: iptables -A INPUT -p tcp --syn --dport 25 -j ACCEPT

This is the beginning of a SYN flood protection rule. This portion of the rule blocks DoS attacks on a mail server port. (You can change this to suit your mail server needs.) There are three more portions of this rule set. The first is to add the same rule but modify the port to whatever is being served up by whatever ports you have open. The next portion is iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 4 -j ACCEPT, which is the actual SYN flood protection. Finally, iptables -A INPUT -p tcp --syn -j DROP will drop all SYN flood packets.

7: iptables -A INPUT -p tcp -m tcp -s MALICIOUS_ADDRESS -j DROP

This is where you can take care of malicious source IP addresses. For this to work properly, you must make sure you know the offending source IP address and that, in fact, it's one you want to block. The biggest problem with this occurs when the offending address has been spoofed. If that's the case, you can wind up blocking legitimate traffic from reaching your network. Do your research on this address.

8: iptables -N port-scan

This is the beginning of a rule to block furtive port scanning. A furtive port scan is a scan that detects closed ports to deduce open ports. Two more lines are needed to complete this rule:

iptables -A port-scan -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j RETURN

iptables -A port-scan -j DROP

Notice that the above rule set is adding a new chain called "port-scan". You don't have to name it such; it's just easier to keep things organized. You can also add timeouts to the above rule set like so:

iptables -A specific-rule-set -p tcp --syn -j syn-flood

iptables -A specific-rule-set -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j port-scan

9: iptables -A INPUT -i eth0 -p tcp -m state --state NEW -m multiport --dports ssh,smtp,http,https -j ACCEPT

What you see here is a chain making use of the multiport argument, which will allow you to set up multiple ports. Using the multiport argument lets you write one chain instead of multiple chains. This single rule saves you from writing out four separate rules, one each for ssh, smtp, http, and https. Naturally, you can apply this to ACCEPT, DENY, REJECT.

10: iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m nth --counter 0 --every 4 --packet 0 -j DNAT --to-destination 192.168.1.10:80

If you're looking to load balance between multiple mirrored servers (in the example case, load balancing a Web server at 192.168.1.10), this rule is what you want. At the heart of this rule is the nth extension, which tells iptables to act on every "nth" packet. In the example, iptables uses counter 0 and acts upon every 4th packet. You can extend this to balance out your mirrored sites this way. Say you have four mirrored servers up and you want to balance the load between them. You could have one line for each server like so:

iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m nth --counter 0 --every 4 --packet 0 -j DNAT --to-destination 192.168.1.10:80
iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m nth --counter 0 --every 4 --packet 1 -j DNAT --to-destination 192.168.1.20:80
iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m nth --counter 0 --every 4 --packet 2 -j DNAT --to-destination 192.168.1.30:80
iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m nth --counter 0 --every 4 --packet 3 -j DNAT --to-destination 192.168.1.40:80

As you can see the server on .10 will be routed every 0 packet, the server on .20 will be routed every 1st packet, the server on .30 will be routed every 2nd packet, and the server on .40 will be routed every 3rd packet.

Other options?

These 10 iptables rules will help you secure your Linux server. Of course, with anything Linux, there are multiple possibilities to achieve the same results. But these rules should serve as an outstanding springboard for Linux server security -- as well as Linux security discussion.

About

Jack Wallen is an award-winning writer for TechRepublic and Linux.com. He’s an avid promoter of open source and the voice of The Android Expert. For more news about Jack Wallen, visit his website getjackd.net.

5 comments
bblackmoor
bblackmoor

Rather than manually configure iptables (which is good to know how to do, but prone to errors and omissions), I generally use the firehol and fail2ban scripts to set up basic iptables protection.

sonotsky
sonotsky

I'll admit that it's been a LOOOOONG time since I've hacked together my own iptables ruleset (I usually take the default rules that come with RHEL, and let BFD add rules automagically as needed), but I thought that iptables does a "first match" algorithm? Thus, if you have a DROP rule, specifying the TCP protocol but no ports, it will deny unrelated packets from passing further down the chain. As Jack says, this is a great rule for hosts (particularly workstations) that have no services for external consumption, but it shouldn't be the first rule on a server-class box. Can anyone confirm please?

pgit
pgit

Sometimes you have to tweak the default fail2ban frequency downward in order to keep it working. Must be some of the script kiddies are unleashing bots that are aware of the default rate fail2ban ships with. I've seen the poor server spitting out "password incorrect" messages perpetually, despite fail2ban running. Just enough of a pause to avoid triggering the target.

speculatrix
speculatrix

why so many "syn"s? mostly just not needed - the accept related/established stateful control will handle all that. why no icmp control? you can't go blocking all icmp on input, you'll fsck things over! why no policy? "iptables -P INPUT DROP" sorry, but this is not a particularly impressive "10" list at all. sorry to be the bearer of bad tidings, but whilst the idea was good it was poorly executed.

benny
benny

You are correct. First rule applicable is applied. Drop should be after all execptions.