Blocking IP Addresses Of Any Country With iptables

This article explains how you can block IP addresses of any country with the help of iptables.

Source : http://blogama.org/node/

 

The API to get the IP addresses to block

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):

http://blogama.org/country_query.php?country=AF,AR

If you dont see IP addresses by lines, view the page code.

 

How often is data updated

During the first week of each month.

 

The full SQL database

For the full SQL database of this data, please read this page.

 

Automatic bash script to block those IP addresses in iptables

The following script will:

  1. Fetch the right IP addresses of the country you would like to block from our API
  2. Add these rules in iptables.
#!/bin/bash
###PUT HERE COMA SEPARATED LIST OF COUNTRY CODE###
COUNTRIES="AK,AR"
WORKDIR="/root"
#######################################
cd $WORKDIR
wget -c --output-document=iptables-blocklist.txt http://blogama.org/country_query.php?country=$COUNTRIES
if [ -f iptables-blocklist.txt ]; then
  iptables -F
  BLOCKDB="iptables-blocklist.txt"
  IPS=$(grep -Ev "^#" $BLOCKDB)
  for i in $IPS
  do
    iptables -A INPUT -s $i -j DROP
    iptables -A OUTPUT -d $i -j DROP
  done
fi
rm $WORKDIR/iptables-blocklist.txt
Share this page:

Suggested articles

16 Comment(s)

Add comment

Comments

By:

Hello sir ,

Thank you for this article it would be useful for many sysadmins

 i have developed this script

let me put it here


 

#!/bin/bash                                                                      #
# Blocking IP 4 Countries : RoMiONeT       

#First article was for marchost at howtoforge.com         #

#This SCript is for blocking ips of countries u want         #
# All Rights are reserved By : RoMiONeT                        #  
# for any further help please contact us at                    #
# ( [email protected] [email protected] )            #
####################################
echo "Blocking IPS of any country By : RoMiONeT"
echo ""
echo "To know code of countries which you want to block"
echo "you can enter ( http://www.blogama.org/country.txt )"
echo ""
sleep 3
echo "Below you can type code of country Ex. ( IL ) for Israel "
echo -n " Enter Code : "
read code
wget -c --output-document=ips4countries.txt http://blogama.org/country_query.php?country=$code
for i in `cat /root/ips4countries.txt`
do
iptables -I INPUT -s ${i} -j DROP
done  ;
echo "Best Regards"
echo "RoMiONeT"
echo "[email protected] & [email protected]"
exit 0

 

Thanks

By:

I might be wrong but I think iptables are cascading such as :

deny from all

allow 123.123.123.0/24

allow 123.123.124.0/24

You will have to google for how to do it exactly.

Limit all IP to US


 

By: Kasper

Think it's a bad idea, to fetch the blocklist on every(!) iptables call, especially when the list is updated weekly only. A cron job or a date-check would be a better solution in my opinion.

By:

@kasper : The probability that 1) a subnet change country before the update, 2) that you are actually blocking that country and 3)that a visitor to your website is coming from that specific subnet is very improbable unless you work at google ;)

 

I didnt think of performance issue... I did some quick benchmark with apache ab command.

2 dedicated server sending requests to 1 small VPS with block to china and india (thousands of iptables rules to test...)

WITHOUT iptables block :

