NoHostAuthenticationForLocalhost yes
The OpenSSH client and server applications are ubiquitous. Like many a software dev, I’m `ssh’ing all over the place. And you know what? I’ve put off learning the ins and outs of its configuration for far too long. I learned that a little bit of know-how can simplify my day-to-day use of SSH. That’s exactly why I’ve written this post to exemplify the configuration options I’m now using.
The file ~/.ssh/config
contains settings for a user’s SSH client.
System-wide SSH client settings are placed in /etc/ssh/ssh_config
.
Settings here can be defined per-host.
General configuration options include aliases, SSH agent behavior, and jump hosts to name a few.
Different sections of a sample ~/.ssh/config
are discussed in detail below.
Further documentation is available from the ssh_config
manpage.
This article assumes the reader is familiar with the basics of SSH and the syntax of SSH configuration files.
The first option does not reside in a Host
or Match
block because it only refers to one host, localhost
on the current machine.
NoHostAuthenticationForLocalhost yes
Normally, SSH consults the ~/.ssh/known_hosts
when connecting to a host.
The known hosts file stores an identifying key for each host it has connected to previously.
As connections are made to new hosts, keys are registered in the user’s known hosts file.
Each time SSH establishes a connection to a known host, the key is checked, and the connection is aborted if it does not match.
When running multiple SSH servers from a single host, the key will fail to match whenever switching servers.
If you connect to various VMs through localhost
, SSH will throw an error whenever switching between machines.
Setting NoHostAuthenticationForLocalhost
to yes
is a convenient way to workaround by skipping host checking is skipped for localhost
altogether.
This does not skip host checking for the |
The following section contains only one option which applies to vm_host
.
As an example, vm_host
represents a computer dedicated for running multiple virtual machines.
Host vm_host
Hostname vm_host.local
The option, Hostname
, indicates the true hostname of this host which means vm_host
is really just an alias.
The alias vm_host
can be used on the command-line instead of having to type out vm_host.local
.
Next, several configuration options are given for the hosts vm1
and vm2
.
Host vm1
HostKeyAlias vm1.localhost
Host vm2
HostKeyAlias vm2.localhost
Host vm1 vm2
Hostname localhost
Port 9001
ProxyJump vm_host
Starting with the shared configuration options, the Hostname
and Port
options indicate that both hosts are available on the port 9001
at the reserved localhost
address.
Since both vm1
and vm2
use the same hostname and port, they can’t both be available simultaneously.
In this scenario, either virtual machine vm1
or vm2
would be available at any one time.
The ProxyJump
key is used here with one intermediate host, vm_host
, defined previously.
This means that the SSH connection will connect to the localhost
address on vm_host
.
So, instead of executing ssh vm_host
followed by ssh -p 9001 localhost
to access either of the VMs, use just one command either ssh vm1
or ssh vm2
.
The individual host blocks provide a distinct HostKeyAlias
for each host.
This is critical because these virtual machines will have different host keys but share the same hostname localhost
.
When checking the known hosts file, instead of looking for an entry for localhost
, SSH will look for an entry for the value provided to HostKeyAlias
.
The configuration line NoHostAuthenticationForLocalhost yes
from the beginning of the file only works for the localhost
address on the current machine.
In other words, this option has no effect when connecting to localhost
on any other machine, including a jump host.
According to the ssh_config
manpage, HostKeyAlias
should be used for handling multiple servers running on a single host.
The following configuration accommodates the variability of the IP address associated with a given hostname on networks using multicast DNS.
Host *.local
CheckHostIP no
Multicast DNS uses the ".local" top-level domain exclusively for hosts on a network.
Setting CheckHostIP
to no
here allows IP addresses for any ".local" hosts to change.[1]
It might be worth setting this option for all users in the system-wide configuration file /etc/ssh/ssh_config .
|
The last section contains a few defaults for all hosts, which boil down to a few quality-of-life improvements.
Host *
AddKeysToAgent yes
IdentitiesOnly yes
IdentityFile ~/.ssh/id_rsa_catalina-build.pub
PreferredAuthentications publickey,keyboard-interactive,password,gssapi-with-mic,hostbased
ServerAliveInterval 90
ServerAliveCountMax 4
# Specific to macOS
UseKeychain yes
The meanings of these options are described one-by-one below.
AddKeysToAgent
Automatically registers SSH keys with the SSH Agent as they are loaded.
IdentitiesOnly
Limits the identities that will be used to authenticate. Because I use KeePassXC to handle my SSH keys, the SSH Agent may have lots of other keys loaded which can lead to authentication problems.
IdentityFile
Provides the path to an authentication identity. The private key file is often provided for this option, but providing the public key works when storing the private key itself directly within KeePassXC.[2].
PreferredAuthentications
Sets the order of preference for the various authentication methods. Here, public key cryptography is preferred first because I use this most often.
ServerAliveInterval
The amount of time in seconds between sending successive SSH keepalives to the SSH server. Setting this option enables SSH server keepalives, which are helpful for keeping existing SSH connections open. A value of 90 here results in a keepalive being sent every 90 seconds.
ServerAliveCountMax
The number of successive keepalives the SSH server must fail to respond to before terminating the connection.
With a max count of four and a ServerAliveInterval
of 90 seconds, the session will be terminated after six minutes where no response from the SSH server is received.
UseKeychain
On macOS, this allows storing and accessing keys from the user’s Keychain so they are automatically available after logging on.[3]
It is possible to forward the SSH Agent to avoid typing passwords so much.
You can forward the SSH Agent by setting ForwardAgent
to yes
, shown in the following example.
Host server
ForwardAgent yes
Be wary when using agent forwarding. Those with administrative access on the forwarded machine will be able to use the keys from your agent to authenticate as you.[4] |
The SSH server is configured in /etc/ssh/sshd_config
.
I explain my typical server options here.
ClientAliveInterval 90
ClientAliveCountMax 4
ClientAliveInterval
The amount of time in seconds between sending successive SSH keepalives to the SSH client. Setting this option enables SSH client keepalives, which are helpful for keeping existing SSH connections open. A value of 90 here results in a keepalive being sent every 90 seconds.
ClientAliveCountMax
The number of successive keepalives an SSH client must fail to respond to before terminating the connection.
With a max count of four and a ClientAliveInterval
of 90 seconds, the session will be terminated after six minutes where no response from the SSH client is received.
That was a bit of configuration. Assuming I didn’t just cover topics you already knew, you should have a better understanding of SSH and its configuration options. Hopefully you’ll be able to capitalize on this knowledge by simplifying your SSH work flow. If you’re interested in smoothing out even more wrinkles in your SSH use, you might checkout the Mosh project.