Frustrate SSH Scanners with Iptables GeoIP Blocking
Updated 2018: Still working! xt_geoip_dl is now available and handles Geolite2 database downloading, simplifying our script.
In the rare situation that we need to run a system that has SSH exposed to the world, we always install something to monitor and block SSH attempts. On the low end, we use fail2ban or sshguard, but our preference is OSSEC – especially when protecting multiple systems.
The noise generated by SSH scanning is highly annoying – particularly if you’ve set these systems up to email on login failures. We’ve used port-knocking before, but found it cumbersome to use. We recently started using GeoIP blocking on some systems to cut scanning down to almost zero. Since we’re in the United States and aren’t likely to try to access servers from other countries, we simply drop all traffic to port 22 where the address doesn’t map back to the United States.
It’s relatively easy to configure using Xtables and MaxMind’s free GeoIP databases.
1. Install xtables-addons
xtables is available in most distro repositories these days, which is a blessing.
2. Install the following script in /etc/cron.weekly and make it executable
#!/bin/sh TMPDIR=$(mktemp -d /tmp/geoipupdate.XXXXXXXXXX) mkdir -p /usr/share/xt_geoip pushd ${TMPDIR} /usr/libexec/xtables-addons/xt_geoip_dl cd GeoLite2* /usr/share/doc/xtables-addons-2.3/geoip/xt_geoip_build -D /usr/share/xt_geoip [ -d "${TMPDIR}" ] && rm -rf ${TMPDIR}
Note: paths likely vary by distro!
3. Run the script manually to both verify it works and setup the Xtables database
2014-02-06 08:56:10 URL:http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz [766825/766825] -> "/tmp/geoipupdate.AV0CTQk98X/GeoIPv6.csv.gz" [1] 2014-02-06 08:56:11 URL:http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip [1293629/1293629] -> "/tmp/geoipupdate.AV0CTQk98X/GeoIPCountryCSV.zip" [1] Archive: /tmp/geoipupdate.AV0CTQk98X/GeoIPCountryCSV.zip inflating: /tmp/geoipupdate.AV0CTQk98X/GeoIPCountryWhois.csv 101758 entries total 0 IPv6 ranges for A1 Anonymous Proxy 97 IPv4 ranges for A1 Anonymous Proxy 0 IPv6 ranges for A2 Satellite Provider 365 IPv4 ranges for A2 Satellite Provider 1 IPv6 ranges for AD Andorra ... 97 IPv6 ranges for ZA South Africa 480 IPv4 ranges for ZA South Africa 11 IPv6 ranges for ZM Zambia 40 IPv4 ranges for ZM Zambia 9 IPv6 ranges for ZW Zimbabwe 46 IPv4 ranges for ZW Zimbabwe
4. Configure iptables to use geoip blocking
Be careful! You can easily lock yourself out of the system!
You might wish to consider inserting a temporary rule explicitly allowing traffic from your current IP address ahead of the GeoIP rules:
-A RH-Firewall-1-INPUT -s X.X.X.X -m tcp -p tcp --dport 22 -j ACCEPT
Here’s a simple rule to only allow US traffic to port 22. Note this only works if you’re using default deny, which of course, you should be using.
-A RH-Firewall-1-INPUT -m state --state NEW -m geoip --src-cc US -m tcp -p tcp --dport 22 -j ACCEPT
Here’s a different take. Instead of only permitting US traffic to port 22, it blocks non-US traffic to port 22. I only use this so I can see the rule counters and see how much traffic it’s blocking. However, if you’re not running default deny (i.e., you need to hire someone to look at your system configuration) this is what you’d need to use instead of the above rule.
Note that you do not need both rules, just one or the other.
-A RH-Firewall-1-INPUT -m state --state NEW -m geoip ! --src-cc US -m tcp -p tcp --dport 22 -j DROP
5. Restart iptables and test
You should find that your SSH scan attempts drop significantly. On systems we can restrict to a single country, we almost never see any SSH attempts.
Obviously this technique works on other services besides SSH. Experiment and enjoy.
Please comment below if you find this helpful or if you have criticism or suggestions!
Lochlann
March 2, 2015 @ 7:04 pm
This is amazing and I hope to find some way to implement it to an entire server *ALL Ports* especially since recently my entire server has been subject to consistent attempts on all ports from 2 specific countries. I run a photography business so my needs for any other country to access my server asides from the one I am in is non existent.
Is there a way to easily set this up so that it just blocks every single port without having to write a rule for each port; especially since there are so many of them?
Mathias Homann
April 14, 2015 @ 3:16 am
Yes, just don’t have a –dport 22 in your iptables rule…
Rudy
February 17, 2017 @ 3:34 pm
One thing I have wondered about–in iptables, I limit SSH to only my remote IP address. On the same host, however, I have two other servers I can access it from, and I can use the internal network address at the host to access any of these three servers from each other. Do I need to worry about using fail2ban or other measures since I am allowing access only from my single IP address? (I likely will still use fail2ban for Apache, but with port 22 blocked to everyone except my IP, I can’t see if it would make SSH on the server any more secure.)
BLOCKING COUNTRIES VIA IPTABLES – Console.Support
September 28, 2017 @ 9:50 am
[…] Frustrate SSH Scanners with Iptables GeoIP Blocking […]
Bloquer des adresses IP par pays avec IPTABLES - Geek and More
December 23, 2020 @ 1:02 am
[…] https://room362.com/post/2016/blocking-countries-via-iptables/ https://www.internetstaff.com/frustrate-ssh-scanners-geoip-iptables-blocking/ […]
Bloquer des adresses IP par pays avec IPTABLES - idem2lyon
March 28, 2022 @ 12:41 am
[…] https://room362.com/post/2016/blocking-countries-via-iptables/ https://www.internetstaff.com/frustrate-ssh-scanners-geoip-iptables-blocking/ […]