Extended Brain Storage

OpenBSD: OpenSSH with Two-Factor Authentication

Posted on June 15, 2019

The OpenSSH daemon is targeted by brute-force attacks almost everyday. There are various ways to deal with the annoying attempts of unauthorised access, such as using certificates, one of which is multi-factor authentication. Here are some thoughts to set this up in the realm of OpenBSD


Having a very complex password or long passphrase may seem to be an adequate solution to minimise the risk that a few random password guesses will be successful. Hands-on experience shows that a better solution is to replace passwords with certificates. And even better solution is to combine multiple pieces of evidence (factors), also known as multi-factor authentication (MFA).


The following how-to considers that users can successfully log in using certificates.

On the server side, the SSH daemon’s configuration file (sshd_config) needs to be updated in order to accept user’s password additionally to the already configured publickey method:

$ echo "AuthenticationMethods publickey,password" >> /etc/ssh/sshd_config

And the server restarted:

$ rcctl restart sshd

OATH OTP Provider

As root, installation of login_oath and libqrencode to generate QR codes:

$ pkg_add login_oath
quirks-3.124 signed on 2019-04-15T12:10:16Z
login_oath-0.8p4:openpam-20141014: ok
login_oath-0.8p4:oath-toolkit-2.6.2p0: ok
login_oath-0.8p4: ok
New and changed readme(s):
$ pkg_add libqrencode
quirks-3.124 signed on 2019-04-15T12:10:16Z
libqrencode-4.0.2: ok

As unprivileged user:

$ openssl rand -hex 20 > ~/.totp-key # generate the seed (in hexadecimal format)
$ chmod 400 ~/.totp-key

Alternatively (not used in the following example), a more secure variant using sha512:

$ head -50 /dev/urandom | sha512 > ~/.totp-key # generate the seed (in hexadecimal format)
$ chmod 400 ~/.totp-key

Verification can be perfomed as follows (the -d<NUM> specifies the number of digits in OTP, the default is 6):

$ oathtool -v -d6 --totp `cat ~/.totp-key`
Hex secret: <HEX-SECRET>
Base32 secret: <BASE32-SECRET>
Digits: 6
Window size: 0
Start counter: 0x0 (0)

Generating the QR code image for the previously generated <BASE32-SECRET>:

$ qrencode -d 90 -s 4 -o <USERNAME>@<SERVER-DOMAINNAME>.png 'otpauth://totp/<USERNAME>@<SERVER-DOMAINNAME>?secret=<BASE32-SECRET>&issuer=<SERVER-DOMAINNAME>'

The generated file needs to be delivered to the client device application using e-mail, for instance.

The OATH provider needs to be integrated with the login class capability database. After the following lines that are present in the /etc/login.conf file:

# Default allowed authentication styles for authentication type ftp

it is necessary to add the following lines:

# Default allowed authentication styles for authentication type ssh

and also update the appropriate class for which the TOTP is being set with the following line:


As typically, it is the staff group, the update looks like this:


Finally, the changes need to by applied either by restarting the server or sourcing the appropriate files as follows:

$ [ -f /etc/login.conf.db ] && cap_mkdb /etc/login.conf

Once connected using an SSH client, the SSH certificate as well as the TOTP (code) will be required.

Trusting Keys Signed by a Certificate Authority

Important note: The following lines are for pure reference only. The configuration may (and most probably will not) work anymore. Reader discretion advised.

Considering the Certificate Authority (CA) was set up using the Easy-RSA, the following commands need to be performed in order to create a signed SSH certificate:

$ cd /PATH/TO/Easy-RSA/ROOT/
$ ssh-keygen -s ./ca.domain.tld/private/ca.key -I <USERNAME>@<SERVER-DOMAINNAME> -n <USERNAME> ~/.ssh/id_rsa.pub
Enter passphrase:
Signed user key ~/.ssh/id_rsa-cert.pub: id "<USERNAME>@<SERVER-DOMAINNAME>" serial 0 for <USERNAME> valid forever

If found useful in any way, the SSH Fingerprint ASCII Visualisation can be retrieved later using (this feature has been available since OpenSSH 5.1):

$ ssh-keygen -lv -f ~/.ssh/id_rsa.pub

Verification of the SSH certificate can be performed as follows:

$ ssh-keygen -L -f ~/.ssh/id_rsa-cert.pub
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:<SHA256-HASH>
        Signing CA: RSA SHA256:<SHA256-HASH> (using ssh-rsa)
        Serial: 0
        Valid: forever
        Critical Options: (none)

The local SSH configuration file needs to be updated accordingly:

$ cat << EOF > ~/.ssh/config
    CertificateFile ~/.ssh/id_rsa-cert.pub
    User <USERNAME>
    IdentityFile ~/.ssh/id_rsa

Before the CA’s public key can be transported to the OpenSSH server, it needs to be converted from the X.509 to the PKCS#8 format as follows:

$ cd /PATH/TO/Easy-RSA/ROOT/
$ openssl x509 -in ./ca.domain.tld/ca.crt -noout -pubkey >pubkey.pem
$ ssh-keygen -i -m PKCS8 -f pubkey.pem >ca.domain.tld.pub

On the server side, the following line should be added to the sshd_config file in order to make sure that the server trusts the keys signed by the CA:

$ echo "AuthenticationMethods publickey,password" >> /etc/ssh/sshd_config
$ echo "TrustedUserCAKeys /etc/ssh/ca.domain.tld.pub" >> /etc/ssh/sshd_config

All settings need to be verified now before the OpenSSH daemon is restarted, as the server may become unavailable when something was incorrectly configured!

$ rcctl restart sshd

Before connecting the client to the OpenSSH server,

$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
2048 SHA256:<SERVER-FINGERPRINT> server.domain.tld
$ vi ~/.ssh/known_hosts

Tags: #OpenBSD #security #sshd #OpenSSH #two-factor #authentication #certificates #hardening

⏴ Previous Post Next Post ⏵