Two factor authentication with TOTP/HOTP¶
For the best two factor authentication (2FA) security, we recommend using hardware authentication devices that support U2F/FIDO. See the guide on two factor authentication with U2F/FIDO for details. However, if this is not possible or is impractical to implement in your case, TOTP/HOTP based 2FA is an improvement over no two factor at all. Smartphone apps to support this type of 2FA are common, such as Google Authenticator.
Background¶
The configuration presented here makes public key authentication the first factor, the TOTP/HOTP code the second factor, and makes password authentication unavailable. Apart from the usual setup steps required for public key authentication, all configuration and setup takes place on the server. No changes are required at the client end; the 2FA prompt appears in place of the password prompt.
The two supported methods are HMAC-based One Time Password (HOTP) and Time-based One Time Password (TOTP). Generally, TOTP is preferable if the 2FA device supports it.
HOTP is based on a sequence predictable only to those who share a secret. The user must take an action to cause the client to generate the next code in the sequence, and this response is sent to the server. The server also generates the next code, and if it matches the one supplied by the user, then the user has proven to the server that they share the secret. A downside of this approach is that if the user generates codes without the server following along, such as in the case of a typo, then the sequence generators can fall “out of sync”. Servers compensate by allowing a gap in the sequence and considering a few subsequent codes to also be valid; if this mechanism is used, then the server “skips ahead” to sync back up. But to remain secure, this can only go so far before the server must refuse. When HOTP falls out of sync like this, it must be reset using some out-of-band method, such as authenticating using a second backup key in order to reset the secret for the first one.
TOTP avoids this downside of HOTP by using the current timezone-independent date and time to determine the appropriate position in the sequence. However, this results in additional requirements and a different failure mode. Both devices must have the ability to tell the time, which is not practical for a USB 2FA token with no battery, for example. And both the server and client must agree on the correct time. If their clocks are skewed, then they will disagree on their current position in the sequence. Servers compensate for clock skew by allowing a few codes either side to also be valid. But like HOTP, they can only go so far before the server must refuse. One advantage of TOTP over HOTP is that correcting for this condition involves ensuring the clocks are correct at both ends; an out-of-band authentication to reset unfortunate users’ secrets is not required. When using a modern smartphone app, for example, the requirement to keep the clock correct isn’t usually a problem since this is typically done automatically at both ends by default.
Note: It is not recommended to configure U2F/FIDO at the same time as TOTP/HOTP. This combination has not been tested, and using the configuration presented here, TOTP/HOTP would become mandatory for everyone, whether or not they are also using U2F/FIDO.
Install required software¶
From a terminal prompt, install the google-authenticator
PAM module:
sudo apt update
sudo apt install libpam-google-authenticator
Note: The
libpam-google-authenticator
package is in Ubuntu’s universe archive component, which receives best-effort community support only.
Configure users¶
Since public key authentication with TOTP/HOTP 2FA is about to be configured to be mandatory for all users, each user who wishes to continue using SSH must first set up public key authentication and then configure their 2FA keys by running the user setup tool. If this isn’t done first, users will not be able to do it later over SSH, since at that point they won’t have public key authentication and/or 2FA configured to authenticate with.
Configure users’ key-based authentication¶
To set up key-based authentication, see “SSH Keys” above. Once this is done, it can be tested independently of subsequent 2FA configuration. At this stage, user authentication should work with keys only, requiring the supply of the private key passphrase only if it was configured. If configured correctly, the user should not be prompted for their password.
Configure users’ TOTP/HOTP 2FA secrets¶
Each user needs to run the setup tool to configure 2FA. This will ask some questions, generate a key, and display a QR code for the user to import the secret into their smartphone app, such as the Google Authenticator app on Android. The tool creates the file ~/.google-authenticator
, which contains a shared secret, emergency passcodes and per-user configuration.
As a user who needs 2FA configured, from a terminal prompt run the following command:
google-authenticator
Follow the prompts, scanning the QR code into your 2FA app as directed.
It’s important to plan for the eventuality that the 2FA device gets lost or damaged. Will this lock the user out of their account? In mitigation, it’s worthwhile for each user to consider doing one or more of the following:
Use the 2FA device’s backup or cloud sync facility if it has one.
Write down the backup codes printed by the setup tool.
Take a photo of the QR code.
(TOTP only) Scan the QR code on multiple 2FA devices. This only works for TOTP, since multiple HOTP 2FA devices will not be able to stay in sync.
Ensure that the user has a different authentication path to be able to rerun the setup tool if required.
Of course, any of these backup steps also negate any benefit of 2FA should someone else get access to the backup, so the steps taken to protect any backup should be considered carefully.
Configure the SSH server¶
Once all users are configured, configure sshd
itself by editing /etc/ssh/sshd_config
. Depending on your installation, some of these settings may be configured already, but not necessarily with the values required for this configuration. Check for and adjust existing occurrences of these configuration directives, or add new ones, as required:
KbdInteractiveAuthentication yes
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive
Note: On Ubuntu 20.04 “Focal Fossa” and earlier, use
ChallengeResponseAuthentication yes
instead ofKbdInteractiveAUthentication yes
.
Restart the ssh
service to pick up configuration changes:
sudo systemctl try-reload-or-restart ssh
Edit /etc/pam.d/sshd
and replace the line:
@include common-auth
with:
auth required pam_google_authenticator.so
Changes to PAM configuration have immediate effect, and no separate reloading command is required.
Log in using 2FA¶
Now when you log in using SSH, in addition to the normal public key authentication, you will be prompted for your TOTP or HOTP code:
$ ssh jammy.server
Enter passphrase for key 'id_rsa':
([email protected]) Verification code:
Welcome to Ubuntu Jammy Jellyfish...
(...)
[email protected]:~$
Special cases¶
On Ubuntu, the following settings are default in /etc/ssh/sshd_config
, but if you have overridden them, note that they are required for this configuration to work correctly and must be restored as follows:
UsePAM yes
PubkeyAuthentication yes
Remember to run sudo systemctl try-reload-or-restart ssh
for any changes made to sshd
configuration to take effect.