Purpose
This will let us use our phone as a second-factor for logging in to an SSH session. This helps harden our SSH security, and encourages users to use 2FA in general. Because it asks for a password that changes every 60 seconds along with your known password, it makes the server MUCH harder to brute-force, especially if it is an Internet-facing server.
Posted on Github as well - comments welcome!
Prerequisites
- Debian / Ubuntu based Linux
- OpenSSH setup and working
- Existing access to the server’s console
- Root priveledges to setup initially; user access later
Bonus - Brute Force Prevention
One neat aspect of this feature is you get better Brute Force prevention! Your server will not even attempt to check your password until after you’ve entered your password and 2FA code. Whether the password is correct or not, the attacker will not know!
Directions
Update your apt repos, and install the required packages:
sudo apt update sudo apt install ssh libpam-google-authenticator
Ensure you have a spare SSH session open, as the following steps could lock you out remotely. You have been warned.
Edit your
/etc/pam.d/sshd
file, and add the following stanza to the very end:# Google Authenticator auth required pam_unix.so try_first_pass auth required pam_google_authenticator.so secret=${HOME}/.google_authenticator
At this point, users cannot log in anymore.
If you only want this on certain accounts, create a stanza in
/etc/ssh/sshd_config
toMatch User
:Match User usernameGoesHere AuthenticationMethods publickey keyboard-interactive:pam
In the above,
usernameGoesHere
can either log in with a Public Key, or with their password and 2-factor code (which is next to be setup). If you want it to match everyone, remove theMatch User...
line.Ensure that the following lines are in your
/etc/ssh/sshd_config
file:ChallengeResponseAuthentication yes UsePAM yes
As the user, run
google-authenticator
, and follow the directions. ChooseY
for asking if you want tokens to be time-based. It will output a QR code that you can scan with your device. It will also save a file to the home directory named.google_authenticator
.Save this file somewhere securely. If you drop this file into another user’s home directory, they will use the same OTP as you. This is great for backing up and restoring as well, or using the same OTP on multiple servers under your control.
Ensure the file has only Read permissions for the owner (
sudo chmod 0600 ${HOME}/.google_authenticator
), otherwise it will fail to read it for security purposes. The standard user should not modify this file manually. If they want a new set of codes, the user will need to re-run thegoogle-authenticator
command to generate a new QR code, recovery codes, etc.Once this is done, the moment of truth… Restart the SSH service, and attempt to log in with your second console!
sudo systemctl restart ssh.service
Ideally, it should ask you to log in with your password, then ask for a verification code (whether the password was right or wrong). If you are successful, it should log you in. If not, use your still-open SSH session to fix it.
Recovery Codes
Running the google-authenticator
command successfully will also output your Emergency scratch codes
, which are useful if you lose access to your mobile device. You can only use these codes once. You’ll notice they are 8 digits long, instead of the standard 6. Keep this safe and not on your phone. There is no sense having your backup on your primary use device.
If you ever need to view the recovery codes (i.e. your piece of paper was ripped to shreds and thrown in a fire), you can cat ${HOME}/.google_authenticator
to view them. You’ll also see the Secret Key as the first line of the file. Using this Secret Key, you can add another authenticator to use the same code by manually typing this in (for example, sharing an account with a friend for some weird, unknown reason).