Tuesday, June 23, 2009

SSH access control with GeoIP

All admins of our systems are in Japan, so it is reasonable to block SSH login attempts from other countries. (Disabling password login is the best to block bruteforce attacks, but in some cases it simply can't be done for some reason... Also, iptables -m recent does good job for that.)

On Debian-based systems it is possible to call external program from /etc/hosts.allow to allow/deny a client. I implemented a country filter based on GeoIP for SSH protection.

Firstly, we need to regularly update GeoIP database. Free database seems to be updated every month. I run this script by cron.daily to check if it is updated and download it if it is. (Database is saved to the directory where the script is.)

/etc/hosts.allow is something like this:
sshd: ALL: aclexec /usr/local/geoip/check %a
then in /etc/hosts.deny:
sshd: ALL
so that connections not explicitly allowed are denied.

Finally this is the script I call from aclexec. Filtering rules are written in function "rule". In this case clients from Japan and unknown are allowed to connect.
Both scripts use syslog for diagnostic output.

This setup can be used for other services such as FTP.


Nautica said...

I tried your solution on a Centos 5 with directadmin without any effort. It blocks everyone that try to login to ssh. GeoIP is installed but i used the Apache Api for my website.
Did you install the python API of GeoIP? Could you be more specific where you put the files and how GeoIP is configuered?

ts1 said...

At first read the log for error messages.
I put 'check' and 'update' scripts in /usr/local/geoip. GeoIP.dat is downloaded in the same directory.
Python GeoIP binding is used by check script.
I don't know if aclexec works on non-Debian OS.

Josh said...

I was also unsuccessful with CentOS 5. After installing the GeoIP Python and C libs from maxmind.com, I found out that RedHat-based systems don't offer aclexec in hosts_options (aka hosts.allow/hosts.deny). I'm out of ideas on a solution.

vrana said...

Thanks for good idea.
For RedHat_based system change "aclexec" to "spawn (command %a)".

Zydoon said...

It works like a charm

Thank you