≡ Menu

iptables: Read a List of IP Address From File And Block

How do I read a list of ip address (subnets) using a text file and block all of them using Linux iptables command?

You can create a file which contains the list of all blocked ip address or subnets per line. You can read a file line by line using while loop.

Example: iptables Read IPs / Subnets From The Text File

Create a text file - /root/firewall/badips.db as follows:

# Block db
# Added on Aug/19/2009
202.54.1.2
# Spammers
203.1.2.3/29

The basic logic as follows to read a text file:

_input=/path/to/text.db
IPT=/sbin/iptables
$IPT -N droplist
egrep -v "^#|^$" x | while IFS= read -r ip
do
	$IPT -A droplist -i eth1 -s $ip -j LOG --log-prefix " myBad IP BlockList  "
	$IPT -A droplist -i eth1 -s $ip -j DROP
done < "$_input"
# Drop it 
$IPT -I INPUT -j droplist
$IPT -I OUTPUT -j droplist
$IPT -I FORWARD -j droplist

Here is a sample shell script:

#!/bin/bash
# Modify script as per your setup
# Usage: Sample firewall script
# ---------------------------
_input=/root/firewall/badips.db
_pub_if="eth1"
IPT=/sbin/iptables
 
# Die if file not found
[ ! -f "$_input" ] && { echo "$0: File $_input not found."; exit 1; }
 
# DROP and close everything
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
 
# Unlimited lo access
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
 
# Allow all outgoing connection but no incoming stuff by default
$IPT -A OUTPUT -o ${_pub_if} -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -i ${_pub_if} -m state --state ESTABLISHED,RELATED -j ACCEPT
 
 
### Setup our black list ###
# Create a new chain 
$IPT -N droplist
 
# Filter out comments and blank lines
# store each ip or subnet in $ip
egrep -v "^#|^$" x | while IFS= read -r ip
do
        # Append everything to droplist
	$IPT -A droplist -i ${_pub_if} -s $ip -j LOG --log-prefix " Drop Bad IP List "
	$IPT -A droplist -i ${_pub_if} -s $ip -j DROP
done <"${_input}"
 
# Finally, insert or append our black list 
$IPT -I INPUT -j droplist
$IPT -I OUTPUT -j droplist
$IPT -I FORWARD -j droplist
 
 
# Okay add your rest of $IPT commands here 
# Example: open port 53
#$IPT -A INPUT -i ${_pub_if} -s 0/0 -d 1.2.3.4 -p udp --dport 53 -j ACCEPT
#$IPT -A INPUT -i ${_pub_if} -s 0/0 -d 1.2.3.4 -p tcp --dport 53 -j ACCEPT
 
# Open port 80
# $IPT -A INPUT -i ${_pub_if} -s 0/0 -d 1.2.3.4 -p tcp --destination-port 80  -j ACCEPT
 
# Allow incoming ICMP ping pong stuff
# $IPT -A INPUT -i ${_pub_if} -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -m limit --limit 30/sec  -j ACCEPT
# $IPT -A INPUT -i ${_pub_if}  -p icmp -m icmp --icmp-type 3 -m limit --limit 30/sec -j ACCEPT
# $IPT -A INPUT -i ${_pub_if}  -p icmp -m icmp --icmp-type 5 -m limit --limit 30/sec -j ACCEPT
# $IPT -A INPUT -i ${_pub_if}  -p icmp -m icmp --icmp-type 11 -m limit --limit 30/sec -j ACCEPT
 
# drop and log everything else
$IPT -A INPUT -m limit --limit 5/m --limit-burst 7 -j LOG
$IPT -A INPUT -j DROP
 
Tweet itFacebook itGoogle+ itPDF itFound an error/typo on this page?

