Skip to main content

Arch Linux with U2F

· 8 min read

Linux-u2f.png

This method will work with ANY security keys that support the U2F standard

Prerequisites

  • A Security key supporting the U2F Standard
  • Linux
  • root access to the System you are gonna configure 2FA for

Installation the pam-u2f

Arch Linux

sudo pacman -Sy --needed pam-u2f

Debian/Ubuntu

sudo apt update && sudo apt install libpam-u2f

Source code

github

GitHub Repo stars

GitHub last commit

Configure Security keys

The pam-u2f package provides a handy tool to configure Security Keys for our users called pamu2fcfg

$ pamu2fcfg --help
Usage: pamu2fcfg [OPTION]...
Perform a FIDO2/U2F registration operation and print a configuration line that
can be used with the pam_u2f module.

-h, --help Print help and exit
--version Print version and exit
-o, --origin=STRING Relying party ID to use during registration,
defaults to pam://hostname
-i, --appid=STRING Relying party name to use during registration,
defaults to the value of origin
-t, --type=STRING COSE type to use during registration (ES256, EDDSA,
or RS256), defaults to ES256
-r, --resident Generate a resident (discoverable) credential
-P, --no-user-presence Allow the credential to be used without ensuring the
user's presence
-N, --pin-verification Require PIN verification during authentication
-V, --user-verification Require user verification during authentication
-d, --debug Print debug information
-v, --verbose Print information about chosen origin and appid
-u, --username=STRING The name of the user registering the device,
defaults to the current user name
-n, --nouser Print only registration information (key handle,
public key, and options), useful for appending

Report bugs at <https://github.com/Yubico/pam-u2f/issues>.

Individual Authorization Mapping by User

  1. Create folder:

    mkdir -p ~/.config/Yubico
  2. Make user keys:

    pamu2fcfg > ~/.config/Yubico/u2f_keys

    2.1 Add Additional keys using

    pamu2fcfg >> ~/.config/Yubico/u2f_keys

pamu2fcfg example output:

/home/user/.config/Yubico/u2f_keys
username:1pQTIDIGWLfyRhYjiFpJeSlSxN4fqdY0ucl59VxQdS0qV9QxDgb5HGL1Hd18o1gQ1wr9B3BP60tk4735JrIE7A==,KPMgCkrhND9yMKaImqwgywBVJlIHc8rDUVbMirXCG70X+bzld/a6HWOjaSlzUXinVp3yfofx96wgmSWkGX6poQ==,es256,+presence

Central Authorization Mapping

Create a file e.g. /etc/u2f_mappings. The file must contain a user name, and the information obtained during the registration procedure.

pamu2fcfg -u username1 >> /etc/u2f_mappings

Activate the pam_u2f.so module in PAM

Configure pam-u2f as a required module after your primary authentication module(s) for use as a second factor. Make sure that the primary authentication method is not sufficient or uses other control values that may preempt execution of pam-u2f.

Dealing with SDDM

  1. For correctly work SDDM with U2F, need to change system-login to system-local-login into /etc/pam.d/sddm Failing to do this will result in the KDE lock screen, and terminal access requiring U2F, but the initial login via SDDM bypassing U2F, which defeats the purpose of having two factor authentication.

  2. Add the following line to config file (change username)

    auth required pam_u2f.so authfile=/home/<username>/.config/Yubico/u2f_keys

sddm config before adding U2F:

/etc/pam.d/sddm
#%PAM-1.0

auth include system-login
-auth optional pam_gnome_keyring.so
-auth optional pam_kwallet5.so

account include system-login

password include system-login
-password optional pam_gnome_keyring.so use_authtok

session optional pam_keyinit.so force revoke
session include system-login
-session optional pam_gnome_keyring.so auto_start
-session optional pam_kwallet5.so auto_start

sddm config after adding U2F:

/etc/pam.d/sddm
#%PAM-1.0

auth include system-local-login
-auth optional pam_gnome_keyring.so
-auth optional pam_kwallet5.so
auth required pam_u2f.so authfile=/home/<username>/.config/Yubico/u2f_keys

account include system-login

password include system-login
-password optional pam_gnome_keyring.so use_authtok

session optional pam_keyinit.so force revoke
session include system-login
-session optional pam_gnome_keyring.so auto_start
-session optional pam_kwallet5.so auto_start
tip

Add the same version to the top of /etc/pam.d/kde to protect the KDE Plasma lock screen.

auth required pam_u2f.so authfile=/home/<username>/.config/Yubico/u2f_keys

PAM Configuration (Reference)
PAM Configuration File Syntax

