OpenSSH/Cookbook/Host-based Authentication

Host-based authentication allows hosts to authenticate on behalf of all or some of that particular host's users. Those accounts can be all of the accounts on a system or a subset designated by the Match directive. This type of authentication can be useful for managing computing clusters and other fairly homogeneous pools of machines.

In all, three files on the server must be prepared for host-based authentication. On the client only two must be modified, but the host itself must have SSH host keys assigned. What follows sets up host-based authentication from one system to another in a single direction. For authentication both directions, follow the procedure twice but reverse the roles of the systems.

Client-side Configurations for Host-based Authentication
On the client or source host, two files must be configured and in addition at least one host key must exist:
 * /etc/ssh/ssh_known_hosts - global file for public keys for known hosts
 * /etc/ssh/ssh_config     - allow clients to request host-based authentication

Then the client's host keys must be created if they do not already exist:
 * /etc/ssh/ssh_host_ecdsa_key
 * /etc/ssh/ssh_host_ed25519_key
 * /etc/ssh/ssh_host_rsa_key

These three steps need to be done on each of the client systems which will be connecting to the specified host. Once set up, the accounts logged on one system will be able to connect to another system without further interactive authentication.

Note that in situations environments host-based authentication might not be considered sufficient to prevent unauthorized access since it goes on a host-by-host basis, mostly.

1. Populate the Client with the Server's Public Keys
The remote server's public host keys must be stored on the client system in the global client configuration file /etc/ssh/ssh_known_hosts. One way to get the public keys from the server is to fetch them using ssh-keyscan(1) and save them.

Be sure to make a backup copy of /etc/ssh/ssh_known_hosts, if it exists, before trying anything. Another way would be to add the server's public host key to the ~/.ssh/known_hosts files in the relevant accounts. But that way is more work.

However they are acquired and verified, the public keys listed there must obviously correspond to the private host keys on the server. Any or all of the three types can be used, RSA, ECDSA, or Ed25519. DSA should no longer be used. For verification of the public keys, refer to the section on how to verify a host key by fingerprint for some relevant methods.

2. System-wide Client Configuration
Two changes must be made. First, the client's configuration must request host-based authentication when connecting to the designated systems. Second, the client configuration file must be set to enable ssh-keysign(8). It is a helper application to access the local host keys and generate the digital signature required for host-based authentication. Both changes can be done globally in /etc/ssh/ssh_config.

Here is an excerpt from /etc/ssh/ssh_config on the client trying host-based authentication to all machines. The Host directive in ssh_config(5) can be used to further constrain access to a particular server or group of servers.

In some distributions, such as Red Hat Enterprise Linux 8, the EnableSSHKeysign directive may need to be placed into the general section before it will work. In that case, do this:

Other configuration directives can be added as needed. For example, here are two additional settings applied to the same pool:

If the home directory of the client host is one that is shared with other machines, say using NFS or AFS, then it may be useful to look at the NoHostAuthenticationForLocalhost directive, too.

As a bit of trivia, the program ssh-keysign(8) itself must be SUID root. But SUID was probably set when it was installed and no changes there are needed.

3. Set Up the Client System's Own Host Keys
The program ssh-keysign(8) needs to read the client system's private host keys in /etc/ssh/. Installing the OpenSSH server will create these keys but if the OpenSSH server has not been installed on the client system, it does not need to be. It is enough to have the keys by themselves. If the client system's private host keys do not exist, it will be necessary to add them manually using ssh-keygen(1) before host-based authentication will work.

The default path is /etc/ssh/ when using the -A option.

Note that although the client's system does not have to have an SSH server actually running in order to use host-based authentication to reach another system, it is entirely feasible to install but then disable or uninstall the SSH server on the client's server as a way to get the host keys in place.

Server-side Configurations for Host-based Authentication
Three files on the server or target host must be modified to enable and allow host-based authentication:
 * /etc/shosts.equiv 	 same syntax as old rhosts.equiv
 * /etc/ssh/ssh_known_hosts 	 holds the host public keys from the clients
 * /etc/ssh/sshd_config 	 turns on host-based authentication

The exact location of shosts.equiv may vary depending on operating system and distro.

1. Registering the Allowed Client Systems with the Server
The shosts.equiv file must contain a list of the client systems which are allowed to attempt host-based authentication. The file can contain host names, IP addresses, or net groups. It is best to keep this file simple and oriented to just the list of hosts, either by name or IP number. It provides only the first cut, anyway. For fine tuning, use sshd_config(5) instead to set or revoke access for specific users and groups.

It is important to note that if you are using the shosts.equiv file, the user name on the client and server system must match. For instance, to connect to bob@server1.example.org, the user name on the client must also be bob. If you need user 'alice' to connect to bob@server1.example.org, you need to specify this in the .shosts file for 'bob', not in the global shosts.equiv file.

