-
Notifications
You must be signed in to change notification settings - Fork 3
Using Authy or Google Authenticator for 2FA with XRDP
This page details how to use the Authy mobile phone app to provide a second factor when logging in to a Linux-based XRDP system.
Although this guide uses Authy, it should be equally applicable to any other app which supports TOTP password generation (e.g. Google Authenticator).
This guide is applicable to all v0.9.x XRDP versions. At the time-of-writing the current version of XRDP is v0.9.13.1. These versions of XRDP are not natively 2FA-aware. However it is possible to use feature of the Linux 'PAM stack' to work around this. This is explained further below.
The reader should be aware of what two-factor authentication (2FA) is, and why it is becoming increasingly important.
An effort has been made to explain other concepts along the way. This may make the document somewhat wordy for more technically advanced readers, but the aim here is to reach as wide an audience as possible.
CentOS 8.2.2004 is used as an example, but the method should be readily adaptable to other distros.
The author has only tested with guide with local users. However, there is no reason why it should not work in enterprise environments, with domain users provided via SSSD or otherwise. In these environments be aware that NFS home directories introduce significant technical challenges. These are not further considered here.
This guide focuses exclusively on XRDP. However, supporting other login methods such as SSH using the same technique and the same secret key is relatively simple once you understand the concepts in this guide.
An OTP or 'one-time password' is a password which is only valid for a single use.
This is an algorithm which allows a time-based one-time password to be used for authentication.
'Time-based' means the OTP is only valid for a few tens of seconds.
In order for this code to be generated and accepted, the authenticator and the authenticatee must share two data items:-
- A secret key
- The current time
TOTP is described further in RFC6238 or on Wikipedia.
PAM is the software stack which sits under most Linux applications, and is responsible for providing authentication services. PAM is extensively described elsewhere, including Wikipedia.
If you are not familiar with it, a good place to start is A.P Lawrence's understanding PAM page.
This software consists of the following items:-
- A program
google-authenticator
which allows a user to set up a shared secret which is stored both in Authy, and within the user's home directory in~/.google-authenticator
. - A PAM module
pam_google_authenticator.so
which processes the OTP generated by Authy using the secret in~/.google-authenticator
.
More details on this software can be found in the module README.md, the latest version of which is here.
For CentOS 8 users, version 1.07 of this software is packaged in the EPEL google-authenticator
RPM.
pam_google_authenticator.so
has an important feature which we make use of here; when the module is configured with the forward_pass
option, it will consider the password string entered by the user to be the user's normal password with the OTP appended to it.
The OTP is removed from the password string and processed by pam_google_authenticator.so
. The remainder of the string (i.e. the normal password) is 'stacked' for other PAM modules to perform password checking.
Importantly, other PAM modules which support the use_first_pass
option will need to be configured with this so that they pick up the stacked password and do not attempt to prompt the user for the password. The following modules will need this option, if you are using them:-
- pam_sss
- pam_unix
- pam_userdb
This diagram shows the main dataflows involved in the authentication process.
The user logging in is a local user with a password stored in /etc/shadow
.
- Check the target systems are configured normally.
- Have each user log in and set up their TOTP secret key.
- Edit
/etc/pam.d/xrdp-sesman
to implement support for the Google authenticator PAM module as follows:-- Add the
pam_google_authenticator.so
module to theauth
section, configured withforward_pass
. - Add the
use_first_pass
option to other PAM auth modules which process the user's password
- Add the
- Test user logins using their standard password with Authy-generated codes appended.
The documentation for Google Authenticator suggests that it is possible to set up the PAM module to ignore users who haven't configured their secret key yet with the nullok
option. This would make it trivial for the system administrator to set up PAM to allow both 2FA and password-only users on the same system.
Sadly, the nullok
option doesn't play well with the forward_pass
option at the time of writing. If the user has no secret key configured, nullok
allows the PAM authentication sequence to continue, but in this case it will not honour the forward_pass
option.
In other words, it is not simple to configure only a subset of users to log in with 2FA over XRDP. It is possible using group memberships and PAM but this is outside the scope of this article.
zzz - stuff about simnglw config file
The reader is assumed to have a fresh copy of CentOS 8 available with the following features:-
- The GNOME desktop is installed
- The
epel-release
RPM has been installed - The
xrdp
andxrdp-selinux
RPMs are installed from EPEL. - The system is provisioned with time via chrony or NTP so that time-based authentication can be used.
- Home directories are unencrypted and writeable.
-
authselect
has been used already, if appropriate. - Users are using the GNOME keyring, and
/etc/pam.d/xrdp-sesman
is configured appropriately.
The file /etc/pam.d/xrdp-sesman
will look like this for a system which supports GNOME keyring:-
#%PAM-1.0
# Generic Fedora config
#auth include password-auth
#account include password-auth
#password include password-auth
#session include password-auth
# Gnome specific Fedora config
auth include gdm-password
account include gdm-password
password include gdm-password
session include gdm-password
As shipped the password-auth
stanzas are enabled. to get GNOME keyring working, these need to be commented out and the gdm-password
stanzas enabled.
gdm-password
is a file which ships with the gdm
RPM. Its function is to ensure the pam_gnome_keyring.so
modules gets called as required, and that the password-auth
file is also included appropriately.
password-auth
is called by many other PAM files. It performs generic password-based authentication. CentOS 8 provides this file as a soft-link to another file generated by the authselect
utility:-
Install the necessary software:-
sudo dnf install google-authenticator qrencode-libs
The qrencode-libs
package allows QR codes to be displayed during the user configuration process which normally makes things easier. If you don't want to configure Authy using QR codes, this can be omitted.
## Configuring users
To set up their secret keys, each user now needs access to their Authy app, and a command-line login.
## 2FA CentOS 8 PAM stack for xrdp-sesman
As previously described, we need make the following changes to the `auth` module type:-
- Include `pam_google_authenticator.so`
- Add `use_first_pass` to modules which normally might input a password.
The first of these is straightforward. The second is however not so straightforward, as the affected modules are stored within the `password-auth` file which is shared with other files.
The approach we take here is:-
- Copy the `password-auth` file (or rather the file it links to) to a new PAM file called `password-auth-ga`. Within this file we add `use_first_pass` as appropriate.
- Copy `gdm-password` to `gdm-password-ga`. Within this file change `auth `references to `password-auth` to `password-auth-ga`. Also add the necessary call to `pam_google_authenticator.so`
This only needs to be done for the `auth` module type. The `account`, `password` and `session` module types are not affected.
This gives us the following arrangement for the `auth` module type:-
[[images/pamfiles2.png]]
Note that future changes made to the system with `authselect` or `authconfig` may change `password-auth` but will NOT change `password-auth-ga`. You will have to make any necessary changes to this file manually.
## Implementing the PAM changes
```bash
sudo cp /etc/pam.d/gdm-password /etc/pam.d/gdm-password-ga
sudo cp /etc/pam.d/password-auth /etc/pam.d/password-auth-ga
Edit /etc/pam.d/gdm-password-ga
and make the following changes:-
- Add some kind of comment at the top describing what the file is.
- Delete all the module types other than
auth
- Add a call to
pam_google_authenticator.so
as the first item . - Replace the reference to
password-auth
withpassword-auth-ga
. This will give us something like the following:-
# See https://github.com/neutrinolabs/xrdp/wiki/Using-Authy-or-Google-Authenticator-for-2FA-with-XRDP auth required pam_google_authenticator.so forward_pass auth [success=done ignore=ignore default=bad] pam_selinux_permit.so auth substack password-auth-ga auth optional pam_gnome_keyring.so auth include postlogin
Edit /etc/pam.d/password-auth-ga
and make the following changes:-
- Replace the 'do not edit' comment with something else which makes sense to you
- Delete all the module types other than
auth
- Add
use_first_pass
to the modules which might otherwise prompt for a password (likely justpam_unix.so
andpam_sss.so
). Occurrences oftry_first_pass
orforward_pass
can be deleted. This will give us something like the following:-
# See https://github.com/neutrinolabs/xrdp/wiki/Using-Authy-or-Google-Authenticator-for-2FA-with-XRDP auth required pam_env.so auth required pam_faildelay.so delay=2000000 auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet auth [default=1 ignore=ignore success=ok] pam_localuser.so auth sufficient pam_unix.so nulloktry_first_passuse_first_pass auth requisite pam_succeed_if.so uid >= 1000 quiet_success auth sufficient pam_sss.soforward_passuse_first_pass auth required pam_deny.so
Finally, edit /etc/pam.d/xrdp-sesman
. Replace the single auth
reference to gdm-password
with gdm-password-ga
. This will give us something like the following:-
%PAM-1.0 # Generic Fedora config #auth include password-auth #account include password-auth #password include password-auth #session include password-auth # Gnome specific Fedora config (auth stanza with GA) auth include gdm-password-ga account include gdm-password password include gdm-password session include gdm-password
Changes to the PAM stack are effective immediately. You do not need to restart the system or xrdp-sesman
.
Users should now be able to log in over XRDP by entering their passwords immediately followed by Authy OTP codes in the XRDP login-screen password field.
To revert to the old PAM stack, we simply need to revert the one-line change to /etc/pam.d/xrdp-sesman