An SSH user CA with 2fa/mfa and time limited public keys and optional SSH gateway.
faythe1 consists of three parts:
- An SSH trusted CA with 2fa (via google-authenticator) with that signs users' public keys which were previously uploaded in a secure, trusted manner (using ssh of course). By default, signed keys are only valid for 1 day.
- A set of client scripts to make obtaining signed keys simple and transparent.
- An optional SSH Gateway for sites that wish to ensure that access via SSH to a site can only be made using trusted, signed public keys.
faythe is a set of client and server scripts designed to make using signed SSH keys transparent and straight-forward for the end users. At the client end, it provides (optional) posix shell or powershell functions to override ssh and scp which check whether the signed key is still current and will prompt for a new 2fa signed key if the current key is expired. At the server end, it provides for signing keys with a limited lifetime using the users' password and google-authenticator for 2fa. Additionally, new users can be enrolled via an enrolment token to facilitate uploading their private key. Finally, a separate SSH gateway can be configured to only trust SSH signed keys.
Note that this only works with OpenSSH command line clients and servers - so use of PuTTY, winscp etc isn't directly catered for. Now that Microsoft provide a native OpenSSH client, this works on that platform too without having to resort to WSL - though it works fine with WSL too.
Note however that PuTTY does support OpenSSH CA signed keys (from version 078 beta), if you convert your OpenSSH private key to PuTTY format and configure PuTTY to use your signed key too, so long as your key is signed, it'll work fine. The powershell version of faythe includes the Restore-Faythe command and the shell version restore_fayth - both of which will just grab a new signed key that will then work transparently with suitably configure PuTTY connections.
If you use SSH a lot in your work, you are likely to prefer public keys over passwords, probably used in conjunction with an SSH agent. However, for the server administrator, enabling just public keys for authentication can be problematic as you have to trust that your users are using a secure passphrase against their public key. Using signed SSH public keys can partially solve this issue - you can prompt once per-day (or other suitable interval) and return a signed copy of their SSH public valid for that interval - with the ability to encode additional principals in the certificate for delegated access. If the signing process involves 2fa, you can further enhance your security as you now have a greater degree of trust in the initial authenticating and signing and the concerns about how well protected the users' private key are a partially addressed.
The SSH CA server needs the following (assuming debian or Ubuntu)
- Additional packages (libpam-google-authenticator, sudo, bsdutils, uuid, qrencode)
- Modifications to /etc/pam.d/ssh to enable google-authenticator and management of enrolment
- Modifications fo /etc/ssh/sshd_config to match two groups (here called faythe-enrol and faythe-users) and enabling of ChallengeResponseAuthentication.
- An optional file to match group membership to principals
- Modification of /etc/sudoers to allow running ssh-keygen and management of fayth_enrol group.
- Two scripts - one for enroling (enrol) and one for re-issuing (reissue)
The ssh clients need to modify the following files
- ~/.ssh/config
One entry for the ssh gateway, ca and enrolment servers to avoid the gateway servers and one entry for the site/domain where you want to authenticate using the CA signed keys - this can either be of the formorHost sshca.example.org sshgw.example.org sshenrol.example.org ProxyJump none *.example.org User alice IdentityFile ~/.ssh/id_ed25519_example.org ProxyJump [email protected]
The latter has the benefit of working both onsite and offsite and only using the gateway when absolutely required.Match Host !sshca.example.org,!sshgw.example.org,!sshenrol.example.org,*.example.org !exec "ssh-keyscan -T 1 %h >~/.ssh/junk 2>&1" ProxyJump [email protected] *.example.org User alice IdentityFile ~/.ssh/id_ed25519_example.org
- .bashrc or .zshrc (linux/mac)
Add line to source ~/.config/faythe/faythe.sh Recommended aliasing of ssh and scp - $PROFILE (Windows Powershell) Add line to source $env:APPDATA/faythe/faythe.ps1 Recommended aliasing of ssh and scp
- A domains file to list one or more domains where faythe is used
Once installed correctly, clients can just use ssh, scp or sftp as per-usual from the command line and if the signed key needs to be renewed, they will be prompted.
The config file domains is used to determine when to use faythe and when to just call standard ssh/scp programs. An example domains file is
example.org alice ~/.ssh/id_ed25519_example.org
Each line contains (space or tab separated)
- A domain name - faythe will only intercept if the ssh or scp command references a host in this domain. Also, faythe expects that this domain has hosts sshca.example.org for trusted key renewals, sshenrol.example.org for enrolling of new users and sshgw.example.org for the optional gateway.
- The login name to use at example.org
- The public key to use at example.org - it is recommended to use _ed25519 certificates and use the naming convention of id_ed25519_example.org
Comments can be included and start with a # and extend to the end of the line. Multiple domains are supported.
If using the SSH gateway functionality, then the gateway, needs a couple of tweaks in /etc/ssh/sshd_config, a per-site file containing user -> allowed hosts file (referenced from /etc/ssh/sshd_config and an optional external command to further validate SSH certificate principals (e.g. to restrict access to the client IP where the certificate was issued from).
This example shows how the user interaction required.
First connection to a faythe managed domain of the day which causes and automatic redirect to the CA to re-sign the key and then subsequent connecting on to the requested service. Note any informational messages are prefixed with +faythe: and printed to stderr. In these examples, it is assumed the user is alice and you are using a variant of the default ssh config settings.
Then a subsquent connection to the same or different host in the same domain:
In this example, on sshhost1.example.org, alice has added the following to her .ssh/authorized_keys file
cert-authority,principals="alice" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAvoR1MaEiuA/JAkInq+NK1ReeCVBAJFxCN8N3fTZ5An [email protected]
and this host allows authentication by public keys - so the password is not required.
However, it would be better for the site to only allow access through an sshgw which can be configured to only accept signed keys with restrictions on what hosts that user/key can access.
Finally, an example of scp - this too would prompt for password and 2fa if it was the first connection of the day ...
Note that sftp will also work in the same manner.
If you are using something like PuTTY (version 0.78beta or newer) that supports CA signed keys then you need retrieve a new signed key if the existing one has expired. For this, you can use a shortcut function
Restore-Faythe <login>@sshca.<domain>
restore_faythe <login>@sshca.<domain>
Either will prompt for the usual 2fa to update the signed key.
Assuming that you have sent an enrolment token to a user, they can self-enrol their public key by ssh'ing to sshenrol.example.org:
At this point, they can use google-authenticator or similar to add the identity for later use.