So, I have a server sitting out there on the internet, and I want to be able to log into it remotely from anywhere. Only here’s the wrinkle, I only want some users to be able to login remotely from anywhere, although I want all users to be able to login from the LAN.
Ok, so cool, SSH provides this cool Match directive that you can use in sshd_config which you can use to limit things like the User and Address and you are even supposed to be able to negate the terms. Sounds great, right? Well, not quite.
Cut to the chase – here’s the block I ended up with:
MaxAuthTries 0 Match User admin Address 192.168.100.0/24 MaxAuthTries 6 Match User creechy MaxAuthTries 6
So what’s this block doing?
By default, its setting the number of authentication attempts (MaxAuthTries) to zero.
Next is a series of Match blocks with all the conditions for allowing each user to login. In this case, I want to allow the admin user to login only from the LAN, but allow creechy to login from anywhere. Within each conditional block I set the maximum number of login attempts to something normal, in this case 6.
The only real downside to this method is that I need to add a block for each user I want to allow to login to the system via SSH. But at the end of the day, this is probably more secure since I know explicitly everything I am allowing.
What didn’t work but probably should have:
My first attempt, which would have been the easiest was to use the negation operator on the address to specifiy everything outside the LAN so that I can deny access.
Match User admin Address !192.168.100.0/24 MaxAuthTries 0
SSH didn’t complain with this syntax, but didn’t seem to honor it either.
So next I thought I’d make two rules, one for allowing access from the LAN and a catch for everywhere else
Match User admin Address 192.168.100.0/24 MaxAuthTries 6 Match User admin MaxAuthTries 0
But this didn’t work. I effectively locked admin out from logging in anywhere. Apparently SSH evaluates all the matching rules. Think changing the order might help? Nope. As far as I can tell, its matching all the rules but it also only uses the first value found for a specific directive, like MaxAuthTries.
Oh well, at the end of the day, I have a decent solution which not much hassle.