1. Introduction

Since humans are generally better at remembering names rather than IP address numbers, many technologies convert the latter to the former. Further, some even exist for the sole purpose of that conversion. Still, others implement the function for internal use.

In this tutorial, we look at the local SSH protocol implementation of hostname to IP address mapping. First, we do a quick refresh on the classic methods for resolving names. Next, we combine one of them with SSH and discuss the results. Finally, we configure and use the internal SSH client name resolution.

For brevity and security reasons, we only consider the newest iteration of SSH version 2 (SSHv2) implemented by OpenSSH.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4 and OpenSSH 8.4p1. It should work in most POSIX-compliant environments.

2. Name Resolution

Generally, there are two common ways to resolve names to IP addresses in Linux:

  • Domain Name System (DNS): domain name to IP address
  • hosts file: hostname to IP address

Let’s briefly look at both.

2.1. Domain Name System (DNS)

Often, DNS only refers to the global, public servers that provide name resolution via the Internet.

Yet, a DNS server can be global or local. Still, not every system has a global domain name, which is paid for and maintained by a network of servers that broadcast it. While there are dynamic DNS services like NoIP.com, their configuration can be tedious and demanding.

On the other hand, local DNS servers aren’t that common and are limited by their nature. On top of that, using one system to query another about the address of a third can be a convoluted and burdening way to communicate.

These drawbacks of DNS can force alternate solutions.

2.2. Hosts Files and /etc/hosts

Hosts files are the simplest form of name-to-address mapping. In fact, DNS servers can be seen as huge remotely-queried hosts files.

The default hosts file for most Linux distributions is /etc/hosts. Essentially, a hosts file is a list of rows, each containing a name and its corresponding address or addresses, all delimited in some way:

$ cat /etc/hosts
127.0.0.1       localhost

::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Here, we see the standard localhost mappings for IPv4 and IPv6 addresses. Each line has an IP and a hostname, which we can resolve back to it:

$ ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.

In this case, ping resolves localhost to 127.0.0.1.

Importantly, even for mappings to remote addresses, the hosts file only works for the local system. Indeed, this can be inconvenient when switching environments.

In all cases, domain and host names can and often differ between themselves and from other names for the same system, like those provided within certain protocol configurations.

3. SSH Name Resolution

After refreshing our knowledge about the general concepts, let’s see how we can resolve names via SSH. Since DNS is usually the Linux default and also an involved solution, we won’t be talking about it for SSH.

When checking the name resolution, we employ the -v verbose switch of our SSH client. It provides additional information during session setup.

3.1. SSH and /etc/hosts

Of course, simply adding a line to /etc/hosts should work for SSH clients as well:

$ ssh -v baeldung@xost
[...]
ssh: Could not resolve hostname xost: Name or service not known
$ ping xost
ping: xost: Name or service not known
$ echo '192.168.6.66 xost' >> /etc/hosts

The name xost was unidentified, so we added an entry for it to our hosts file. Now, we can repeat our tests:

$ ping xost
PING xost (192.168.6.66) 56(84) bytes of data.
[...]
$ ssh -v baeldung@xost
[...]
debug1: Connecting to xost [192.168.6.66] port 22.
[...]

Here, once added to /etc/hosts, we see that a previously unknown name xost is identified as 192.168.6.66 by both our SSH client and ping.

3.2. ssh_config

As an alternative to classic approaches, we can leverage the ssh_config file to configure name resolution only for SSH.

Although potentially limiting, this method can provide several benefits:

  • even more localized resolution of names
  • set via the SSH protocol configuration
  • internal client names can set multiple SSH parameters of a connection

By using the Hostname statement within a Host block in our SSH client configuration file, we can create a mapping:

Host xost
  Hostname 192.168.6.66

Conveniently, we can use other names that the system recognizes as well (such as a domain name). Moreover, there are TOKENS, which work similarly to the format specifiers of the printf command. They allow us to avoid hardcoding dynamic values.

Let’s test our setup so far:

$ ssh -v xost
[...]
debug1: Connecting to xost [192.168.6.66] port 22.
[...]

Evidently, our settings work for ssh. Now, let’s try the same name with ping:

$ ping xost
ping: xost: Name or service not known
[...]

As expected, other tools are unaffected by the SSH protocol setup.

4. Summary

In this article, we explored the main ways to use name resolution with SSH.

In conclusion, while we have many alternatives, including the classic DNS and hosts files, we can usually achieve the greatest flexibility via the direct configuration of our SSH client alone.