Tightening UFW Firewall Rules to Limit SSH Access

The auth.log on one of my servers (really, on all of the servers I have access to) is full of stuff like this:

Dec  8 03:19:33 localhost sshd[4718]: User root from 10.1.2.3 not allowed [...]
Dec  8 03:19:35 localhost sshd[4721]: Invalid user db2inst1 from 10.1.2.3
Dec  8 03:19:38 localhost sshd[4723]: User root from 10.1.2.3 not allowed [...]

fail2ban is configured to (temporarily) block these after a certain number of attempts, but they keep coming back. One particular IP address was hitting ssh constantly (except for the ban periods) for several days, so I added a rule to drop everything from that address -- but this strategy isn't scalable.

The simple, obvious solution is to only allow access from known hosts. It would be very rare that I need to access this server from anywhere except a small number of addresses. I started with a ufw (Ubuntu's "uncomplicated firewall") ruleset like this:

% sudo ufw status
Status: activeTo                         Action      From
--                         ------      ----
Anywhere                   DENY        10.1.2.3
Anywhere                   DENY        172.16.99.88
22                         ALLOW       Anywhere

To avoid getting locked out, I added (temporarily) a crontab entry for root:

*/15 * * * * /usr/sbin/ufw allow ssh

This will allow access to ssh from any un-banned IP address (the current policy) every 15 minutes. Then I inserted a rule that allows access to ssh from my home ISPs netblock. (You can figure out the netblock by doing a whois lookup on your external IP address; you may need to add multiple netblocks if your ISP has several allocated. Be careful: it's no fun to get locked out!) This action is safe because I have not yet removed global ssh access. Note that I'm using "insert 3" to add this rule at a specific position in the list.

sudo ufw insert 3 allow proto tcp from 10.9.8.0/18 to any port 22

And I added a rule to permit access from another server with a fixed IP I have access to (for the rare case where I need to access this server when I'm not at home):

sudo ufw insert 3 allow proto tcp from 172.17.101.102 to any port 22

Now my ruleset looks like:

Status: activeTo                         Action      From
--                         ------      ----
Anywhere                   DENY        10.1.2.3
Anywhere                   DENY        172.16.99.88
22/tcp                     ALLOW       172.17.101.102
22/tcp                     ALLOW       10.9.8.0/18
22                         ALLOW       Anywhere

So far, so good, but ssh access is still permitted from anywhere -- because of that last rule. This is the dangerous part... you could get locked out if you haven't set the rules correctly. (You set up that crontab entry, right?)

sudo ufw delete allow ssh

Wait for the prompt... hooray, I'm still connected! After checking that I can access ssh from home and the other server, I know it's safe to remove the crontab job. (If the cron job has already fired, you'll need to rerun the ufw delete allow ssh command.)

At this point I can delete the first two rules that ban specific IPs, since they're outside my netblock and won't be allowed anyway.

Now I can enjoy quieter logs without all those access attempts from China and Croatia!

Posted on 2011-12-08 by brian in security .
Comments on this post are closed. If you have something to share, please send me email.