We hope you find this tutorial helpful. In addition to guides like this one, we provide simple cloud infrastructure for developers. Learn more →

How to Authenticate Users to a SSH Server Using Monkeysphere on an Ubuntu VPS

Posted Mar 24, 2014 7.7k views Security Ubuntu


Administering large numbers of SSH keys and servers can be very difficult as your organization grows. Correctly identifying valid keys and removing invalid keys throughout an organization can be fraught with errors and have huge consequences on your server security.

In addition, when there are server changes, sometimes your users will receive warnings about being unable to establish the authenticity of your server. Most users will not double-check the key fingerprint of the server before connecting, allowing someone to potentially spoof the server and execute a man-in-the-middle attack.

A project called monkeysphere was created to address these issues. It does this by leveraging GPG keys and the web of trust model to both validate a server's credentials, and provide easy user management.

In a previous guide, we discussed how to setup monkeysphere to validate servers to users. We will continue where we left off in this guide, where we will learn how to authenticate users to our servers automatically, based only on their GPG keys and our server administrator's trust in these users. This will allow us to create authentication files that use plain English instead of mostly cryptographic information.

This guide will assume that you have the setup that we left off with in the previous guide (server.example.com, admin.example.com, client.example.com with the necessary trust relationships established). Let's get started.

Create an Identity Certifier on the SSH Server

The first step towards allowing our SSH server to automatically authenticate our users to the server is to establish an identify certifier. An identity certifier is simply a person we are designating as trusted in establishing the identity of users.

In most cases, the simple and logical choice is to have the server administrator identify users who should be able to log in. We are going to go this route. You can also create more than one identity certifier if your situation requires a distribution of that responsibility.

Let's begin by getting the fingerprint of our administrative user again. On our admin's computer, we can use the same GPG command we used in the last guide to get the full fingerprint:

gpg --with-colons --fingerprint admin@fakedomain.com

Again, we are looking for the line of output that looks like:


The section highlighted in red is what we need here.

On the SSH server (server.example.com), we are going to add this key as an identity certifier. You can do this by typing:

monkeysphere-authentication add-identity-certifier A61256B85307B7ED9AD8D93E9E06881E49E95F19

Monkeysphere will then pull the matching GPG information from the keyservers and store it in its own keyring. It will mark this key as one that can verify the identity of other users.

Generate Authentication Subkeys for SSH Users

Now that we have established that our server administrator can identify which users are legitimate, we need to do a bit of work on the client side.

Each client must generate a GPG subkey that will be used for the actual authentication. While the public GPG key is used to identify the user, the subkey is used for the actual login procedure.

The monkeysphere command contains a subcommand that will allow you to easily generate an authentication subkey. On your client, type:

monkeysphere gen-subkey

A subkey will be generated and added to your local GPG keyring under your main key.

We need to upload the key change to the keyserver again so that our SSH server can use this subkey to generate internal authentication files for the user in question. The key we need to publish is our main key, which contains the subkey change. To get the key information, type:

gpg --list-keys client@fakedomain.com
pub   2048R/87791BD0 2014-03-14
uid                  client <client@fakedomain.com>
sub   2048R/3294D31D 2014-03-14
sub   2048R/0FECF512 2014-03-14

The highlighted portion is the key ID that we'll use to send to the server. Use this ID to send the key back to the server:

gpg --keyserver pool.sks-keyservers.net --send-key 87791BD0

Now that our subkey is available on the keyservers (it may take a bit of time to propagate), we can configure our SSH server to generate authentication files using this key.

Creating the Authentication Files on the SSH Server

Now we need to create the actual authentication files. Monkeysphere authentication files come in two distinct categories.

The user-level files are the ones that we should interact with to establish authentication policies. These are simple, straight forward, plain English files that simply specify people by name and email (as committed to GPG) who should be allowed to log in. These files are located in a subdirectory in each user's home directory, just like regular SSH authorized_keys files.

These files are then used by Monkeysphere to generate authentication files that SSH can understand using the subkeys associated with each valid user that we created above. Monkeysphere generates authentication files for each user in the /var/lib/monkeysphere/authorized_keys directory.

We will create the directories and files on the SSH server in this section.

Start by going to the home directory of whatever user you want to configure access for. Since we've needed to be signed in with administrative privileges to get this far, let's set up access for our root user. In the home directory, create a hidden directory called .monkeysphere:

cd /root
mkdir .monkeysphere

Monkeysphere requires certain permissions on the user-level folders and files in order to consider them valid. Specifically, it requires that there are no write permissions for anyone beyond the file or directory owner.

Let's set the directory permissions to match this scheme and then let's move into the directory:

