# Setting up SSH to Manage Connections to Multiple Hosts

## Introduction

There are many machines in my company that I need to work with using ssh. For quite some time, I had been using ssh in the most primitive way, i.e., running ssh <user>@<host> and then entering the password. However, this was very tedious so I decided to find a better way. After some googling, I settle on the following solutions:

• enabling key-based authentication to avoid typing passwords;
• defining host specifications in a configuration file to avoid typing remote user names, host addresses, jump hosts, etc.

The remaining text of this post shows how to implement these solutions.

## Enabling key-based authentication

If you haven’t heard of key-based authentication, here is a short article that exlains what it is.

By default, SSH keys are stored in the ~/.ssh/ directory. Check if there are any existing keys before generating a new one to avoid overwriting:

ls ~/.ssh/

To generate a new pair of keys, use the ssh-keygen command:

ssh-keygen -t rsa -b 2048 -C ""

where -t specifies the type of key to create (defaults to rsa); -b specifies the number of bits in the key to create (defaults to 2048, which is generally sufficient); -C adds a comment to describe the key (defaults to <user>@<host>).

Before actually generating the key pairs, the program will prompt for a passphrase. If you specify a passphrase, then when you use the keys to login to remote machines later, ssh will ask you to type in the same passphrase. This adds an additional layer of security, but is optional.

After generating the key pairs, you may want to rename the keys. However, note that some programs (e.g., ssh-copy-id) might assume a naming convention for the key files where a private key matches id* (e.g., id_rsa), while the corresponding public key matches id*.pub (e.g., id_rsa.pub). For these programs to work properly, you should also follow these conventions.

To have the key-based authenticationt to take effect, you should append the generated public key to the authorized keys list on the remote machine. This can be done with a handy command called ssh-copy-id1:

ssh-copy-id -i ~/.ssh/id_rsa.pub <user>@<host>

where -i specifies the public key to be appended. If the local machine does not provide ssh-copy-id, you can also use:

cat ~/.ssh/id_rsa.pub | ssh <user>@<host> "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

After the above steps, you should be able to login to the remote machine without having to type the password.

## Defining host specifications

By default, ssh reads ~/.ssh/config to obtain configuration data for the current user. The file contains sections separated by Host specifications, and each section defines parameters for hosts that matches the pattern given in the specification. For each parameter, the first obtained value will be used; therefore, more host-specific settings should be given near the beginning of the file, and general defaults at the end.

To see the full list of configurable parameters and their meanings, use man ssh_config. Below is an example of a ~/.ssh/config file:

Host host_1
HostName 111.222.333.444
User user_1

Host host_2
HostName 222.333.444.555
User user_2
# specify jump a host; in case multiple sequential jump hosts are required, separate each one with ,.
ProxyJump [email protected]

Host host_*
IdentityFile "~/.ssh/id_rsa"

Here are a few things to note:

• wildcard expansion is supported by Host specifications;
• quote the argument with " if it contains any whitespaces;
• lines starting with # and empty lines are interpreted as comments;
• only the user should own and have read/write access to the file; this can be ensured by running chown <user> ~/.ssh/config (prefix with sudo when necessary) followed by chmod 600 ~/.ssh/config;
• to eliminate the use of passwords, the public key should be authorized in both the target host and the jump host(s).

After the configuration, you can type the ssh command followed by a host specification (you can use tab to autocomplete the specification) to establish a connection to the target host, e.g.:

ssh host_1

1. If the connection requires a jump host, use the -o option to specify one, i.e., -o "ProxyJump <user>@<host>".