Page 1 of 1

allow only a country with iptables

Posted: 2013/05/21 18:30:14
by comodino
Hi everybody,
i would like to allow all comunication to/from my server from/to only a country.
I hase seen that is possible to block ip by country...but is simpler to allow a country instead of deny (n-1) country...
can you help me?
Thanks

allow only a country with iptables

Posted: 2013/05/21 20:00:09
by TrevorH
The only way I know of to allow/block by country is to research which IP subnets are allocated to which country and then code up iptables rules for those ranges. Given this, it's much easier to allow one country than it is to exclude the other 163 (or however many it is this week).

Re: allow only a country with iptables

Posted: 2013/05/21 21:32:55
by jerseyjoe
MaxMind provides a database both as free (leaving a bit to be desired) and pay product that lists all the IP ranges they know about in a specific country.
Keep in mind there could be a large number of proxy in a given country (corporate and otherwise) which could mean that someone could originate outside a country but appear to be inside the country in question.
So there's a place to start to identify all the IPs you want to block or allow.
It should also give you an idea of the scope of just how much work you are talking about.

Then you have to start asking yourself questions like:
What if the 'country' is something like the EU?
What if you mean all of North America?

Then start asking about:
What happens when you need to update this information as it evolves?
What happens if you find IPs in the country in question that MaxMind did not know about: how will you handle those changes to allow changes from MaxMind's own changes with time?

This is all quite doable as I've done it before, but I encourage you to really think about the lifecycle of it.

JerseyJoe

Re: allow only a country with iptables

Posted: 2013/05/22 08:24:40
by assen
Hi,

There are two ways I have done this.

First, if you have an AS (or can convince your ISP to have a BGP session with you using a private AS), you can receive via BGP only routes that originate within your country. There are many ways to do, like checking the list of AS for your country (which is much shorter than the list of IP prefixes), or using the number of hops, or by having separate BGP sessions for national peers etc.

Second, you can use a LIR's public database dump (from RIPE, ARIN etc.) to retrieve the list of all IP address assignments. Each has a country conde and these with size of at least /24 are usually good to use. The database is plain text, so you only need a simple parser.

Whichever way you go, consider aggregating the IP prefixes as this can reduce the number of netfilter rules tenfold.

Once you have automated this, you'll rarely need to run it mode than once a month.

WWell,

Re: allow only a country with iptables

Posted: 2013/05/22 09:38:06
by TrevorH
I'd also recommend using ipsets and not individual iptables rules for each IP block. Using ipset is much more efficient than having thousands of iptables rules.

Re: allow only a country with iptables

Posted: 2013/05/22 14:17:24
by comodino
Thanks...the reason to this solution is that, in my log file of httpd (access and error) there are log like these:
[code]
xx.xxx.xxx.xxx - - [20/May/2013:20:16:45 +0200] "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 226 "-" "-"
xx.xxx.xxx.xxx - - [21/May/2013:16:46:12 +0200] "GET /vtigercrm/graph.php?current_language=../../../../../../../..//etc/elastix.conf%00&module=Accounts&action HTTP/1.1$
xx.xxx.xxx.xxx - - [21/May/2013:18:22:27 +0200] "GET /vtigercrm/graph.php?current_language=../../../../../../../..//etc/elastix.conf%00&module=Accounts&action HTTP/1.1$
xx.xxx.xxx.xxx - - [21/May/2013:23:55:43 +0200] "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 226 "-" "-"
xx.xxx.xxx.xxx - - [21/May/2013:23:55:43 +0200] "GET /" 400 476 "-" "-"

[Tue May 21 16:46:12 2013] [error] [client xx.xxx.xxx.xxx] File does not exist: /var/www/vhosts/default/htdocs/vtigercrm
[Tue May 21 18:22:27 2013] [error] [client xx.xxx.xxx.xxx] File does not exist: /var/www/vhosts/default/htdocs/vtigercrm
[Tue May 21 23:55:43 2013] [error] [client xx.xxx.xxx.xxx] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /w00tw00t.at.ISC.SANS.DFind:)
[/code]

