OpenSSH 8.9 Rejects an Old RSA Key While fail2ban Locks Out an Office
bastion is an Ubuntu 22.04 jump host running OpenSSH 8.9p1. sshd_config sets PasswordAuthentication no, PubkeyAuthentication yes, AllowGroups ssh-users, AuthorizedKeysFile .ssh/authorized_keys, StrictModes yes and LogLevel INFO.
A new administrator, alice, was added to ssh-users (id alice shows the group), and her key was copied with ssh-copy-id, but she receives alice@bastion: Permission denied (publickey). Her key is an RSA 2048-bit key generated in 2019 with PuTTYgen and converted with puttygen -O private-openssh. /home/alice is 0755, /home/alice/.ssh is 0700, authorized_keys is 0600, all owned by alice. AppArmor is not confining sshd, and SELinux is not in use.
At the same time, fail2ban (jail sshd, maxretry 3, findtime 10m, bantime 1h) has banned 203.0.113.10 - the NAT address of alice's office, where 40 staff work - after three failed logins from one misconfigured monitoring script. Legitimate staff are now locked out, and the ban will not expire for another 47 minutes.
1. List, in the order you would check them, the reasons alice's key is refused, and say which one is most likely given the details.
Read the worked answer
- What sshd actually thinks its configuration is:
sshd -T | grep -Ei 'allowgroups|authorizedkeysfile|pubkeyauthentication|pubkeyacceptedalgorithms'. FirstMatch and Include can change what you read in the file.AllowGroupsis evaluated with the NSS stack; if the group was just created or alice just added, an SSSD or nscd cache on the bastion may not see it yet, so checkgetent group ssh-usersas well asid alice. A missing group membership looks exactly like a key problem in the client. - StrictModes: a failure logs
Authentication refused: bad ownership or modes for file ...only atLogLevel VERBOSE, so raise it temporarily. Every parent directory must also not be group- or world-writable; a chown done carelessly often leavesauthorized_keysowned by root. - Key algorithm. This is the most likely cause here: OpenSSH disabled the SHA-1
ssh-rsasignature by default in 8.8, so a 2019 PuTTYgen RSA key offers a signature algorithm that 8.9 will not accept. The client just saysPermission denied, while the server at DEBUG level logs a line likesignature algorithm ssh-rsa not in PubkeyAcceptedAlgorithms. Confirm by runningssh -vvv alice@bastionand looking at the offeredpublickey ... ssh-rsaline.
Fix properly by issuing an ed25519 key: ssh-keygen -t ed25519 -a 100, install it, and remove the old entry. A temporary workaround is PubkeyAcceptedAlgorithms +ssh-rsa in sshd_config, but it re-enables SHA-1 for everyone and should be time-boxed and documented. Debug interactively with sshd -ddd -p 2222 on a second session before reloading the production daemon.
2. The office NAT address is banned. Explain how to lift it and how to prevent this class of false positive without removing brute-force protection entirely.
Read the worked answer
Lift it first: fail2ban-client status sshd shows the banned address and the matched log lines; fail2ban-client set sshd unbanip 203.0.113.10 removes it from the database so it survives a fail2ban restart, unlike editing a file by hand or letting the timer expire. Restarting fail2ban also re-applies the ban from its database, which is a common surprise.
The design problem is that a ban is per source address, and a NAT address is shared by 40 people. Options, in order of preference:
- With
PasswordAuthentication noalready set, brute-force login is not a real threat to this host. The monitoring script's failures are noise. Switch the filter tomode = normalso lines such asConnection closed by authenticating userorReceived disconnect- which a broken script produces in bulk - no longer count as failures. - Add
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24to the jail or to[DEFAULT], and raisemaxretry/findtimefor the sshd jail while shorteningbantime. - Replace the full ban with per-source rate limiting (iptables hashlimit or nftables meters) so one noisy source is throttled rather than cut off.
Do not simply disable the jail: a password-only service somewhere else would then be unprotected. Decide based on whether the host accepts passwords, and make that decision explicit in the jail's comment so the next administrator understands why the NAT range is allow-listed.
3. Propose the sshd configuration changes that make this kind of incident less likely while keeping 40 staff working, and say how you would validate them safely.
Read the worked answer
Goals: keep password auth off, make each user's source address meaningful, and make failures auditable without locking out a whole office.
PermitRootLogin prohibit-password
KbdInteractiveAuthentication no
MaxAuthTries 3
LoginGraceTime 20
MaxStartups 10:30:60
LogLevel VERBOSE
Match Address 10.8.0.0/24,203.0.113.0/24
AuthenticationMethods publickey
Use a Match block to require publickey from the corporate ranges while keeping the global rules simple; avoid stacking AllowGroups and Match in ways that interact unpredictably, and test both orders with sshd -T -C user=alice,addr=203.0.113.10,host=office to see the resulting configuration for a specific connection. sshd -t must pass before any reload.
A better long-term answer for the shared office address is to put staff behind a WireGuard or OpenVPN endpoint: each user then arrives from a distinct tunnel address, fail2ban can act precisely, and the office NAT is no longer a single point of lockout.
Validation: keep an existing session open, run sshd -t, systemctl reload ssh, then test from a machine you control with ssh -vvv and confirm the log now records Accepted publickey for alice ... SHA256:<fingerprint>. LogLevel VERBOSE gives you the fingerprint, which is what you need to correlate an incident later, and it costs nothing in disk. Only after a successful test should you close the emergency session.