Skip to content

Intro to SSH

Before the mid-1990s, telnet (teletype network) was the standard tool to connect to remote machines. Tatu Ylönen, a computer scientist at Helsinki University of Technology designed the SSH (secure shell) protocol, which added encryption to improve connection security, in 1995 after discovering a password-sniffing attack on the University's network.

Nowadays, SSH is the way to log into remote Linux machines, and can also be used to transfer files using rsync, copy a git repository, port tunneling, etc.

Even if you are not yet ready or willing to switch from another OS to Linux on your local machine, you can still use SSH to manage remote Linux machines.

Installation

To install SSH, you will need to install one of the packages that implement the protocol. This book assumes that you will use openssh, but there are other alternatives you may look into.

Installation on Arch Linux

You can install the client and server by installing the openssh package:

$ sudo pacman -S openssh

Installation on Ubuntu

The client and server are packaged separately on Ubuntu, and can respectively be installed with:

$ sudo apt install openssh-client
$ sudo apt install openssh-server

~/.ssh/

Per-user SSH configuration is stored in the ~/.ssh/ directory. This directory must be restricted to the user that owns it, with permissions set to 700. It may contain one or more of the following files:

  • authorized_keys: a list of public keys allowed to authenticate as the user on the machine hosting this file.
  • config: SSH client configuration for this user.
  • id_ed25519: private Ed25519 key for this user.
  • id_ed25519.pub: public Ed25519 key for this user.
  • id_rsa: private RSA key for this user.
  • id_rsa.pub: public RSA key for this user.
  • known_hosts: a list of known server signatures. This file is created automatically.

SSH keys

SSH keys can serve as an even more secure alternative to passwords, and can be used to authenticate with remote machines. They are not prone to brute-forcing attacks like password authentication is.

SSH keys are generated in pairs, with one private key and a public key. The public key is used to authenticate with the remote machine and can safely be shared with others. The private key, as its name suggests, must be kept private, and is used to decrypt messages.

There are different key types, including DSA, which is considered deprecated, and RSA, which both rely on the factoring problem and the difficulty of factoring the product of two large prime numbers. There's also Ed25519, and ECDSA which rely on elliptic-curve cryptography.

I would generally recommend Ed25519 keys. Elliptic-curve keys are smaller than RSA keys, while providing similar security. There are also concerns that the NSA may have back-doored the ECDSA key.

Generating SSH keys

You can generate SSH keys with the ssh-keygen command. To create a new Ed25519 key pair, run:

$ ssh-keygen -t ed25519

It will prompt you for a file name, and a passphrase. The default file name is .ssh/id_ed25519, and there's no real reason to change it, unless you generate multiple keys, e.g. to manage multiple git identities.

The passphrase may be left blank. If you do enter a passphrase, you will be prompted for it whenever you use the SSH key, e.g. to connect to a server. I generally skip the passphrase for convenience.

Authorized keys

In order to authenticate on remote machines, you may add your public key to the ~/.ssh/authorized_keys file on the remote machine. To do so, simply copy the contents of your public key file, e.g. ~/.ssh/id_ed25519.pub, and add it to the remote host.

If password authentication is enabled, you can also use the ssh-copy-id command to copy your public key to the remote machine.

We will see other ways to add public keys in later chapters.

Connecting to a server

You can connect to a remote machine using SSH by using the ssh command. For example:

$ ssh example.com

Note: this requires the server to be installed and activated on the remote machine, and the client to be installed locally.

If you used a non-standard name for your identity (key) file, you may need to use the -i flag to specify it, e.g. ssh -i ~/.ssh/why_did_I_do_this example.com. By default, your current user's username will be used to authenticate. If you have a different username on the remote host, you can pass it the login flag -l, e.g. ssh -l ubuntu example.com.

The first time you connect to a remote server, you will be prompted to accept the fingerprint. This identifies the remote server. If the fingerprint ever changes randomly, you may need to investigate whether anything suspicious is happening, e.g. domain highjacking, file-system tampering, etc. Accepting the fingerprint will add it to the known_hosts file, so you will not be prompted again.

Note: there are valid reasons for fingerprints to change as well, such as re-building a VPS with the same IP address. This will generate a new SSH fingerprint. If you are sure it is secure to connect using the new fingerprint, you can edit the ~/.ssh/known_hosts file, and delete the old fingerprints. This will force the SSH to prompt you anew.

Configuration

You can configure the SSH client globally, or per-host using the /etc/ssh/ssh_config file to apply settings for all users, or ~/.ssh/config for the current user. Please see the ssh_config man page for complete details.

I highly recommend setting the ServerAliveInterval setting to 30 or 60 seconds, as this may help prevent SSH from dropping idle connections.