and i have seen that the ip are often from china, russia, ...

i have seen on the web on internet [url=http://www.cyberciti.biz/faq/block-entier-country-using-iptables/]how block country with iptables[/url]
but instead of block several country i would like to block all in my iptables and allow only one country like Germany.
To do this i have found on internet this script

[code]
#!/bin/sh
# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.
### Allow all traffic from hungary (hu) Use ISO code separated by space ###
ISO="hu"

### Set PATH ###
IPT=/usr/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep

### No editing below ###
ACCEPTLIST="countryok"
ZONEROOT="/root/iptables"
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"

cleanOldRules(){
$IPT -F $ACCEPTLIST
}

# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT

# clean old rules
cleanOldRules

# create a new iptables list
$IPT -N $ACCEPTLIST

for c in $ISO
do
# local zone file
tDB=$ZONEROOT/$c.zone

# get fresh zone file
$WGET -O $tDB $DLROOT/$c.zone

# country specific log message
SPAMDROPMSG="External IP Drop"

# get
GOODIPS=$(egrep -v "^#|^$" $tDB)
for ipaccept in $GOODIPS
do
$IPT -A $ACCEPTLIST -s $ipaccept -j RETURN
done
done

# Allow transmission
$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 51413 -j RETURN
$IPT -A $ACCEPTLIST -p udp -m udp --dport 51413 -j RETURN

# Log and Drop everything else
$IPT -A $ACCEPTLIST -j LOG --log-prefix "$SPAMDROPMSG"
$IPT -A $ACCEPTLIST -j DROP
$IPT -I zone_wan -j $ACCEPTLIST

exit 0
[/code]

i haven't already test it....but is there a solution less heavy?
for exemple if i write in my iptables this:
[code]
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
[/code]
can prevent the log in my log file?

Re: allow only a country with iptables

Posted: 2013/05/22 14:37:22
by jerseyjoe
Are you sure you really want to merely get rid of the log entry?

Perhaps it would be wise to consider Snort IDS somewhere in your network.
This would do more for your front line security than merely blind you to traffic from the foreign hosts.
It would additionally allow you to honeypot these possible trouble makers.

The last rule you specified is basically allow established connections.
Are you sure you want ESTABLISHED connections not RELATED connections is the first question with that rule.
I presume from the HTTP this is a webserver so think that over.

Re: allow only a country with iptables

Posted: 2013/05/22 14:38:39
by TrevorH
As noted above, if you intend to do this I would use ipsets. You can `yum install ipset` then do something like this (as an example)

[code]
ipset -N UK_IP nethash
ipset -A UK_IP xxx.xxx.xxx.xxx/24
ipset -A UK_IP yyy.yyy.yyy.yyy/24
iptables -A INPUT -m state --state NEW -m set --set UK_IP src -m tcp --dport 80 -j ACCEPT
[/code]

This uses one iptables rule per country and a 'set' to which you add all the subnets which belong to that country.

Hmm, seems the ipset package has no initscript so you'll have to devise a mechanism to save/restore them on reboot etc.

Re: allow only a country with iptables

Posted: 2013/05/22 15:10:49
by comodino
for exemple to allow only UK and ES, on all port and then to all server, should I do this?

[code]
ipset -N geoAllowIP nethash
for IP in $(wget -O – http://www.ipdeny.com/ipblocks/data/countries/{uk,es}.zone)
do
ipset -A geoAllowIP $IP
done

ipset save geoAllowIP

iptables -A INPUT -m state --state NEW -m set --set geoAllowIP src -j ACCEPT
[/code]

is true? so only the ip in the list can interact with server? (http, https, ftp, ssh....)

Re: allow only a country with iptables

Posted: 2013/05/22 16:09:01
by TrevorH
The general idea looks correct although I didn't check the details. You will need to modify the `ipset save` part since that just dumps the config to stdout in the same way that iptables-save does - so it's not persistent storage.