chmod 755 .monkeysphere
cd .monkeysphere

Within this directory, we need to create a file called authorized_user_ids. This is the user-level authentication file. Create it with your text editor:

nano authorized_user_ids

In this file, we simply list the users, by name and email, exactly as they are in GPG. So to see the formatting we need to use, we can type this again on our client machine:

gpg --list-keys client@fakedomain.com
pub   2048R/87791BD0 2014-03-14
uid                  client <client@fakedomain.com>
sub   2048R/3294D31D 2014-03-14
sub   2048R/0FECF512 2014-03-14

So this is all we have to type in this file:

client <client@fakedomain.com>

If we want to add additional people, we just add them one per line:

client <client@fakedomain.com>
admin <admin@fakedomain.com>

This is much easier to read and manage than large authorized_keys files. Those files tend to get out-of-date and it is difficult to tell if an older key is still valid or not. With this method, it is easy to be able to ask yourself "should Bob have access to this machine?" If not, simply remove his name.

Save and close the file when you are finished.

Now, we need to remember to take away write permissions from anyone not the owner:

chmod 644 authorized_user_ids

Repeat this procedure for any user you wish to configure remote access for.

Generating Internal Authentication Files

Now that we have our user-level authentication files in place, we can generate our internal authentication files easily.

All we have to do is issue this command:

monkeysphere-authentication update-users

You should run this command after making any changes to the user-level authentication files.

If you only want to update a specific user, you can add their name as an argument:

monkeysphere-authentication update-users root

Let's see what files were generated by this procedure. We need to go to the directory where these are stored:

cd /var/lib/monkeysphere/authorized_keys

Inside, you should see a file for each user on the system that you configured access for. The one small caveat to this is that each user in the user-level authentication file needs to have an associated subkey available on the public GPG keyserver network.


demouser  root

If we look at the files, we will see a key that looks like:

MonkeySphere2014-03-22T13:14:31 client <client@fakedomain.com>

As you can see, this is basically a normal authorized_keys entry. We have abstracted this away though for easier user management and the ability for users to dynamically update their keys through GPG.

You may also see additional lines in this file that are not related to any entry you made in in the authorized_user_ids file. This is because, by default, monkeysphere appends any entries it finds in existing authorized_keys files to the end of the generated file. This is to help you in transitioning between the two systems and for users who are unable, for whatever reason, to switch.

Now that we've generated these new authorization files, we need to update the SSH daemon's configuration to look at these files instead of the files within each user's directory.

Open the config file with your editor (make sure you are selecting sshd_config, not ssh_config):

nano /etc/ssh/sshd_config

Within this file, find and modify the AuthorizedKeysFile parameter, or create it if it does not exist. Set the value to this:

AuthorizedKeysFile /var/lib/monkeysphere/authorized_keys/%u

Save and close the file when you are finished.

Now, we just need to restart the SSH daemon for the change to take place:

service ssh restart

Configure Client to Send GPG Key for Authentication

Now, our server is completely configured to accept the GPG subkey that we created for authentication.

We need to configure our client to connect using this information instead of the usual password or RSA keys. Monkeysphere does this through the use of the ssh-agent utility, which is used to store authentication details for SSH connections for extended periods of time.

We can try it out without starting the agent itself by using a one-off command like this:

ssh-agent sh -c 'monkeysphere subkey-to-ssh-agent && ssh server.example.com'

This will work, and after you have entered your password for the GPG key, you should be able to connect to the server without entering any password for the server's account.

However, it's probably worthwhile to start an agent session. You can do that in your current shell by typing:

eval $(ssh-agent)

To start this automatically every time we login, we can add it to the client's ~/.bash_profile file:

echo 'eval $(ssh-agent)' >> ~/.bash_profile

Either way, we then need to add our GPG subkey to the SSH agent so that it can use it for authentication. Do this by typing:

monkeysphere subkey-to-ssh-agent

You will have to type in your GPG key password, but this will only be required once per session.

We can see that it has been accepted by typing:

ssh-add -l

2048 2a:1a:1d:52:32:e5:f4:45:b2:a3:ff:d0:c0:6e:69:f6 client <client@fakedomain.com> (RSA)

We can now login without being prompted for anything to any account that we have access to using our GPG subkey:

ssh server.example.com


After getting Monkeysphere set up on your infrastructure, you'll have a sustainable way of managing server and human interactions for your organization. This method can handle server administrators joining and leaving the organization because all user-level authentication is in plain English. Additionally, you will not have to worry about an attacker trying to spoof access to your servers.

By Justin Ellingwood
Creative Commons License