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.)
Now I can enjoy quieter logs without all those access attempts from China and Croatia!