{ 11 comments… add one }

  • Suren June 7, 2011, 5:17 pm

    the script looks good, but when i run the script i get this message…
    egrep: x: No such file or directory

    • linzhe January 16, 2015, 1:40 am

      the script have som erro,it should be:

      egrep -v "^#|^$"  $_input | while IFS= read -r ip;
      do
      	$IPT -A droplist -i eth1 -s $ip -j LOG --log-prefix " myBad IP BlockList  "
      	$IPT -A droplist -i eth1 -s $ip -j DROP
      done
      
  • Alan September 2, 2011, 12:19 pm

    just remove the egrep bit, I got the same message, its only required if you have whitespace in your list of banned IPs. Make sure it doesnt, and you can remove the egrep part, everything up to and including the pipe |

  • Marco April 9, 2012, 10:20 am

    Hi,
    I have an list.db and it looks like:

    #list of spamers
    14.192.76.0/22
    14.196.0.0/15
    

    ……etc
    when I try to run a script:

    #!/bin/bash
    _input=/root/list.db
    IPT=/sbin/iptables
    #$IPT -N droplist     // I already have BLACKLIST instead droplist
    egrep -v "^#|^$" x | while IFS= read -r ip
    do
    	$IPT -A BLACKLIST -s $ip -j LOG --log-prefix "spam_blacklist" --log-level 7
    done < "$_input"
    

    Im getting error for every entry which got netmask stated as /xx
    … looks like this:
    ‘ specified.4.4: invalid mask `21
    Try `iptables -h’ or ‘iptables –help’ for more information.

    How to alter the script??

  • Sukhjinder December 17, 2012, 7:09 pm

    In case the list of IP address in text file contains duplicate IP address, how is your script will handle it?

  • Dara April 29, 2013, 9:37 am

    It’s not great since egrep doesn’t work and I need comments in the text file…

  • Mee February 8, 2014, 12:20 pm

    Working code

    INTEX="eth1"
    # CHANGE THIS
    badip=/path/to/badip.db
    # [FLUSH OLD RULES]
    $IPT -F droplist
    # [DROP OLD CHAIN]
    $IPT -X droplist
    # [CREATE CHAIN]
    $IPT -N droplist
    /bin/egrep -v "^#|^$" $badip | while IFS= read -r ip
    do
            $IPT -A droplist -i $INTEX -s $ip -j LOG --log-prefix " myBad IP BlockList  "
            $IPT -A droplist -i $INTEX -s $ip -j DROP
    done < "$badip"
    # Drop it
    $IPT -I INPUT -j droplist
    $IPT -I OUTPUT -j droplist
    $IPT -I FORWARD -j droplist
    
    • Som April 6, 2014, 6:49 am

      I used the code above but when i execute the script for second time i get this error:
      iptables: Too many links
      iptables: Chain already exists
      and i think you forgot to insert IPT=/sbin/iptables

      • Som April 6, 2014, 7:23 am

        I added a few lines at the script:

        INTEX="eth1"
        # CHANGE THIS
        badip=/path/to/badip.db
        IPT=/sbin/iptables
        # delete previous droplist (INPUT,OUTPUT,FORWARD)
        $IPT -D INPUT -j droplist
        $IPT -D OUTPUT -j droplist
        $IPT -D FORWARD -j droplist
        # [FLUSH OLD RULES]
        $IPT -F droplist
        # [DROP OLD CHAIN]
        $IPT -X droplist
        # [CREATE CHAIN]
        $IPT -N droplist
        /bin/egrep -v "^#|^$" $badip | while IFS= read -r ip
        do
                $IPT -A droplist -i $INTEX -s $ip -j LOG --log-prefix " myBad IP BlockList  "
                $IPT -A droplist -i $INTEX -s $ip -j DROP
        done < "$badip"
        # Drop it
        $IPT -I INPUT -j droplist
        $IPT -I OUTPUT -j droplist
        $IPT -I FORWARD -j droplist
        
  • uOY May 13, 2014, 1:36 am

    Why people add chain droplist to the OUTPUT chain.

    if you look at the iptables you will see the OUTPUT chain will also try to match the source ip as the bad ip. This will never happen.

    you have to create another loop and make the bad ip as ip destination for the OUTPUT chain.

  • Sam Mingolelli September 25, 2014, 5:17 pm

    You can also setup a ipset and use iptables match set feature instead of adding all these individual IPs as standalone entries in your iptable’s table.

    $ iptables …… -A INPUT -m set –match-set blacklist src -j DROP

Leave a Comment