ssh – No More Memorizing IP Addresses!
Quick – without looking anything up, think of the IP address of a system you regularly ssh to. Got it? Here’s the real question: why do you know that?
I grew up in the days when you had to memorize phone numbers because phones most definitely weren’t smart. (If you did too, you may find this youtube video of kids encountering a rotary phone for the first time fun 🙂 ). In much the same way that we have a contact app on our phones now, why aren’t you using the contact list built into ssh?
I’ll introduce that file here, and cover the basics – the core items that every command-line ssh user should know. This lets you get using the config file with about a minute of setup.
Command-line versions of ssh use the file $HOME/.ssh/config to remember the options needed to connect to our ssh servers. Here’s an example of one stanza of this file that I use to connect to a raspberry pi zero:
Host pi-demo-zero pi-demo-0 pi0 192.168.0.233 User pi Hostname raspberrypi.local. #Hostname 192.168.0.233 Port 22 HostKeyAlias pi-demo-zero
The Host line (the only one that starts at the far left, all settings below it are indented) gives all the easy-to-remember name(s) I might have for this system. I can use any of them in any place I might have used an IP address or hostname in the past:
ssh pi0 scp -p pi-demo-0:/var/log/messages /tmp/ rsync -av -e ssh monitorscript.sh root@192.168.0.233:/usr/local/bin/ sftp pi-demo-zero
By placing “192.168.0.233” in the list of identifiers, I still get all the following settings applied even if I fall back to typing the IP address on the command line or in scripts I wrote earlier.
The User line defines the default user account I use on this remote system. Using “root” here is discouraged, and may even be blocked; it’s better to log in as a normal user and run “sudo” instead if you need to do things as root. That said, there may be times when I choose to log in as root directly, such as in the rsync command above. There I overrode the default user “pi” on the command line and transferred the file using the root account so I could send it directly to a directory owned by root (“/usr/local/bin/”).
In fact, any setting other than the “Host” line itself can be overridden with command-line options. See “man ssh” for the general command-line options, and “man ssh_config” for the more esoteric ones.
The Hostname entry says where to find this system. The field name “Hostname” is unfortunate – it can be any of the following:
- A dns-registered hostname
- A hostname from /etc/hosts on this system
- An IPv4 or IPv6 address
- A hostname advertised by multicast messages (mDNS), such as raspberrypi.local. (This is actually a really nice trick for logging in to a raspberry pi when you don’t know it’s IP address; use “Hostname raspberrypi.local.” in your config block).
When I use any kind of hostname, I’ll commonly add a commented-out line with the raw IP address of the system once I know it, so that I can still reach the box if I ever run into problems with DNS resolution (such as the “#Hostname 192.168.0.233” line above).
The Port line says on what port the ssh server listens. By default that’s 22, so I can definitely leave that off. It’s handy to know if you have ssh listening on another port on a particular system.
Finally, the HostKeyAlias line gives a name to use when remembering this host key. I commonly use the first entry on the Hosts line, but it can be anything. You can see this alias in use by looking at ~/.ssh/known_hosts ; this alias will show up at the left of the host key instead of the ip address(es).
By forcing a name like this I only have to accept the key once and it’ll work no matter which name I use when ssh’ing.
For IPv6 addresses, the concepts are identical. Because we’re connecting to a different destination in the network sense, we need to create an almost identical block:
Host pi-demo-zero-v6 pi-demo-0-v6 pi0-v6 fe80::fd6f:24bd:16a4:46e #wlan0 Hostname fe80::fd6f:24bd:16a4:46e User pi HostKeyAlias pi-demo-zero
In this block, I include a comment that this is the IP address on the wlan0 interface. Keep these on their own lines, as openssh doesn’t like comments at the end of a functional line like the other 4 above.
One really nice timesaver is the (optional) Host * section at the bottom of the file. Under Host * I can place all the settings that apply to most of the servers to which I connect:
Host * User williams Port 22 ConnectTimeout 20
Here I’ve placed my defaults (remote user account name is almost always “williams”, port is almost always 22, and I want ssh to give up trying to connect if it hasn’t succeeded in 20 seconds). That means I no longer need to enter those in individual Host stanzas unless they’re different from the default (which is why I would need the “User pi” entries above to override the “williams” default).
The entries in these stanzas can apply essentially any setting available to openssh, so you can enable port forwarding, vpn, agent forwarding, or any of the others by adding a line to this file (and not having to remember how to do it on the command line).
I’ve been using this approach over the past 3 decades as a network admin, sysadmin, security administrator, and developer. My ~/.ssh/config file has 2094 entries; I’m glad I don’t have to memorize their IP addresses and hostnames!
Here are those three stanzas together along with a template to make adding new items faster:
#Template - copy and edit this for a new host #Host ZZ # Hostname zz # HostKeyAlias zz Host pi-demo-zero pi-demo-0 pi0 192.168.0.233 User pi Hostname raspberrypi.local. #Hostname 192.168.0.233 HostKeyAlias pi-demo-zero Host pi-demo-zero-v6 pi-demo-0-v6 pi0-v6 fe80::fd6f:24bd:16a4:46e #wlan0 Hostname fe80::fd6f:24bd:16a4:46e User pi HostKeyAlias pi-demo-zero Host * User williams Port 22 ConnectTimeout 20
You can start using this approach now – when you next ssh to a host, add a block for it first!
Resources: “man ssh_config” for the different settings that can be placed in this file.
Bill has authored numerous articles and tools for client use. He also serves as a content author and faculty member at the SANS Institute, teaching the Linux System Administration, Perimeter Protection, Securing Linux and Unix, and Intrusion Detection tracks. Bill’s background is in network and operating system security; he was the chief architect of one commercial and two open source firewalls and is an active contributor to multiple projects in the Linux development effort. Bill’s articles and tools can be found in online journals and at http://github.com/activecm/ and http://www.stearns.org.