Project:Infrastructure/dev.gentoo.org 2-step authentication

From Gentoo Wiki
Jump to: navigation, search
Warning
The 2-step authentication support is currently experimental. It may be subject to future changes, including migrating to a different implementation (and potentially importing your secrets to it), disabling it temporarily in case of serious issues or discontinuing the project entirely.

The SSH server on our developer machine (dev.gentoo.org) now has an experimental support for 2-step authentication[1], in which the usual public key authentication is followed by HOTP/TOTP input (see also: article on Two-factor authentication). The two-step authentication is implemented using sys-auth/google-authenticator PAM module.

Enabling HOTP/TOTP

TOTP with default settings

In order to enable two-step authentication with the default settings, you can use our simple wrapper script:

user $enable-2fa-totp
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?[...]
[QRCode]
Your new secret key is: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Your verification code is 123456
Your emergency scratch codes are:
  12345678
  23456789
  34567890
  45678901
  56789012

Do you want me to update your "/home/[user]/.google_authenticator" file? (y/n)

The above summary includes a QRCode for easy setup (you may need to zoom the terminal out to use it) and the Base32-encoded secret for manual setup. It also includes a verification code which will probably expire before you manage to set it up, and 5 emergency scratch codes that you should write down and keep in a safe place.

After enabling it, please make sure to test it using a parallel session. If you lock yourself out, you can use the emergency codes to login.

The default settings are:

  • TOTP (as specified in RFC6238) with SHA-1 algorithm and X=30 second period
  • window of 3 codes allowed (i.e. the previous one, the current one and the next one), accounting for a clock drift of ±30 seconds
  • code reuse disallowed (i.e. you can't use the same TOTP code to establish two sessions, you need to wait for the next one)
  • rate limiting to 3 attempts over 30 seconds
  • 5 emergency scratch codes

HOTP or TOTP with custom settings

If you'd like to use different settings, run the custom script and follow the on-screen instructions:

user $enable-2fa-custom

There are also some additional options available only via command-line arguments.

Disabling HOTP/TOTP

In order to disable the two-step authentication:

user $disable-2fa

The authentication process

If you do not have HOTP/TOTP enabled, you should be able to log in as usual. Please note that due to protocol limitations some SSH clients may ask you for a password[2] — if that is the case, please type any non-empty string and the authentication should succeed.

If you do have HOTP/TOTP enabled, your SSH client will first authenticate using the public key, then ask you for a verification code (or 'password', depending on the implementation). Type in your current verification code to proceed.

In either case, you will never be asked for your account/LDAP password.

Limitations / future extensions

authorized_keys automated command keys

Enabling HOTP/TOTP will explicitly enforce it for all logins to your account. If you are using command= lines in authorized_keys to allow automated logins from some services, the additional authentication token will be requested from them as well. If you need those commands to work, please don't use enable it yet. We are planning to provide additional support for this use case later on.

SHA2 hashes

sys-auth/google-authenticator does not support non-SHA1 hashes even though they are permitted by the TOTP standard and supported by some clients. Upstream seems to be willing to accept a patch for that. For more information, see https://github.com/google/google-authenticator-libpam/issues/11.

U2F

U2F would require direct support both on server and client-side of OpenSSH. However, it seems that nobody is currently working on this, and the available patches have serious flaws. For more details, see https://bugzilla.mindrot.org/show_bug.cgi?id=2319; in particular the following comment: https://bugzilla.mindrot.org/show_bug.cgi?id=2319#c21

Server implementation

Installed packages

The following packages are installed to implement the service:

OpenSSH setup

The following configuration is used to enable 2-step authentication:

FILE /etc/ssh/sshd_config2-step verification setup
PasswordAuthentication yes
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,password publickey,keyboard-interactive

The first two are needed to enable the password and keyboard-interactive methods respectively. The third sets it appropriately for 2-step verification.

AuthenticationMethods is a list of space-separated alternatives where each alternative specifies comma-separated list of required steps. This setting means that the user needs to do either:

  • publickey followed by password
  • or publickey followed by keyboard-interactive.

Note that this setting alone would require the user to both use his SSH key and his account password.

PAM setup

Once SSH is explicitly set to require publickey authentication, PAM settings can be altered. For Gentoo purposes, we created a separate pam.d file for this setup.

FILE /etc/pam.d/google-authPAM setup for google-authenticator
auth       required	pam_google_authenticator.so no_increment_hotp nullok
auth       required	pam_permit.so

The explicit pam_permit module is necessary to allow users without OTP set up. If that is the case, pam_google_authenticator considers itself ignored and PAM needs another module to succeed to consider the authentication successful.

To trace the specific logic:

  • if user has OTP set up, pam_google_authenticator asks him for the code:
    • if the code is correct, pam_google_authenticator succeeds and pam_permit succeeds → login succeeds
    • if the code is incorrect, pam_google_authenticator fails → login fails
  • if user does not have OTP set up, nullok makes pam_google_authenticator return ignore status
    • however, pam_permit succeeds → login succeeds

Footnotes

  1. Terminology note: we don't consider this two-factor authentication because both SSH key and OTP token device is something you have, i.e. the same factor. Nevertheless, if you keep both elements separately (e.g. the SSH key connected to your computer, and OTP app on your phone), there's a security gain in this.
  2. Clients implementing keyboard-interactive authentication will not ask for a password since PAM does not request one. However, clients implementing password authentication will do since protocol does not provide for querying whether one is necessary (or providing a custom prompt). While this might be confusing, we've decided it's better to allow for it in case some clients did not implement or use keyboard-interactive for some reason.