Safe changes on a shared server
On your own server, a bad SSH change locks out one person: you. On an agency box or a shared host, it locks out everyone who logs in a way you didn't know about. Find out who they are first.
Published . Ubuntu and Debian servers running OpenSSH, with systemd and the journal.
- Why shared servers are different
- Who is logged in, and who has been
- Whose keys are on the server
- Who is allowed in, by config
- Turning off passwords locks out password users
- Per-user rules with Match
- Announce the change, then make it
Why shared servers are different
Most SSH hardening advice assumes one admin with one key. A shared server has a developer who still uses a password, a contractor with a key in someone else's authorized_keys, a deploy script that logs in every night, and a client who logs in twice a year. None of them are watching when you restart sshd.
Your own test login working proves only that you can get in. Before changing SSH or the firewall, build a list of every account that logs in, from where, and with what.
Who is logged in, and who has been
Start with who is on right now:
who -H
Then the login history. last reads /var/log/wtmp; -i shows IP addresses instead of names:
last -i | head -50
History only goes back as far as the log has been kept, and automated logins that don't open a terminal may be missing. The SSH log shows every login and the method used:
sudo journalctl -u ssh --since "30 days ago" | grep "Accepted"
Each line says Accepted publickey for or Accepted password for, then the user and the source address. That's the list that matters. Anyone on the password side is who you'd lock out by turning passwords off.
Whose keys are on the server
Find the accounts that can log in at all, meaning they have a real shell:
getent passwd | awk -F: '$7 !~ /(nologin|false)$/ {print $1, $6}'
Then count the keys in each account's authorized_keys. Home directories may not be readable by you, so run it as root:
sudo sh -c 'wc -l /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys'
Read each file. The comment at the end of a key line often names the person or machine. A key you can't identify belongs to someone, so ask before you remove it. Also check where sshd actually looks for keys, in case it was changed:
sudo sshd -T | grep -i authorizedkeysfile
Who is allowed in, by config
Check whether the server already limits logins by user or group:
sudo sshd -T | grep -Ei '^(allowusers|allowgroups|denyusers|denygroups)'
sshd -T prints the config sshd really uses, after all included files, so it's more reliable than reading sshd_config by eye.
Be careful adding these yourself. Once AllowUsers is set, only the listed users can log in. Once AllowGroups is set, only members of the listed groups can. Everyone else is refused, even with a valid key. A DenyUsers match wins over AllowUsers. If you use them, a group like sshusers is easier to keep right than a list of names, because adding a person doesn't need an sshd restart.
Turning off passwords locks out password users
PasswordAuthentication no is good advice. On a shared server it also means that every person who logs in with a password is cut off at the next restart, and nobody tells them why. The same goes for keyboard-interactive logins, which KbdInteractiveAuthentication controls.
Don't turn off passwords until every password user has a working key. Use the Accepted password list from the log. Ask each person to send you their public key, add it, and have them confirm a key login works before you change anything. Those who can't switch yet get a Match block, below.
The full steps for the switch itself are in Disable SSH password authentication.
Per-user rules with Match
A Match block applies settings only to connections that fit it. Put it at the end of /etc/ssh/sshd_config, because everything after a Match line belongs to it until the next Match or the end of the file. To turn passwords off for everyone except one account that still needs them:
PasswordAuthentication no
Match User legacy-deploy
PasswordAuthentication yes
On Ubuntu and Debian, files in /etc/ssh/sshd_config.d/ are read first, and the first value wins. If one of them already sets PasswordAuthentication, your global line is ignored, so check with sshd -T.
Or allow passwords only from the office network:
Match Address 198.51.100.0/24
PasswordAuthentication yes
Only some keywords work inside a Match block, but PasswordAuthentication, KbdInteractiveAuthentication, AuthenticationMethods and PermitRootLogin all do. Test what a specific user will get before you restart:
sudo sshd -t
sudo sshd -T -C user=legacy-deploy,host=your.server.example,addr=203.0.113.25 | grep -i passwordauthentication
sudo sshd -T -C user=maria,host=your.server.example,addr=203.0.113.26 | grep -i passwordauthentication
The first should say yes and the second no. Then restart and keep your current session open while you test a fresh login.
Announce the change, then make it
- Say what changes and when. "From Thursday 10:00, SSH needs a key. Send me yours by Wednesday."
- Pick a time when people are around to tell you if they can't get in, not Friday night.
- Change one thing at a time. Passwords this week,
AllowGroupsnext week. If someone is locked out, you know why. - Keep a way back that doesn't depend on SSH, such as your provider's web console, and a session that stays open until a fresh login works.
The same applies to firewall rules. Before you limit port 22 to a few addresses, check the last -i and log output for every address people log in from. More on safe ordering in SSH hardening without lockout.
Stenvakt was built for shared servers. Its shared-SSH protection means it never locks out other people's logins: it checks who logs in and how before it touches SSH. You see a Preview of every fix, and fixes run in safe mode, so if a change cuts off SSH the server rolls it back by itself. It's a Mac app and isn't out yet: get early access.
Sources
- OpenBSD manual: sshd_config(5) (AllowUsers, AllowGroups, Match, PasswordAuthentication)
- OpenBSD manual: sshd(8) (-t, -T and -C)
- Ubuntu manpage: last(1)
- Ubuntu manpage: who(1)
- Ubuntu Server docs: OpenSSH server