The entries in the configuration file are in the format:

service-name module-type control-flag module-path module-options


service-name - Name of the service, for example, ftp, login, or passwd. An application can use different service names for the services that the application provides. For example, the Solaris secure shell daemon uses these service names: sshd-none, sshd-password, sshd-kbdint, sshd-pubkey, and sshd-hostbased. The service-name other is a predefined name that is used as a wildcard service-name. If a particular service-name is not found in the configuration file, the configuration for other is used.

module-type - The type of service, that is, auth, account, session, or password.

control-flag - Indicates the role of the module in determining the integrated success or failure value for the service. Valid control flags are binding, include, optional, required, requisite, and sufficient. See below how PAM Stacking Works for information on the use of these flags.

module-path - The path to the library object that implements the service. If the pathname is not absolute, the pathname is assumed to be relative to /usr/lib/security/$ISA/. Use the architecture-dependent macro $ISA to cause libpam to look in the directory for the particular architecture of the application.

module-options - Options that are passed to the service modules. A module's man page describes the options that are accepted by that module. Typical module options include nowarn and debug.

How PAM Stacking Works

The control flag indicates the role that a PAM module plays in determining access to the service. The control flags and their effects are:

Binding – Success in meeting a binding module's requirements returns success immediately to the application if no previous required modules have failed. If these conditions are met, then no further execution of modules occurs. Failure causes a required failure to be recorded and the processing of modules to be continued.

Include – Adds lines from a separate PAM configuration file to be used at this point in the PAM stack. This flag does not control success or failure behaviors. When a new file is read, the PAM include stack is incremented. When the stack check in the new file finishes, the include stack value is decremented. When the end of a file is reached and the PAM include stack is 0, then the stack processing ends. The maximum number for the PAM include stack is 32.

Optional – Success in meeting an optional module's requirements is not necessary for using the service. Failure causes an optional failure to be recorded.

Required – Success in meeting a required module's requirements is necessary for using the service. Failure results in an error return after the remaining modules for this service have been executed. Final success for the service is returned only if no binding or required modules have reported failures.

Requisite – Success in meeting a requisite module's requirements is necessary for using the service. Failure results in an immediate error return with no further execution of modules. All requisite modules for a service must return success for the function to be able to return success to the application.

Sufficient – If no previous required failures have occurred, success in a sufficient module returns success to the application immediately with no further execution of modules. Failure causes an optional failure to be recorded.

The following two diagrams shows how access is determined in the integration process. The first diagram indicates how success or failure is recorded for each type of control flag. The second diagram shows how the integrated value is determined.

Effect of Control Flags

img

How Integrated Value Is Determined

img

Passwordless sudo with U2F

You can use U2F key for Passwordless sudo i.e only the U2f key would be needed to run sudo commands

We can achieve this by editing the /etc/pam.d/sudo file

Add the following line to the TOP of the sudo file

auth sufficient pam_u2f.so authfile=/home/<username>/.config/Yubico/u2f_keys cue [cue_prompt=<Prompt we want to show to our users>]

Example:

/etc/pam.d/sudo
#%PAM-1.0
auth sufficient pam_u2f.so authfile=/home/<username>/.config/Yubico/u2f_keys cue [cue_prompt=Please Confirm Your Identity.]
auth include system-auth
account include system-auth
session include system-auth

SSH Credentials

First need to make sure the client has OpenSSH 8.2 or higher installed:

$ ssh -V
OpenSSH_9.1p1, OpenSSL 3.0.7 1 Nov 2022

To generate a new SSH key pair, which can be either ecdsa-sk or ed25519-sk key pair. The -sk extension stands for security key. Please note that the ed25519-sk key pair is only supported by new YubiKeys with firmware 5.2.3 or higher that supports FIDO2. This means that YubiKeys with firmware below 5.2.3 are only compatible with ecdsa-sk key pairs. If possible, generate an ed25519-sk SSH key pair for this reason.

tip

You can check the YubiKey firmware* version with the following command.

lsusb -v 2>/dev/null | grep -A2 Yubico | grep "bcdDevice" | awk '{print $2}'

Or we can use YubiKey Manager

YubiKey Manager AppImage

*Yubico does not allow its firmware to be modified to minimize the physical attack surface.

It is then possible to generate a credential file with:

ssh-keygen -t ed25519-sk -C "$(hostname)-Yubikey"

ssh-keygen

ssh-keys

Add your new public key to the remote host

ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub user@192.168.1.1

Use:

ssh -i ~/.ssh/id_ed25519_sk user@192.168.1.1

Additional information