Monday, November 28, 2016

Build a (fire)wall and make China pay for it

I've been gradually building up a Raspberry Pi for use in my shack, and I've also been experimenting with a home control and security systems hosted on Pi platforms.  To be really useful, a home control system needs to be accessible from outside my home, and a remote radio setup would also be nice.  This has led me down a path of learning about how to conveniently but safely expose ports on my Pi platforms to the internet.

At any given moment, there are thousands of attackers active on the internet.  If you expose ports like TCP 80 (web server), or TCP 22 (ssh) you will be attacked, likely within minutes.  These attacks range from sophisticated hack attempts carried out by state-sponsored security teams, to teenagers running automated scanners that look for obvious weaknesses like unmodified default passwords.

Most attacks try to leverage brute-force methods - they start with a presumption that the superuser login is "pi" (the default) and work through a list of obvious passwords like the default "raspberry", or "pi", or "password", or "123456", etc.

Presuming you've changed your superuser password (and ideally your login name) an easy method to add security is to implement fail2ban.  The fail2ban method tracks failed login attempts over time, and if the same IP address fails more than X times within Y minutes, that address is then added to a ban list in iptables.  If your password is non-obvious, this works fairly well.  The problem is that, without additional setup, iptables exist in memory and are wiped on every reboot.  And because they exist in memory, you'll ultimately waste Pi resources trying to exclude billions of IP addresses.  It's possible to preemptively ban ranges and subnets of IP addresses, but you're still talking about nearly 8,000 entries just for a single country like China.  Also; fail2ban only works if someone actually attempts a login - it does nothing about attackers who probe connections without logging in.

The reality is, the number of IP addresses from which I want to allow connection is very small, and (unless I'm traveling) they're all US-based.  So the trick is to only allow connection from IP addresses originating in the US.  Turns out this is possible using GeoIP and some scripting.  The GeoIP method uses a file database of IP address ranges listed by country.  When an ssh client connects, their IP address is compared with the database.  If the IP address is not from the US, it refuses the connection.
I still run fail2ban, to handle any US-based attackers, and to deal with any non-ssh traffic.  Let me know in comments if you use GeoIP for security, and what you think of my strategies.

No comments: