Find the key by fingerprint
A comment like alice@laptop can be changed and proves nothing, so search by fingerprint. If you have the public key:
ssh-keygen -lf alice.pub
256 SHA256:NxFS05Q+k1zf9LgrjGPL94UJfFS6B/89THkWACOEJgg alice@laptop (ED25519)
If you do not have it, the server log shows which key each login used:
Accepted publickey for deploy from 203.0.113.10 port 33998 ssh2: ED25519 SHA256:NxFS05Q+k1zf9LgrjGPL94UJfFS6B/89THkWACOEJgg
See how to check SSH logins for where that log is.
Search one server
Run this as root, because each ~/.ssh is private to its owner:
sudo bash -c '
FP="SHA256:NxFS05Q+k1zf9LgrjGPL94UJfFS6B/89THkWACOEJgg"
for f in /root/.ssh/authorized_keys* /home/*/.ssh/authorized_keys*; do
[ -f "$f" ] && ssh-keygen -lf "$f" | grep -F "$FP" && echo " found in $f"
done'
Check for service accounts with homes elsewhere, and for a different AuthorizedKeysFile:
sudo sshd -T | grep -i authorizedkeysfile
getent passwd | cut -d: -f1,6
Search all servers
Save the search above as a script on each server, or run it through a loop from your own machine. The list of hosts is yours to supply, and sudo must not ask for a password here:
while read -r host; do
echo "== $host"
ssh -n "$host" sudo /usr/local/bin/find-ssh-key
done < hosts.txt
Do not forget machines that are not servers in the usual sense: Git hosting, network devices, jump hosts, CI runners and backup targets.
Why the -n matters in that loop is explained in how to run a command over SSH.
Remove the key
Match on the key itself, not on the comment, and keep a backup:
KEY=$(cut -d' ' -f2 alice.pub)
f=/home/deploy/.ssh/authorized_keys
sudo cp -p "$f" "$f.bak"
sudo grep -vF "$KEY" "$f.bak" | sudo tee "$f" > /dev/null
Delete the backup once you have checked that the others can still log in. The same key can appear on more than one line, and this removes all of them.
Block it with RevokedKeys
Removing the lines fixes what you found. RevokedKeys also blocks the key on any account where you did not find it, or where it gets added back. The simplest form is a file of public keys:
sudo cp alice.pub /etc/ssh/revoked_keys
sudo chmod 644 /etc/ssh/revoked_keys
# /etc/ssh/sshd_config.d/10-revoked.conf
RevokedKeys /etc/ssh/revoked_keys
sudo sshd -t && sudo systemctl reload ssh
The service is called sshd on Red Hat and Fedora systems. A login with that key now fails, and the log says:
Authentication key ED25519 SHA256:NxFS05Q+k1zf9LgrjGPL94UJfFS6B/89THkWACOEJgg revoked by file /etc/ssh/revoked_keys
Create the file before you add the setting. If it is missing or unreadable, sshd refuses public key logins for all users. In our test the log said Error checking authentication key ... in revoked keys file. An empty file is fine.
A KRL for many keys
A Key Revocation List is a compact binary version of the same file, and the setting is the same. Create one, and add to it with -u. Without -u, it replaces what was there:
sudo ssh-keygen -k -f /etc/ssh/revoked_keys alice.pub
sudo ssh-keygen -k -u -f /etc/ssh/revoked_keys bob.pub
Check a key against it:
ssh-keygen -Q -f /etc/ssh/revoked_keys alice.pub
alice.pub (alice@laptop): REVOKED
A key not on the list shows ok. The exit code is 1 when a key is revoked and 0 when it is not, which is handy in scripts. You can list what a KRL contains with ssh-keygen -Q -l -f /etc/ssh/revoked_keys.
End the sessions already open
A revoked key only stops new logins. In our test, a session opened before the key was removed kept running and finished normally. Look for open sessions with who, and if it is that person's own account, end them:
sudo pkill -KILL -u alice
This kills everything that account is running, so do not use it on a shared account without looking first.
Close the account
Some common commands do less than you would expect. We tested each with a working key:
| Command | Can the key still log in? |
|---|---|
passwd -l alice | Yes. It locks only the password. |
usermod -s /usr/sbin/nologin alice | It gets no shell, but ssh -L tunnels still work. |
chage -E 0 alice | No. The log says Access denied for user alice by PAM account configuration. |
Use chage -E 0 to block the account at once, and delete it later with userdel once you know nothing depends on it.
Everything else the person knew
If the person had access to a shared account or a server's root, a key may be only part of it. Check for:
- Shared accounts: replace their keys and passwords.
- Private keys they could read, such as deploy keys: replace them, and revoke the old ones.
- Crontabs and
sudoersfiles that mention them. - Keys added under other accounts. Compare what is in each
authorized_keysfile with what you expect to be there.
Make it easier next time: short-lived certificates
With SSH certificates there is no list of keys on each server. The server trusts a certificate authority, and each certificate expires by itself. This signs a key for eight hours, for the account deploy:
ssh-keygen -s user_ca -I alice@example.com -n deploy -V +8h -z 1001 alice.pub
When someone leaves, stop signing for them. The last certificate stops working on its own, and the log says Certificate invalid: expired. To cut off a certificate before then, revoke it by identity or serial number. Write a small file called spec:
id: alice@example.com
serial: 1001
sudo ssh-keygen -k -u -f /etc/ssh/revoked_keys -s user_ca.pub spec
See SSH certificates explained for the setup.
Questions
Does deleting a Linux user remove their SSH access?
Deleting the account with userdel stops logins to it. Locking only the password with passwd -l does not: a key still logs in. Their key may also sit in other accounts, so search by fingerprint.
Do open SSH sessions end when a key is removed?
No. Removing or revoking a key only stops new logins. End the sessions already open, for example with pkill on the person's own account.
What is an OpenSSH KRL?
A Key Revocation List: a compact binary file of revoked keys and certificates, made with ssh-keygen -k and named by RevokedKeys in sshd_config.