SSH Tips & Tricks
Here are some of our best tips & tricks for using SSH more effectively. This post will cover how to:
- Add a second factor to your SSH login
- Use agent forwarding safely
- Exit from stuck SSH sessions
- Keep a persistent terminal open
- Share a remote terminal session with a friend (without Zoom!)
Here's five different ways to add a second factor to your SSH connections:
Upgrade your OpenSSH and use a security key. In February 2020 OpenSSH added support for FIDO U2F (Universal Second Factor) security keys. This is a great new feature, but there's a caveat: Because this upgrade introduces new key types for security keys, you'll only be able to use a security key if both client and server have been upgraded to OpenSSH 8.2+. You can check your client version with
ssh -Vand a remote sshd version with
nc [servername] 22
Two new key types were added—
ed25519-sk(along with corresponding certificate types). To generate your key files, insert your security key and run:
$ ssh-keygen -t ecdsa-sk -f ~/.ssh/id_ecdsa_sk
This creates public and private keys tied to your U2F device. A private key on the U2F device is used to decrypt the on-disk private "key handle" when the security key is activated.
You can also supply a passphrase for your keys, as a second factor.
OpenSSH also supports a different style of generating
-sk-type keys: resident keys. With the resident key approach, the key handle is stored on the U2F device. This way, you'll always have it on the security key when you need it. Create resident keys with:
$ ssh-keygen -t ecdsa-sk -O resident -f ~/.ssh/id_ecdsa_sk
Then, to bring the key handle back into memory on a new machine, insert the security key and run:
$ ssh-add -K
You'll still need to activate the security key when connecting to a host.
Use PIV+PKCS11 and a Yubikey. If you want to connect to machines running older versions of SSHD, you can still use a security key—with a different approach. Yubico has a guide for using U2F+SSH with PIV/PKCS11. This is not the same thing as FIDO U2F. It works, but it's arcane to use.
Use Single Sign On SSH. I wrote a tutorial to help you set this up. One advantage of single sign on SSH is, you can leverage the security policy of your identity provider—including multi-factor authentication (MFA) support.
Agent forwarding in SSH allows a remote host to access your local machine's SSH agent. When you SSH with agent forwarding turned on (often using
ssh -A), the connection will have two channels: Your interactive session, and a channel for agent forwarding. The Unix domain socket created by your local SSH agent gets connected to the remote host through this channel. This is risky because a user with
root access on the remote machine can access your local SSH agent and potentially impersonate you on the network. With the standard SSH agent that ships with OpenSSH, you wouldn't even know this was happening. If you use a U2F key (or Sekey), you will effectively thwart any attempt to use your SSH agent.
Even with this precaution, it's still a good idea to use agent forwarding sparingly. Don't use it for all sessions—use it when you know you'll need it for a specific SSH session.
SSH sessions can often hang due to network interruptions, a program that gets out of control, or one of those terminal escape sequences that lock keyboard input. 🤦♂️
Here's how to get out of a stuck session:
Exit automatically on network interruptions. In your
ServerAliveInterval 5 ServerAliveCountMax 1
sshwill check the connection by sending an echo to the remote host every
ServerAliveIntervalseconds. If more than
ServerAliveCountMaxechos are sent without a response,
sshwill timeout and exit.
Break out of the session.
sshincludes the escape character
~by default. The command
~.closes an open connection and brings you back to the terminal. (You can only enter escape sequences on a new line.)
~?lists all of the commands you can use during a session. On international keyboards, you may need to press the
~key twice to send the
Why do stuck sessions happen? Computers didn't move around very much when the internet was invented. When you’re on a laptop and you move between IPv4 WiFi networks, your IP address changes. Because SSH relies on TCP connections, and TCP connections depend on endpoints with stable IP addresses, anytime you change networks your SSH connections will become orphaned and effectively lost. When your IP address changes, it takes a while for your network stack to discover that a connection has been orphaned. With TCP connections, we don’t want one side to close down the connection too quickly when there's a network issue. So TCP will keep retrying to send data for a while before it gives up. Meanwhile in your terminal, the session appears stuck. IPv6 adds some new mobility features that make it possible for a device to retain a home address while moving between networks. Someday, maybe this won't be as much of an issue.
Here's two different approaches to keeping a session going when you're either moving between networks or wanting to disconnect for a while:
If you really need a connection that does not go down even when you move between networks, use Mosh—the mobile shell. Mosh is a secure shell that uses SSH for the handshake, then switches to its own encrypted channel for the session. This separate channel is very resilient. It can handle a dropped internet connection, changes to your laptop's IP address, major network lag, and more, thanks to the magic of UDP and the synchronization protocol that Mosh uses.
To use Mosh, you'll need to install it on both your client and server and open up ports 60000-61000 for inbound UDP traffic to your remote host. Then just
mosh user@serverto connect.
Mosh operates at the level of screens and keystrokes, and this gives it a lot of benefits over SSH, which ferries the binary stream of standard input and output between the client and server. If we only have to synchronize screens and keystrokes, then an interrupted connection becomes much quicker to resume later. SSH would have to buffer and send everything that happened, but Mosh only needs to buffer keystrokes and synchronize the latest frame of the terminal window with the client.
If you'd like to "come and go as you please" and keep the same terminal session going on a remote host, use the terminal multiplexer
tmux. I love
tmuxand I use it all the time. If your SSH connection dies, just reconnect and type
tmux attachto return to your
tmuxsession. It also has some great features, like in-terminal tabs and panes that are similar to the tabs in macOS Terminal, and terminals that can be shared with others.
Some folks like tricking out their
tmuxwith Byobu, a package which provides a lot of usability enhancements and key bindings for
tmux. Byobu ships with Ubuntu, and is easy to install on a Mac with Homebrew.
When debugging a complex issue on your servers, you might like to share an SSH session with someone who is not in the same room.
tmux is perfect for this for terminal sharing! Here are the steps:
- Make sure
tmuxis installed on your bastion, or on whatever server you want to use.
- Both of you will need to SSH to the machine using the same account.
- One person should run
tmuxto start the
- The other person should run
- Voila! You're sharing a terminal.
If you want more sophisticated multi-user
tmux sharing, there's
tmate, which is a fork of
tmux that makes shared terminal sessions a lot easier.
Hit us up on Twitter!—we'd love to expand this post with your best suggestions for using SSH.
Carl Tashian (Website, LinkedIn) is an engineer, writer, exec coach, and startup all-rounder. He's currently an Offroad Engineer at Smallstep. He co-founded and built the engineering team at Trove, and he wrote the code that opens your Zipcar. He lives in San Francisco with his wife Siobhan and he loves to play the modular synthesizer 🎛️🎚️