-Round 1 :

 Requests per second:    140.46 [#/sec] (mean) on server 1

Requests per second:    153.48 [#/sec] (mean) on server 2

-Round 2:

 Requests per second:    139.69 [#/sec] (mean) on server 1

Requests per second:    147.11 [#/sec] (mean) on server 2

 

 WITH iptables block :

-Round 1:

 Requests per second:    138.17 [#/sec] (mean) on server 1

Requests per second:    143.10 [#/sec] (mean) on server 2

-Round 2

 Requests per second:    154.69 [#/sec] (mean) on server 1

 Requests per second:    151.13 [#/sec] (mean) on server 2

By: Impeach Obama

What's Google got to do with anything?  They're a search engine, not an ISP...

By: Anonymous

Look this.

http://blog.kdn2.info/2010/11/block-facebook-com-with-iptables/

By:

For sites with lots of traffic you are better off looking at the following

 ipset - http://ipset.netfilter.org/

iptables geoip patch -  http://people.netfilter.org/acidfu/geoip/howto/

 

By: WMG

Agreed. Using iptables in this manner only complicates the ruleset; ipset is more geared towards long listed of IP address entries, and far more efficient in terms of lookup since they are indexed. Using iptables with hundreds if not thousands of block requests is a nightmare to manage and very inefficient on the server.

Someone here in the comments also mentioned wanting to allow only one country and block the rest--ipset makes that possible very easily. Great reading here:

https://www.linuxjournal.com/content/advanced-firewall-configurations-ipset

By: Anonymous

Great Howto!  I can't believe this is that simple!

 Is there an efficient way to do the reverse of this?  I have a site where it only needs to be available in the US (actually only 1 state in the US)

 It seems that this would be a good idea, but putting in a ton of Deny statements would slow things down.

Anyone have any ideas?

By: Skinnner

A python version of the script is available here:

http://forum.ipinfodb.com/viewtopic.php?f=9&t=44 (indentation is broken but I'm sure you can work it out)

which will allow importation of the rule file via the iptables-restore command.

As it is, the script expects a line separated list of IP/network addresses in the form w.x.y.z/CIDR, though it will probably work with a full subnet mask instead of CIDR as well. It also expects the ipaddr module to be installed (http://code.google.com/p/ipaddr-py/).

There is no proper error checking in the script, so you'll have to implement that yourself.

I use it in conjunction with the resulting file from the wget command in the above bash script after it has been sorted/unique'd.

Sk

By:

hi

thx for the script, i'm modified for allow only one country access to the ftp server

example:

 first step need to create iptables chain for filter

 

iptables -N ftp-filter

 

second step need to add policy to input chain

 

iptables -A INPUT -p tcp -m multiport --dport ftp,ftp-data -j ftp-filter

 

and use the script:

#!/bin/bash
#first step
#iptables -N ftp-filter
#iptables -A INPUT -p tcp -m multiport --dport ftp,ftp-data -j ftp-filter
#http://www.countryipblocks.net/e_country_data/
COUNTRIE="HU"
WORKDIR="/root/"
#######################################
cd $WORKDIR
wget -c --output-document=iptables-whitelist.txt http://www.countryipblocks.net/e_country_data/"$COUNTRIE"_cidr.txt
if [ -f iptables-whitelist.txt ]; then
  iptables -F ftp-filter
  BLOCKDB="iptables-whitelist.txt"
  IPS=$(grep -Ev "^#" $BLOCKDB)
  for i in $IPS
  do
    iptables -A ftp-filter -p tcp -s $i -m multiport --dport ftp,ftp-data -j ACCEPT
  done
fi
iptables -A ftp-filter -p tcp -m multiport --dport ftp,ftp-data -j REJECT --reject-with tcp-reset
rm $WORKDIR/iptables-whitelist.txt


By: Deniz Gezmis

Make sure you have "--no-check-certificate" switch with wget.

By:

Hello everyone,

I am looking for a shell or perl script to browse a log file, extract the IP, do a whois on each to see if IP address is a facebook or not
if it's a facebook address, the script adds it to a file bloc_ip.txt
if not it goes to the following address ...

since I am not a developer, I want a loan or similar script that I can change it.

Can someone help me?

By: Ryan

 Here is a working block list generator

http://ipinfodb.com/ip_country_block.php

By: hereisanother

Block countries, allow http/https:

#!/bin/sh   # Code Used From Skynet By Adamm   # https://github.com/Adamm00/IPSet_ASUS   # Remove #, then add # on line above to enable logs!   # Optional: Rename [BLOCKED - INBOUND] to specified country (only one name at a time allowed atm)   # Usage is as follows For AsusWRT Merlin:   # sh /jffs/scripts/scriptname.sh "xx xx xx xx"   # or sh /jffs/scripts/countryblock.sh "xx"   # Call the file whatever you want, then just add an entry in /jffs/scripts/firewall-start (above Skynets)   # For example:   # sh /jffs/scripts/countryblock.sh "il"   # chmod 0755 /jffs/scripts/countryblock.sh       if [ -z "$1" ]; then echo "Country Field Cannot Be Empty - Please Try Again"; echo; exit 2; fi   if [ "${#1}" -gt "246" ]; then countrylist="Multiple Countries"; else countrylist="$1"; fi   if [ "$(nvram get wan0_proto)" = "pppoe" ] || [ "$(nvram get wan0_proto)" = "pptp" ] || [ "$(nvram get wan0_proto)" = "l2tp" ]; then   iface="ppp0"   else   iface="$(nvram get wan0_ifname)"   fi   modprobe xt_set   if ! ipset -L -n CountryBlock >/dev/null 2>&1; then ipset -q create CountryBlock hash:net --maxelem 200000 comment; fi   iptables -t raw -D PREROUTING -i "$iface" -m set --match-set CountryBlock src -j DROP 2>/dev/null   # iptables -t raw -D PREROUTING -i "$iface" -m set --match-set CountryBlock src -j LOG --log-prefix "[BLOCKED - INBOUND] " --log-tcp-sequence --log-tcp-options --log-ip-options 2>/dev/null   iptables -t raw -D PREROUTING -i "$iface" -m set --match-set CountryBlock src -p tcp -m tcp -m multiport --sports 80,443 -j ACCEPT 2>/dev/null   iptables -t raw -D PREROUTING -i br0 -m set --match-set CountryBlock dst -j DROP 2>/dev/null   # iptables -t raw -D PREROUTING -i br0 -m set --match-set CountryBlock dst -j LOG --log-prefix "[BLOCKED - OUTBOUND] " --log-tcp-sequence --log-tcp-options --log-ip-options 2>/dev/null   iptables -t raw -D PREROUTING -i br0 -m set --match-set CountryBlock dst -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT 2>/dev/null   iptables -t raw -I PREROUTING -i "$iface" -m set --match-set CountryBlock src -j DROP 2>/dev/null   # iptables -t raw -I PREROUTING -i "$iface" -m set --match-set CountryBlock src -j LOG --log-prefix "[BLOCKED - INBOUND] " --log-tcp-sequence --log-tcp-options --log-ip-options 2>/dev/null   iptables -t raw -I PREROUTING -i "$iface" -m set --match-set CountryBlock src -p tcp -m tcp -m multiport --sports 80,443 -j ACCEPT 2>/dev/null   iptables -t raw -I PREROUTING -i br0 -m set --match-set CountryBlock dst -j DROP 2>/dev/null   # iptables -t raw -I PREROUTING -i br0 -m set --match-set CountryBlock dst -j LOG --log-prefix "[BLOCKED - OUTBOUND] " --log-tcp-sequence --log-tcp-options --log-ip-options 2>/dev/null   iptables -t raw -I PREROUTING -i br0 -m set --match-set CountryBlock dst -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT 2>/dev/null   echo "Banning Known IP Ranges For (${1})"   echo "Downloading Lists"   for country in $1; do   /usr/sbin/curl -fsL --retry 3 http://ipdeny.com/ipblocks/data/aggregated/"$country"-aggregated.zone >> /tmp/CountryBlock.txt   done   echo "Filtering IPv4 Ranges & Applying Blacklists"   grep -F "/" /tmp/CountryBlock.txt | sed -n "s/\\r//;/^$/d;/^[0-9,\\.,\\/]*$/s/^/add CountryBlock /p" | sed "s/$/& comment \"Country: $countrylist\"/" | ipset restore -!   rm -rf "/tmp/CountryBlock.txt"

 

 

By: A

Sadly the domain blogama.org is for sale... 

so none of this actually applies.