Skip to content

Instantly share code, notes, and snippets.

@commonquail
Last active September 28, 2015 16:11
Show Gist options
  • Save commonquail/dc8319f2982e724a3583 to your computer and use it in GitHub Desktop.
Save commonquail/dc8319f2982e724a3583 to your computer and use it in GitHub Desktop.

Overview

This is a brief cheat sheet for basic OpenSSH use and configuration, because I can never remember how to do something or why to do it that way.

The advice is based on several sources listed either inline or at the end.

Examples use the user hello at some remote machine with the IP address 10.11.22.33, listening for SSH connections on port 3742.

Regular usage

Establish a connection with

ssh -i ~/.ssh/id_rsa_world [email protected]:3742

The SSH client can be configured to reduce the command to

ssh world

To avoid having to repeat the passphrase when authenticating several times in succession an SSH agent implementation can be used. Some operating systems, including Mac OS X and Ubuntu distributions, manage these by default. Otherwise, OpenSSH includes ssh-agent for this purpose.

ssh-agent sets up environment variables it needs to function so its output needs to be evaluated:

eval $(ssh-agent)

Afterwards, a key can be unlocked with

ssh-add ~/.ssh/id_rsa_world

Situational usage

Generating key pairs

For public key authentication you need to have a key pair. A new one can be generated with

ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa_world

Specify a passphrase when prompted, then transfer the public key.

It is recommended not to use the default key names (id_rsa, etc.). In addition to simply being difficult to keep track of, by default OpenSSH will look for these and transmit any it finds when establishing a connection. The client can be configured to not do this, but getting in the habit of avoiding the default names is probably better.

Transferring public keys

After generating a key pair, the public key needs to be copied to the remote machine.

If the remote machine is, say, a VCS host with SSH support, it may provide a Web interface for inputting the public key (and it may provide no other means of transferring it). They public key can be copied from the command line with

xsel --clipboard < .ssh/id_rsa_world.pub

or an equivalent selection utility.

The file can also be opened in any plain text editor and the contents copied from there.

Otherwise, if the remote machine provides shell access, you can use

ssh-copy-id -i ~/.ssh/id_rsa_world -p 3642 [email protected]

which, with SSH client configuration, can be reduced to

ssh-copy-id -i world

Lastly, the key can be copied manually with

scp ~/.ssh/id_rsa_world.pub -P 3742 [email protected]:
ssh [email protected]:3742
mkdir ~/.ssh
chmod 700 ~/.ssh
cat ~/id_rsa_world.pub >> ~/.ssh/authorized_keys
rm ~/id_rsa_world.pub
chmod 600 ~/.ssh/authorized_keys

In the last case it is not possible to reuse the identity file, because the identity file requires public key authentication, which in turn depends on the above steps having been carried out. Afterwards, however, scp -i world can replace the destination specification (insofar as the necessary client configuration has been made).

Changing a passphrase without modifying a key

A passphrase for an existing key can be changed with

ssh-keygen -f ~/.ssh/id_rsa_world -p

Configuration

For documentation, see man ssh_config.

Client configuration precedence is

  1. command line options
  2. user configuration (~/.ssh/config)
  3. system-wide configuration (/etc/ssh/ssh_config)

In the configuration file, settings are divided into Host sections applied in the order of most to least specific match. From man ssh_config:

Since the first obtained value for each parameter is used, more host-specific declarations should be given near the beginning of the file, and general defaults at the end.

This means Host * should always be the last section.

Below is a basic ~/.ssh/config template aiming for generally sensible security settings. It prefers to re-specify default system-wide settings for situations where these may not be trusted; for instance, where you do not own the system or where the distribution's default configuration diverges from vanilla OpenSSH.

All indentation is optional.

# Per-host configuration.
#
# If HostName is omitted, the value for Host is used instead.
# If the value for Host is anything other than the actual host name,
# the configuration may be ignored by other tools:
# for instance, Git will accept "github.com"
# but not "GitHub" or "github".
#
# $ ssh world
Host world
    # connects to this case-sensitive hostname...
    HostName 10.11.22.33

    # listening on port...
    Port 3742

    # as user...
    User hello

    # with identity file...
    IdentityFile ~/.ssh/id_rsa_world

# A set of trusted servers with a common prefix.
Host my-*
    # Forward X11 fully;
    # default: no
    ForwardX11Trusted yes

# Fall-back options.
# Set global defaults here.
Host *
    # Do not connect to any remote machine using SSH-1;
    # default: 2
    Protocol 2

    # Only use the 'IdentityFile's specified in this file;
    # default: no
    IdentitiesOnly yes

    # Do not forward authentication agent to remote machine;
    # default: no
    ForwardAgent no

    # Do not forward X11;
    # default: no; no
    ForwardX11 no
    ForwardX11Trusted no

    # Check every 60 seconds that the connection is still alive,
    # and terminate connection after 5 failed tries;
    # default: 0 (never); 3
    ServerAliveInterval 60
    ServerAliveCountMax 5

    # Reuse existing connections,
    # useful especially for slow hosts;
    # default: no
    ControlMaster auto
    ControlPath /tmp/%r@%h:%p
    ControlPersist no

