Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'm sure Linux sysadmins are quite familiar with iptables, the userland interface to the netfilter packet-filtering framework.

Now, this "Question" is meant to be a Community Wiki for collecting together various bits-n-pieces of iptables wisdom. Nothing is too common or too obscure. Post anything you know that would help others make the most of iptables.

share|improve this question

11 Answers 11

Using whitelist and blacklist with iptables

#!/bin/bash

WHITELIST=/whitelist.txt
BLACKLIST=/blacklist.txt

#THIS WILL CLEAR ALL EXISTING RULES!
echo 'Clearing all rules'
iptables -F

#
## Whitelist
#

for x in `grep -v ^# $WHITELIST | awk '{print $1}'`; do
        echo "Permitting $x..."
        $IPTABLES -A INPUT -t filter -s $x -j ACCEPT
done

#
## Blacklist
#

for x in `grep -v ^# $BLACKLIST | awk '{print $1}'`; do
        echo "Denying $x..."
        $IPTABLES -A INPUT -t filter -s $x -j DROP
done

Script to open ports

#!/bin/bash
ALLOWEDTCP="80 3128 3784"
ALLOWEDUDP="3128 3784"

#
## Permitted Ports
#

for port in $ALLOWEDTCP; do
       echo "Accepting port TCP $port..."
       $IPTABLES -A INPUT -t filter -p tcp --dport $port -j ACCEPT
done

for port in $ALLOWEDUDP; do
        echo "Accepting port UDP $port..."
        $IPTABLES -A INPUT -t filter -p udp --dport $port -j ACCEPT
done

Blocking portscan

# Attempt to block portscans
# Anyone who tried to portscan us is locked out for an entire day.
iptables -A INPUT   -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP

# Once the day has passed, remove them from the portscan list
iptables -A INPUT   -m recent --name portscan --remove
iptables -A FORWARD -m recent --name portscan --remove

# These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT   -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A INPUT   -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP

iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP

Spoofed/Invalid packets

# Reject spoofed packets
# These adresses are mostly used for LAN's, so if these would come to a WAN-only server, drop them.
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP

#Multicast-adresses.
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP

# Drop all invalid packets
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP

Block Smurf attacks

# Stop smurf attacks
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -j DROP

# Drop excessive RST packets to avoid smurf attacks
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT

Block ICMP (aka ping)

# Don't allow pings through
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
share|improve this answer
2  
Consider adding a comment to the "spoofed" comments, so that less experienced users know why the source addresses are considered spoofed (...when arriving on a wan interface). –  3molo Mar 10 '11 at 15:07
    
Good call :-). Done. –  Bart De Vos Mar 10 '11 at 16:11
    
wait. Isn't Block ICMP (aka ping) line redundant to Block smurf attack line: iptables -A INPUT -p icmp -m icmp -j DROP ? –  Stann Mar 31 '11 at 3:14
    
also - here is the explanation for many items described here: newartisans.com/2007/09/neat-tricks-with-iptables.html –  Stann Mar 31 '11 at 7:01
    
@Andre: Sure, it's redundant. Some people might only want to block ICMP, that's why I mentioned it ;-) –  Bart De Vos Mar 31 '11 at 7:30

Optimize netfilter's Performance Using ipset

If you write a lot of similar rules based on mere IP, port, or both, consider using ipset to optimize netfilter's performance.

For example:

iptables -s 192.168.1.11 -j ACCEPT
iptables -s 192.168.1.27 -j ACCEPT
iptables -s 192.168.1.44 -j ACCEPT
... hundreds of similar rules ...
iptables -s 192.168.251.177 -j ACCEPT

This means that a packet with the source address of 192.168.251.177 must first traverse hundreds of rules before it can get its verdict of ACCEPT.

Of course, experienced sysadmins will split the rules by subnet. But that still means hundreds of rules.

ipset to the rescue!

First, define an IP Set of ipmap type:

ipset -N Allowed_Hosts ipmap --network 192.168.0.0/16

Then, populate it with the addresses:

for ip in $LIST_OF_ALLOWED_IP; do ipset -A Allowed_Hosts $ip; done

Finally, replace the hundreds of iptables rules above with one rule:

iptables -m set --match-set Allowed_Hosts src -j ACCEPT

When a packet arrives, netfilter will perform a very quick bitmap search for the packet's source (src) IP against the Allowed_Hosts IP Set. All packets coming from 192.168.0.0/16 will experience one rule. And do believe me that searching a bitmap is at least two order of magnitudes faster than performing hundreds of iptables rule-checking.

ipset is not limited to IP addresses. It can also match based on ports, IP-port tuple, network/subnet addresses, IP-MAC tuple, and so on and so forth. And it can match those criteria as source or destination or a mix of both (in the case of tuples).

And finally, with ipset you can automatically put IP addresses in blacklists/whitelists. These blacklists/whitelists can also 'age', thus automatically deleting the IP address after a configurable amount of time has passed.

Please refer to ipset's man page for more details.

VERY IMPORTANT NOTE:

Some Linux distros do not have 'out-of-the-box' support for ipset. Two distros I know that do not support ipset out-of-the-box are Ubuntu and Debian. Running aptitude on them tantalizingly shows that an ipset package is available, but I strongly recommend you to not install that package for two reasons: (1) It's an old version of ipset, and (2) It won't work anyway.

Instead, download ipset's source from its website: http://ipset.netfilter.org/install.html

Alternatively, if you use xtables-addons, ipset is included in its source: http://xtables-addons.sourceforge.net/

Edit: The above is true for Ubuntu 10.04, the latest LTS at the time of writing. Ubuntu 12.04 has built-in support for ipset and/or xtables-addons, in the sense that installing the relevant package properly enables the features. I don't know the situation on Debian, though, having not used it for quite some time...

share|improve this answer
1  
That's a real pity it's not supported by default on Debian and Ubuntu. I thought you were going to list some obsure distros :/ –  UpTheCreek Apr 25 '13 at 7:44
    
@UpTheCreek I've edited my answer... the 'special note' was applicable during time of posting the answer, but no longer applicable now. –  pepoluan Mar 10 at 12:40

Add comments to your rules:

-m comment --comment "Comments help to read output of iptables -nvL"
share|improve this answer

Block Well-Known TCP Attacks

Add the following rules, preferably in -t raw -A PREROUTING

-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP

The attacks being blocked are, respectively:

  • SYN-FIN attack
  • SYN-RST attack
  • X-Mas attack
  • nmap FIN scan
  • NULLflags attack
  • ALLflags attack

(feel free to edit the names of the attacks above)

share|improve this answer
2  
The -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP could be removed, as the -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP will catch every packet it could block. –  Jean-Philippe Guérard Nov 19 '12 at 14:26

Enabling NAT

  1. echo 1 > /proc/sys/net/ipv4/ip_forward
  2. /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Step 1 sets the kernel parameter to allow for ip forwarding, step 2 sets up an iptables rule that enables NAT on interface eth0.

share|improve this answer
1  
That won't be persistent through a reboot, will it? You need to edit /etc/sysctl.conf net.ipv4.ip_forward = 1. (Assuming Red Hat or derivative.) –  Aaron Copley Apr 3 '11 at 14:48

Block ICMP attacks

Add the following rules, preferably in -t raw -A PREROUTING

-p icmp -m u32 ! --u32 "4&0x3FFF=0"   -j DROP
-p icmp -m length --length 1492:65535 -j DROP

The first rule blocks all ICMP packets whose "fragmentation flag" is not 0. (ICMP should never be fragmented; they should be carrying small payloads)

The second rule blocks oversized unfragmented ICMP packets.

share|improve this answer

(from my iptables_tricks.txt file, recompiled from a lot of places :P)

Makes iptables wait 15 seconds between new connections from the same IP:

 iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
 iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
share|improve this answer
1  
Same, but with counting of attempts: -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --rttl --name SSH -j DROP –  alexm Apr 25 '11 at 6:15

using FireHOL - convenient iptables wrapper

I found it much more intuitive than direct iptables commands. Especially for people with past experience with other firewalls:

FireHOL is an iptables firewall generator producing stateful iptables packet filtering firewalls, on Linux hosts and routers with any number of network interfaces, any number of routes, any number of services served, any number of complexity between variations of the services (including positive and negative expressions).

share|improve this answer
2  
I prefer Shorewall which is actively developed, supports IPv4 and IPv6, and can generate firewalls for other iptables systems. –  BillThor Mar 10 '11 at 16:52
    
@BillThor sounds like a good tool - thanks –  Ophir Yoktan Mar 10 '11 at 17:28

Another GUI that can be used to configure iptables is Firewall Builder. It lets users create rule elements as objects in a database and then drag-and-drop these objects into a rules editor to create the desired firewall policy. The application then generates a script file with all the iptables commands required to implement the rules.

Unlike some other iptables GUI solutions where you can only manage one iptables configuration at a time, with Firewall Builder you can manage a large number of iptables configurations all from a single application. Firewall Builder runs on Linux, Windows and Mac OS X, has been around for over 10 years and has thousands of active users around the world.

Full Disclosure - I'm the co-founder of NetCitadel which is the company that develops Firewall Builder.

share|improve this answer

Something I do, mainly because of my ignorance of a more elegant solution, is to manually check my nginx and mail server logs every 5 hours for excessive access by individual IP's. I run a few scripts together that A.) Check the access.log and list off the top 10 IP's organized by how many hits they have to the server B.) Dump the results into a log file C.) Have another script look at that log file and ban any IP that has hit the server more than X amount of times over the past X hours D.) Save my iptables.save E.) truncate my logs

Here's what it looks like:

**autoBanIPs.sh**

#!/bin/bash

#This script checks every 5 hours to see if any IP has made over 1800 connections and then bans them.  We clear the logs once this is done

now=$(date +"%m_%d_%Y")

/root/bin/checkBadIPs.sh > /home/ipChecker/ipcheck_$now.txt
/usr/bin/perl -ne 'print if grep {$_>1800} /(\d{3,})/g' /home/ipChecker/ipcheck_$now.txt | awk '{print $2}' > /home/ipChecker/badIPs_$now.sh
sed -i "s/^/\/usr\/local\/sbin\/blockIP /g" /home/ipChecker/badIPs_$now.sh
/bin/bash /home/ipChecker/badIPs_$now.sh
cat /home/ipChecker/ipcheck_$now.txt >> /home/ipChecker/ipcheck_$now.log
rm /home/ipChecker/ipcheck_$now.txt
rm /home/ipChecker/badIPs_$now.sh
/usr/bin/truncate -s 0 /var/log/nginx/access.log

**checkBadIPs.sh**

cat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -n | grep -v 127.0 | tail -10

**BlockIP**

#!/bin/bash
sudo iptables -I INPUT -s $1 -j DROP
sudo bash -c "iptables-save > /etc/network/iptables.save"

Again I know this is crude as hell and there is probably a nice clean efficient protool that does all of this but I didn't know about it and this thing has been going for a year or two now and keeping the bad guys at bay. The one thing I would very SERIOUSLY recommend is that you have a proxy or another server in the wings that you can use to access your main server.. The reason being is that if you are doing web development one day out of the blue and you ping your self 2000 times in 5 hours for some testing you could get blocked with no way back in except for a proxy. You can see that in checkBadIPs.sh I've put grep -v 127.0 and in my actual files I have a ton of ignore rules for my own IP's and other trusted IP ranges but sometimes your IP changes, you forget to update and then you're locked out of your own server :)

Anyways, hope that helps

share|improve this answer
    
A quick bit of googling found me this, which seems to do what I described above: cyberciti.biz/faq/iptables-connection-limits-howto –  Ryan Wiancko Aug 22 at 16:20
    
Nice! I'd use ipset rather than elongating the iptables chain, but the idea is great and I think I'll apply them to my production servers. Thanks for sharing! –  pepoluan Aug 23 at 14:48
1  
I just read about ipset for the first time the other day and was gleefully delighted to learn about what it does.. I'm a little scared to implement it just because I'll probably muck it up in the beginning and shut the server down but it's on my list of things to learn here. That being said my iptable chain is probably around 30-40 items and only gets 1 new one every day or two so it's not at a point that I'm overly worried. –  Ryan Wiancko Aug 24 at 19:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.