My name is Philipp C. Heckel and I write about nerdy things.

OpenSSH ‘AuthorizedKeysCommand’ with ‘fingerprint’ argument (Patch for OpenSSH 6.6p1)


Linux, Programming, Security

OpenSSH ‘AuthorizedKeysCommand’ with ‘fingerprint’ argument (Patch for OpenSSH 6.6p1)


Many of us developers or system administrators use OpenSSH’s public key authentication (aka password-less login) on a daily basis. The mechanism works based on public key cryptography: By adding a RSA/DSA public key to the authorized_keys file, the user with the matching private key can login without a password. The mechanism works great for a couple of hundred, thousands and even 100k thousand users (tested, login takes ~2sec).

But what if there are more keypairs, say, a million users, or a more flexible approach is desired? Maybe with an LDAP or a database backend? Think of GitHub and how they do their ssh git@github.com ... login! This blog post shows you how to do that by patching OpenSSH’s AuthorizedKeysCommand option to support an additional fingerprint argument.


Content


1. AuthorizedKeysCommand: Not quite a solution (just yet)

At first sight, the AuthorizedKeysCommand option in the /etc/ssh/sshd_config config file is the right choice. Every time someone tries to log in, it executes a command and returns a dynamic authorized_keys file.

Example: If the option is set to AuthorizedKeysCommand /my/command.sh and a user tries to log in as ssh git@myserver.com .., OpenSSH will run /my/command.sh git and parse whatever the command outputs as authorized_keys file.

The command.sh script could query a database or an LDAP backend, so this is definitely dynamic! However, it does not fix the million user problem, because if the user ‘git’ could be logged in to by a million users, the dynamically created authorized_keys file would still need a million entries.

To make an efficient keypair lookup, we need the key fingerprint as an additional argument for the AuthorizedKeysCommand. So instead of doing /my/command.sh git, we want the command to be run like this: /my/command.sh git 64:a1:03:7c:1d:b6:7e:b0:0f:fd:76:7e:f0:ca:4f:20.

Using the user (here: git) and the fingerprint (here: 64:a1:03:7c:1d:b6:7e:b0:0f:fd:76:7e:f0:ca:4f:20), we can query the database or the LDAP and only return one result (instead of a million!).

Imagine something like this:

2.1. Solution 1: Using OpenSSH 6.9

If you are reading this at a point at which OpenSSH 6.9 has been released and is available for you to use, check out the changes in the AuthorizedKeyCommand option. As of today (May 2015), a patch is being reviewed (see bug #2081) that greatly enhances this command, and also may contain the fingerprint as an argument (here: %f).

2.2. Solution 2: Patching OpenSSH

If above mentioned patch has not been merged, we need to patch OpenSSH ourselves (check out the source in this GitHub Gist). That actually sounds harder than it is. If your system is based on Debian/Ubuntu, for instance, you can get the source of the OpenSSH version you are currently using via apt-source, and then rebuild a Debian package after patching the source via dpkg-source and dpkg-buildpackage.

Here’s how that works:

2.2.1. What’s in the patch?

The patch is really simple. As mentioned above, it merely runs the authorized_keys command with an additional ‘fingerprint’ argument — nothing more. Not counting the log output, it’s a 4 line fix.

2.2.2. Testing the patch

First create a dummy authorized_keys script and save it at /usr/local/sbin/ssh_authorized_keys (don’t forget to chmod +x it!) — something like this:

Then edit your /etc/ssh/sshd_config file and add the AuthorizedKeysCommand directive:

Now run your OpenSSH server and connect to it with the matching private key:

To get a more extensive logging, start SSHd like this:

3 Comments

  1. Kat

    Hi!
    Great post – thank you! :)
    Contact me please, I have a proposition for you.
    Bests!


  2. Kevin

    Hi Philipp,

    Thank you for the tutorial.

    I building a git server system same as Github with patch OpenSSH and looking for publish key in a Database.

    So, my customer can connect to the server by:

    ssh git@domain.com:username/repos.git

    Instead:

    ssh -o IdentityFile=user.key user@localhost id

    ??

    Before connect, they added the key to the admin page.

    And how to get a fingerprint key?

    Thanks.


  3. Philipp C. Heckel

    1. I would strongly suggest to use a newer version of OpenSSH, so you don’t have to patch it.
    2. Here’s how you get the fingerprint from the public key: https://stackoverflow.com/questions/9607295/how-do-i-find-my-rsa-key-fingerprint