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

Posted on in Categories last updated October 26, 2010

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

12 comment

    1. 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
      
  1. 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 |

  2. 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??

  3. 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
    
    1. 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

      1. 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
        
        1. i tried your script i got those errors

          : not foundk.sh: 6: ./masipblock.sh: iptables
          : not foundk.sh: 7: ./masipblock.sh: iptables
          : not foundk.sh: 8: ./masipblock.sh: iptables
          : not foundk.sh: 10: ./masipblock.sh: iptables
          : not foundk.sh: 12: ./masipblock.sh: iptables
          : not foundk.sh: 14: ./masipblock.sh: iptables
          ./masipblock.sh: 19: ./masipblock.sh: Syntax error: “done” unexpected (expecting “do”)

          run on ubuntu 15.04

  4. 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.

  5. 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