This file resides in the directory /etc/ in OpenBSD, which this book uses for the reference system when possible. On other systems the file might be found in the directory /etc/ssh/. Either way, the shosts.equiv file identifies which addresses are allowed to try authenticating. Check the manual page for sshd(1) on the actual system being used to be sure of the correct location.

Hunt for a manual page hosts.equiv(5) for more details on .shosts.equiv (and .shosts.), but consider that its use is long since deprecated and most systems won't even have that manual page.

Leftovers from the Old Days
Two legacy files may be on really old systems. and are optionally modified if they are referred to from within shosts.equiv. Each line in the netgroup file consists of a net group name followed by a list of the members of the net group, specifically host, user, and domain.


 * /etc/netgroup - default netgroup list
 * /etc/netgroup.db - netgroup database, build from netgroup

However, these are mostly legacy from the old rhosts and should be avoided.

Another leftover is using .shosts in each account's home directory. That would be a local equivalent to .shosts.equiv. In that way, individual users can have a local .shosts containing a list of trusted remote machines, or user-machine pairs, which are allowed to try host-based authentication.

.shosts must not writable by any group or any other users. Permissions set to 0644 should do it. The usage and format of .shosts is exactly the same as .rhosts, but allows host-based authentication without permitting login by insecure, legacy tools rlogin and rsh. The list is one line per host. The first column is obligatory and contains the name or address of the host permitted to attempt host-based authentication.

However a global .shosts.equiv is preferable to having .shosts in each and every home directory.

2. Populate the Server with the Client's Public Keys
The client systems listed in the server's shosts.equiv must also have their public keys in /etc/ssh/ssh_known_hosts on the server in order to be acknowledged. There are three required data fields per line. First is the host name or IP address or comma separated list of them, corresponding to those from shosts.equiv. Next is the key type, either ssh-rsa for RSA keys or ssh-ed25519 for Ed25519 keys or ecdsa-sha2-nistp256 for ECDSA keys. The third field is the public key itself. Last, and optionally, can be a comment about the key.

Just like step one for the client, there are many ways of collecting the public key information from the client and getting it to the server. It can be copied using sftp(1), copied from ~/.ssh/known_hosts, or grabbed using ssh-keyscan(1). Though the latter two methods only work if the client system also has an SSH server running.

3. System-wide Server Configuration
The third file that must be changed on the server is sshd_config(5). It must be told to allow host-based authentication by setting the HostbasedAuthentication directive, either for all users or just some users or just certain groups.

Host-based authentication can be limited to specific users or groups. Here is an example excerpt from sshd_config(5) allowing allow any user in the group 'cluster2' to let the hosts authenticate on their behalf:

Certain host keys types can be allowed using HostbasedAcceptedAlgorithms, formerly HostbasedAcceptedKeyTypes, with a comma-delimited list of acceptable key algorthms. All the key algorithms which are to be allowed must be listed because those not listed are not allowed. Patterns can be used in the whitelist. Below, Ed25519 and ECDSA keys are allowed, but others, such as RSA and DSA are not.

Host Names and Other DNS Matters
Make complete DNS entries for the clients if possible, including allowing reverse lookups. If the client machine is not listed in DNS, then the server might have trouble recognizing it. In that case you might have to tell sshd(8) not to do reverse lookups in DNS for connecting hosts. This can be a problem on informal LANs where hosts have addresses but no registered host names. Here is an example from /etc/ssh/sshd_config to work around lack of DNS records for the client using the HostbasedUsesNameFromPacketOnly directive.

Don't add this directive unless the normal way fails. Otherwise it can interfere and prevent authentication. Sometimes the host trying to connect gets identified to the target host as something other than what was expected. That too will block authentication. So make sure that the configuration files match what the host actually calls itself.

Debugging
Configuration should be quite straight forward, with small changes in only three files on the server and two on the client to manage. If there are difficulties, be prepared to run sshd(8) standalone at debug level 1 (-d) to 3 (-ddd) and ssh(1) at debug level 3 (-vvv) a few times to see what you missed. The mistakes have to be cleared up in the right order, so take it one step at a time.

If the server produces the message "debug3: auth_rhosts2_raw: no hosts access file exists" turns up, the shosts.equiv file is probably in the wrong place or missing and no fallback ~/.shosts lies in reserve in that account.

If the server cannot find the key for the client despite it being in known_hosts and if the client's host name is not in regular DNS, then it might be necessary to add the directive HostbasedUsesNameFromPacketOnly. This uses the name supplied by the client itself rather than doing a DNS lookup.

Here is a sample excerpt from a successful host-based authentication for user 'fred' from the host at 192.0.2.102, also known as desktop1, using an Ed25519 key. The server first tries looking for an ECDSA key and does not find it.

Note any warnings or error messages and read them carefully. If there is too much output, remember the -e option for the server and use it to save the debugging output to a separate file and then read that file afterwards.

Since this method relies on the client as well as the server, running the client with increased verbosity can sometimes help too.

If there is too much output from the client to handle, remember the -E option and redirect the debug logs to a file and then read that file at leisure.