Require two factors for SSH
Task
Configure SSH to require both a key and a one-time code, getting the one- character distinction right that decides whether you have two factors or a choice of one. Prove it end to end, and prove the common misconfiguration fails open.
Steps
- Set up key authentication and confirm it works, as in the SSH lab.
- Enrol a TOTP secret for your user with
google-authenticator, saving the emergency codes. - Add
pam_google_authenticatorto/etc/pam.d/sshdand setChallengeResponseAuthentication yes(orKbdInteractiveAuthentication yes) in sshd_config. - Now the decisive line. Set
AuthenticationMethods publickey,keyboard-interactive-- with a COMMA. The comma means both must succeed. Reload and confirm a login now demands the key AND the code. - Demonstrate the misconfiguration: change the comma to a space (
publickey keyboard-interactive). Reload and confirm that either factor alone now suffices -- you have silently reduced two-factor to one. - Restore the comma. Confirm again that both are required, and that a correct key with a wrong code is refused.
- Confirm the emergency codes work as the second factor when the TOTP device is unavailable.
Verify
sshd -T | grep -i authenticationmethods
# with a valid key but no/ wrong code, login must fail:
ssh -o PreferredAuthentications=publickey user@server true 2>&1 | grep -qi 'denied\|further authentication' && echo "key alone is not enough"
grep -q 'auth.*pam_google_authenticator' /etc/pam.d/sshd && echo "second factor in the stack"
The middle check is the proof: a valid key alone must be refused. If it lets you in, the AuthenticationMethods line has a space where it needs a comma, and your two-factor setup is one factor with extra steps.
Notes
A comma joins methods that must all succeed; a space separates alternatives any one of which suffices. It is a single character deciding whether the machine requires two factors or accepts either -- and the misconfigured version passes every casual test, because your key still logs you in.