logo

iptables country block

This tool will automatically create iptables rules on Linux system to block all connection from one country or more. The blocklist is created with an API that fetch data in our SQL database based on IP address country location.

Data accuracy

The list of IP address by country below is a grouping of IP by country and CIDR of our database. The data has over 99.5% accuracy on a country basis. The database is updated monthly.

API Usage
First you need to know the code (ISO 3166 format) of the country you would like to block. The full list is available here. Once you have the country code, you can now get the list at the following url (Afghanistan and Argentina in this example). If your browser show the data on a single line, simply view the page source code :
http://ipinfodb.com/country_query.php?country=AF,AR
This will output something like this :
58.147.128.0/19
67.212.160.0/24
80.247.139.0/24
82.205.190.0/21
82.205.198.0/23
82.205.202.0/22
[...]
Automatic bash script
The following script will fetch the right IP addresses of the country you would like to block from our API and then add these rules in iptables.
#!/bin/bash
### IpInfoDB iptables countries block bash script###
### Slightly modified script from http://www.cyberciti.biz
### Countries code available : http://ipinfodb.com/country.txt ###
### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ##
ISO="AF CN"
 
### Set PATH ###
IPT=/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep
ZONEROOT="/root/iptables/"
IPTCBRESTORE="/root/iptables/iptables.cb"
 
### Network config ###
IPTCBDEVICE=eth0
ALLOWPORTS=80,443
ALLOWSUBNET=192.168.0.0/255.255.0.0
 
### No editing below ###
CBLIST="countrydrop"
MAXZONEAGE=7
DLROOT="http://ipinfodb.com/country_query.php?country="
 
cleanOldRules(){
    $IPT -L $CBLIST > /dev/null 2>&1
    if [ $? = 0 ] ; then
	$IPT -D INPUT ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
	$IPT -D OUTPUT ${IPTCBDEVICE:+-o }${IPTCBDEVICE} -j $CBLIST
	$IPT -D FORWARD ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
    fi
    $IPT -F $CBLIST
    $IPT -X $CBLIST
 
    for i  in `$IPT -L -n | grep Chain | cut -f 2 -d ' ' | grep '\-$CBLIST'`
    do
	$IPT -F ${i}
	$IPT -X ${i}
    done
}
 
updateZoneFiles() {
    ZONEARCH=${ZONEROOT}/arch
    mkdir -p ${ZONEARCH}
    find ${ZONEROOT} -maxdepth 1 -mindepth 1 -ctime +${MAXZONEAGE} -exec mv {} ${ZONEARCH} \;
 
    for c  in $ISO
    do
	# local zone file
	tDB=$ZONEROOT/$c.zone
 
	if [ -f $tDB ] ; then
	    printf "Zone file %s is new enough - no update required.\n" $tDB
	else
	    # get fresh zone file if it is newer than MAXZONEAGE days
	    $WGET -O $tDB $DLROOT$c
	fi
    done
    oldzones=`find ${ZONEROOT} -mindepth 1 -maxdepth 1 -type f -exec basename {} \; | cut -f 1 -d '.'`
    # Archive old zones no longer blocked
    for z in $oldzones ; do
	archme=${c}
	for c  in $ISO ; do
	    if [ $c = $z ] ; then archme="X"; fi
	done
	if [ $archme = $z ] ; then
	    mv ${archme} ${ZONEARCH}
	else
	    printf "Working from previous zone file for %s\n" ${z}
	fi
    done
}
 
createIPTLoadFile() {
    printf "# Generated by %s on" $0 > ${IPTCBRESTORE}
    printf "%s " `date` >> ${IPTCBRESTORE}
    printf "\n*filter\n" >> ${IPTCBRESTORE}
    # Create CBLIST chain
    printf ":$CBLIST - [0:0]\n" >> ${IPTCBRESTORE}
    printf "%s INPUT ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST\n" "-I" > ${IPTCBRESTORE}.tmp
    printf "%s OUTPUT ${IPTCBDEVICE:+-o }${IPTCBDEVICE} -j $CBLIST\n" "-I"  >> ${IPTCBRESTORE}.tmp
    printf "%s FORWARD ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST\n" "-I" >> ${IPTCBRESTORE}.tmp
 
    if [ "Z${ALLOWPORTS}" = "Z" ] ; then
	printf "Blocking all traffic from country - no ports allowed\n"
    else
	printf "%s $CBLIST -p tcp -m multiport --dports ${ALLOWPORTS} -j RETURN\n" "-I">> ${IPTCBRESTORE}.tmp
    fi
 
    if [ "Z${ALLOWSUBNET}" = "Z" ] ; then
	printf "Blocking all traffic from country - no subnets excluded\n"
    else
	printf "%s $CBLIST -s ${ALLOWSUBNET} -j RETURN\n" "-I">> ${IPTCBRESTORE}.tmp
    fi
 
    for c  in $ISO
    do
	# local zone file
	tDB=$ZONEROOT/$c.zone
 
	# country specific log message
	SPAMDROPMSG="iptables: ${c}-Country-Drop: "
 
        # Create drop chain for identified packets
	CBLISTDROP=${c}-${CBLIST}-DROP
	printf ":${CBLISTDROP} - [0:0]\n" >> ${IPTCBRESTORE}
	printf "%s ${CBLISTDROP} -j LOG --log-prefix \"$SPAMDROPMSG\"\n" "-A" >> ${IPTCBRESTORE}.tmp
	printf "%s ${CBLISTDROP} -j DROP\n" "-A" >> ${IPTCBRESTORE}.tmp
 
	# Load IP ranges into chains correlating to first octet
	BADIPS=$(egrep -v "^#|^$" $tDB)
	for ipblock in $BADIPS
	do
	    topip=`echo $ipblock | cut -f 1 -d '.'`
	    chainExists=`grep -c :${topip}-${CBLIST} ${IPTCBRESTORE}`
	    if [ $chainExists = 0 ] ; then
		printf "Creating chain for octet %s\n" ${topip}
		printf ":$topip-$CBLIST - [0:0]\n" >> ${IPTCBRESTORE}
		sip=${topip}.0.0.0/8
		printf "%s $CBLIST -s ${sip} -j $topip-$CBLIST\n" "-A" >> ${IPTCBRESTORE}.tmp
	    fi
	    printf "  Adding rule for %s to chain for octet %s\n" ${ipblock} ${topip}
	    printf "%s $topip-$CBLIST -s $ipblock -j ${CBLISTDROP}\n" "-A" >> ${IPTCBRESTORE}.tmp
	done
    done
    cat ${IPTCBRESTORE}.tmp >> ${IPTCBRESTORE} && rm -f ${IPTCBRESTORE}.tmp
    printf "COMMIT\n# Completed on " >> ${IPTCBRESTORE}
    printf "%s " `date` >> ${IPTCBRESTORE}
    printf "\n" >> ${IPTCBRESTORE}
}
 
directLoadTables() {
    # Create CBLIST chain
    $IPT -N $CBLIST
    $IPT -I INPUT ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
    $IPT -I OUTPUT ${IPTCBDEVICE:+-o }${IPTCBDEVICE} -j $CBLIST
    $IPT -I FORWARD ${IPTCBDEVICE:+-i }${IPTCBDEVICE} -j $CBLIST
 
    if [ "Z${ALLOWPORTS}" = "Z" ] ; then
	printf "Blocking all traffic from country - no ports allowed\n"
    else
	$IPT -I $CBLIST -p tcp -m multiport --dports ${ALLOWPORTS} -j RETURN
    fi
 
    if [ "Z${ALLOWSUBNET}" = "Z" ] ; then
	printf "Blocking all traffic from country - no subnets allowed\n"
    else
	$IPT -I $CBLIST -s ${ALLOWSUBNET} -j RETURN
    fi
 
    for c  in $ISO
    do
	# local zone file
	tDB=$ZONEROOT/$c.zone
 
	# country specific log message
	SPAMDROPMSG="$c Country Drop"
 
        # Create drop chain for identified packets
	CBLISTDROP=${c}-${CBLIST}-DROP
	$IPT -N ${CBLISTDROP}
	$IPT -A ${CBLISTDROP} -j LOG --log-prefix "$SPAMDROPMSG"
	$IPT -A ${CBLISTDROP} -j DROP
 
	# Load IP ranges into chains correlating to first octet
	BADIPS=$(egrep -v "^#|^$" $tDB)
	for ipblock in $BADIPS
	do
	    topip=`echo $ipblock | cut -f 1 -d '.'`
	    $IPT -L $topip-$CBLIST > /dev/null 2>&1
	    if [ $? = 1 ] ; then
		printf "Creating chain for octet %s\n" ${topip}
		$IPT -N $topip-$CBLIST
		sip=${topip}.0.0.0/8
		$IPT -A $CBLIST -s ${sip} -j $topip-$CBLIST
	    fi
	    printf "  Adding rule for %s to chain for octet %s\n" ${ipblock} ${topip}
	    $IPT -A $topip-$CBLIST -s $ipblock -j ${CBLISTDROP}
	done
    done
}
 
loadTables() {
    createIPTLoadFile
    ${IPT}-restore -n ${IPTCBRESTORE}
    #directLoadTables
    printf "Country block instituted for: %s\n" "$ISO"
}
 
# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
 
# clean old rules
cleanOldRules
 
# update zone files as needed
updateZoneFiles
 
# create a new iptables list
loadTables
 
exit 0