These specific configurations are useful for some popular Git hosts:

Host github.com
    User git
    IdentityFile ~/.ssh/id-github

Host bitbucket.org
    User git
    IdentityFile ~/.ssh/id-bitbucket

Host gitlab.com
    User git
    IdentityFile ~/.ssh/id-gitlab

Questions

Which algorithm should I use?

Nearly always RSA, with a length of at least 2048.

For several years now 1024 bits has been considered inadequate, with 2048 being the recommended minimum.

RSA and DSA keys of equal length offer similar levels of security, so the faster algorithm tends to be preferable.

DSA is faster at generating signatures but slower at validating them. In typical usage, which includes SSH authentication, validation will happen much more than generation, so RSA is superior. This sample output from openssl speed (very slow command) shows a difference of a factor 10:

                  sign    verify    sign/s verify/s
rsa  512 bits 0.000048s 0.000004s  20733.3 250973.3
rsa 1024 bits 0.000156s 0.000011s   6422.8  93317.1
rsa 2048 bits 0.001173s 0.000036s    852.2  27853.8
rsa 4096 bits 0.008385s 0.000134s    119.3   7485.3
                  sign    verify    sign/s verify/s
dsa  512 bits 0.000048s 0.000046s  20686.6  21779.0
dsa 1024 bits 0.000111s 0.000122s   8995.7   8222.6
dsa 2048 bits 0.000355s 0.000422s   2814.1   2372.1

Another argument against DSA is that FIPS 186-2 mandates a length of exactly 1024 bits for DSA keys, with no limit for RSA keys. FIPS 186-2 has been superseded by FIPS 186-3, which explicitly allows longer DSA keys, but older implementations of ssh-keygen are not (yet) FIPS 186-3 compliant and so will prevent generating longer keys.

Recent advancements in cryptography suggest that elliptic curve cryptography (ECC) is better still. A caveat is that of the two ECC algorithms supported by OpenSSH, ECDSA looks like it may have been sabotaged by NSA and Ed25519 requires version 6.5 (Jan 2014) and up.

If the availability of Ed25519 can be relied on, it is considered both faster and more secure than RSA.

Do I need a passphrase?

Usually, yes.

The recommendation here is to provide a passphrase, since otherwise the private key will not be encrypted, for instance allowing root free access to it.

In certain situations, such as for headless script automation, a passphrase is not feasible, however. In those situations you should feel free to omit the passphrase but instead take care to configure the remote machine so that such connections are as safe as possible. One tool for this is the command= directive in the authorized_keys file; further configuration is outside the scope of this article.

How can I verify a key's passphrase?

You need the SSH client to issue a challenge. The simplest way to do this is with ssh-keygen:

ssh-keygen -f ~/.ssh/id_rsa_world -y

If the passphrase is correct the public key will be printed to stdout.

You can also achieve this by attempting to load the key into an agent, for instance with ssh-agent and ssh-add.

Why is the remote machine ignoring my correctly configured key?

A recurring issue is incorrect file permissions, for which there are quite strict requirements.

For the connecting client, ensure

chmod go-w ~/
chmod 700 ~/.ssh/
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_rsa_world
chmod 600 ~/.ssh/*.pub

Note that public keys (*.pub) may optionally be readable by anyone (644).

For the remote machine, ensure

chmod go-w /home/hello/
chmod 700 /home/hello/.ssh/
chmod 600 /home/hello/.ssh/config
chmod 600 /home/hello/.ssh/authorized_keys

If that does not solve the problem, look elsewhere.

How do I recursively connect to remote machines?

With ProxyCommand.

The example below uses the previous configuration for world. It also defines an additional finnish-world, but this machine is on a network that can only be reached from world.

Host world
    HostName 10.11.22.33
    Port 3742
    User hello
    IdentityFile ~/.ssh/id_rsa_world

Host finnish-world
    HostName 192.168.1.1
    User hei
    ProxyCommand ssh -q -W %h:%p world

To connect to finnish-world we can first connect to world as normally with

ssh world

and from there establish a direct connection to finnish-world.

The ProxyCommand directive used above does this automatically, so that

ssh finnish-world

on the original machine works as desired.

Do not use SSH agent forwarding (ssh -A).

References

https://wiki.archlinux.org/index.php/SSH_keys

https://heipei.github.io/2015/02/26/SSH-Agent-Forwarding-considered-harmful/

https://www.reddit.com/r/programming/comments/3fut6m/his_ssh_server_knows_who_you_are/ctt71cd

https://www.reddit.com/r/programming/comments/3fut6m/his_ssh_server_knows_who_you_are/ctsfdb3

https://superuser.com/questions/261361/do-i-need-to-have-a-passphrase-for-my-ssh-rsa-key

https://security.stackexchange.com/questions/5096/rsa-vs-dsa-for-ssh-authentication-keys

https://heipei.github.io/2015/04/29/OpenSSH-Secure-Networking-Swiss-Army-Knife/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment