Add new SSH fundamentals article #1
@ -3,51 +3,369 @@ Date: 2019-06-17
|
||||
Tags: ssh
|
||||
Slug: demystifying-ssh
|
||||
Description: Understanding, using and troubleshooting SSH for fun and not-for-profit
|
||||
Author: hbsc & friends
|
||||
Author: decentral1se
|
||||
Status: draft
|
||||
Category: fundamentals
|
||||
|
||||
## Introduction
|
||||
|
||||
## Requirements
|
||||
One of the more important and foundational skills needed for experimenting and
|
||||
maintaining servers is understanding, using and troubleshooting SSH.
|
||||
|
||||
## How does SSH help us?
|
||||
SSH is all about remotely gaining access to the command-line interface of your
|
||||
server. Remotely accessing your server is probably one of the first things
|
||||
you'll want to achieve when starting to run a server from your home.
|
||||
|
||||
## All the moving parts
|
||||
When your server has no screen attached, no desktop environment installed, you
|
||||
would like to access it when you are not at home or allow your friend to log
|
||||
in, you will need to use SSH.
|
||||
|
||||
## Getting SSH access
|
||||
Using SSH can be a frustrating experience. There are many moving parts to
|
||||
consider when dealing with user accounts, permissions, public key cryptography,
|
||||
protocols, clients, servers and agents. And yet despite so much to consider,
|
||||
SSH is praised as something easy to use and quite often presupposed knowledge
|
||||
between peers.
|
||||
|
||||
## Giving SSH access
|
||||
With this in mind, there is a need to demystify SSH. In this guide we aim to
|
||||
show how to setup an SSH client and server as well as discuss common issues and
|
||||
approaches for day to day use and troubleshooting.
|
||||
|
||||
## Things people say when they understand SSH
|
||||
## Prerequisites
|
||||
|
||||
### Do you have SSH installed?
|
||||
### Can you send me your SSH public key?
|
||||
### Can you give me SSH access to the server?
|
||||
### Are you able to SSH in?
|
||||
### What's in your SSH config?
|
||||
The SSH ecosystem is old and venerable. It is available on all modern GNU/Linux
|
||||
distributions. You can use your home server or if you don't have one yet you
|
||||
can use your own personal laptop to experiment (in this case, your laptop will
|
||||
play the role of both the server and client as explained later).
|
||||
|
||||
The commands shown in this guide were run on a [Debian Stretch] distribution
|
||||
but the actual tool names should be the same on other distributions.
|
||||
|
||||
[Debian Stretch]: https://en.wikipedia.org/wiki/Debian_version_history#Debian_9_.28Stretch.29
|
||||
|
||||
## SSH and OpenSSH
|
||||
|
||||
The term "SSH" can refer to a number of different but related things.
|
||||
|
||||
SSH stands for the [Secure Shell] which is a protocol for describing how to
|
||||
provide a secure channel of communication from a client to a server. However,
|
||||
it more typically refers to the [OpenSSH suite of tools] which are the programs
|
||||
you will install and use when dealing with SSH.
|
||||
|
||||
[Secure Shell]: https://en.wikipedia.org/wiki/Secure_Shell
|
||||
[OpenSSH suite of tools]: https://en.wikipedia.org/wiki/OpenSSH
|
||||
|
||||
The OpenSSH tools are an implementation of the SSH protocol. This means that
|
||||
these tools follow the behaviour described in the documents of the protocol.
|
||||
|
||||
## Installing the SSH server and client
|
||||
|
||||
It is important to understand the client/server architecture of SSH. If you are
|
||||
remotely connecting to your home server from your laptop, then your laptop is
|
||||
the client and the home server is the server.
|
||||
|
||||
There are two packages which contain all the tools that the OpenSSH tool suite
|
||||
provides. The [openssh-server] and [openssh-client] packages.
|
||||
|
||||
[openssh-server]: https://packages.debian.org/stretch/openssh-server
|
||||
[openssh-client]: https://packages.debian.org/stretch/openssh-client
|
||||
|
||||
To install the SSH server on your home server, run:
|
||||
|
||||
```bash
|
||||
$ sudo apt install -y openssh-server
|
||||
```
|
||||
|
||||
And from your client (laptop or otherwise), run:
|
||||
|
||||
```bash
|
||||
$ sudo apt install -y openssh-client
|
||||
```
|
||||
|
||||
## Creating a user account on the server
|
||||
|
||||
In order for your client to connect to the server, a user account must be
|
||||
created on the server. This can be done with the following command (where
|
||||
`homebrewer` is the new user account):
|
||||
|
||||
```bash
|
||||
$ sudo useradd --create-home --shell /bin/bash homebrewer
|
||||
```
|
||||
|
||||
You should then set a password for this new user:
|
||||
|
||||
```bash
|
||||
$ sudo passwd homebrewer
|
||||
```
|
||||
|
||||
This password will be used in the following step.
|
||||
|
||||
## Logging in for the first time
|
||||
|
||||
You can now SSH into the server from your client. Assuming that you have a DNS
|
||||
entry which points to your home server (`myhomebrewserver.com`) then you can
|
||||
log in with:
|
||||
|
||||
```bash
|
||||
$ ssh homebrewer@myhomebrewserver.com
|
||||
```
|
||||
|
||||
On first connection to a new server, you will be shown a fingerprint and asked
|
||||
if you would like to continue connecting. For now, choose to continue without
|
||||
validating the fingerprint.
|
||||
|
||||
You should then be asked for the password that you entered when creating the
|
||||
account. If you have any issues at this point, please see the [Troubleshooting
|
||||
SSH] section.
|
||||
|
||||
[Troubleshooting SSH]: #troubleshooting-ssh
|
||||
|
||||
## Passwords, keys and security
|
||||
|
||||
As we have seen so far, connecting to an SSH server using password
|
||||
authorisation is relatively simple. However, password authorisation is
|
||||
typically recommended against due to [security considerations].
|
||||
|
||||
Security is relative and you may not be concerned with defending against a
|
||||
[brute-force attack]. However, since other methods of authorisation are so
|
||||
commonly used and often the source of of problems when dealing with SSH
|
||||
connectivity, we will also cover this topic also.
|
||||
|
||||
[security considerations]: http://docs.hardentheworld.org/Applications/OpenSSH/#disable-password-authentication
|
||||
[brute-force attack]: https://en.wikipedia.org/wiki/Brute-force_attack
|
||||
|
||||
The alternative to password authorisation is [public key cryptography]. The
|
||||
idea is to generate two keys, one public and the other private. The public key
|
||||
part can be shared publicly and will be registered with the SSH server. The
|
||||
private key part cannot be shared with anyone else and will be used on the
|
||||
client side for authentication.
|
||||
|
||||
[public key cryptography]: https://en.wikipedia.org/wiki/Public-key_cryptography
|
||||
|
||||
For those not familiar with public key encryption, a brief and pragmatic
|
||||
introduction is provided by [this ssd.eff.org guide].
|
||||
|
||||
[this ssd.eff.org guide]: https://ssd.eff.org/en/module/key-concepts-encryption#1
|
||||
|
||||
## Validating server host keys
|
||||
|
||||
When logging into your server you were asked to validate a key fingerprint:
|
||||
|
||||
```
|
||||
The authenticity of host 'myhomebrewserver (666.666.666.666)' ed.
|
||||
ECDSA key fingerprint is SHA256:lUhBmQXjkOL0zyoDNarUIbhd3RXo7X
|
||||
Are you sure you want to continue connecting (yes/no)?
|
||||
```
|
||||
|
||||
When an SSH server is installed, key pairs are generated on the server. The
|
||||
design of SSH is such that when you make a secure connection you should be sure
|
||||
that where you are connecting to is the server you expect.
|
||||
|
||||
On the server, you can validate that this is fingerprint you expect:
|
||||
|
||||
```bash
|
||||
$ sudo ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key
|
||||
256 SHA256:lUhBmQXjkOL0zyoDNarUIbhd3RXo7X root@myhomebrewserver (ECDSA)
|
||||
```
|
||||
These values should match the ones you were first shown. Where the `ECDSA` in
|
||||
the first message corresponds to the key file name in `/etc/ssh/`. The SSH
|
||||
server will generate key pairs for each algorithm it supports.
|
||||
|
||||
As you have accepted your server host key fingerprint, the public key of the
|
||||
server will be placed in your `$HOME/.ssh/known_hosts` file on your client
|
||||
where it will be remembered for future connections.
|
||||
|
||||
If the host key ever changes, you will see something like:
|
||||
|
||||
```
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
|
||||
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
|
||||
It is also possible that a host key has just been changed.
|
||||
...
|
||||
```
|
||||
|
||||
This simply means that that the host key you accepted for this host has changed
|
||||
and you should first figure out why this is the case before making a secure
|
||||
connection.
|
||||
|
||||
## Dealing with SSH keys
|
||||
|
||||
### Generating a public and private key pair
|
||||
|
||||
Now that we understand the idea of host keys, we should generate client keys.
|
||||
On your client, run the following:
|
||||
|
||||
```
|
||||
$ ssh-keygen -t ed25519
|
||||
```
|
||||
|
||||
This uses the [currently preferred algorithm] for generating keys. The key
|
||||
generation will ask you to enter a passphrase. It is typically recommended use
|
||||
a strong passphrase (see [diceware]) for the reason that if someone else gets
|
||||
your private key part, they still will still not be able to use it because they
|
||||
also need to know the passphrase.
|
||||
|
||||
[currently preferred algorithm]: https://wiki.archlinux.org/index.php/SSH_keys#Generating_an_SSH_key_pair
|
||||
[diceware]: https://www.rempe.us/diceware/#eff
|
||||
|
||||
You should now have two keys in your `$HOME/.ssh` folder. A `id_ed25519`
|
||||
(private key part) and a `id_ed25519.pub` file (public key part).
|
||||
|
||||
Your public key part might look something like:
|
||||
|
||||
```
|
||||
$ cat $HOME/.ssh/id_ed25519
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOTWIy+Em89QR/Xs6RUmr+0U0F3GVXY/UA2MXs9MoqdY myuser@myhost
|
||||
```
|
||||
|
||||
You can then start an `ssh-agent` instance and register the private key part:
|
||||
|
||||
```bash
|
||||
$ eval "$(ssh-agent -s)"
|
||||
$ ssh-add $HOME/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
The `ssh-agent` should ask for your passphrase. The agent is useful because it
|
||||
will store the passphrase of your key and re-use it the next time you log into
|
||||
the server. This can be particularly useful later on when you need to use
|
||||
multiple SSH keys.
|
||||
|
||||
You can confirm that the `ssh-agent` has loaded this key by running:
|
||||
|
||||
```bash
|
||||
$ ssh-add -L
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOTWIy+Em89QR/Xs6RUmr+0U0F3GVXY/UA2MXs9MoqdY myuser@myhost
|
||||
```
|
||||
|
||||
And finally, you can then configure your client to use this key. Create a
|
||||
`$HOME/.ssh/config` file and put something like the following configuration
|
||||
into it (remember to replace with your server details):
|
||||
|
||||
```bash
|
||||
Host myhomebrewserver
|
||||
Hostname myhomebrewserver.com
|
||||
User homebrewer
|
||||
Port 22
|
||||
IdentityFile ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
This is useful because it allows you to only type:
|
||||
|
||||
```bash
|
||||
$ ssh myhomebrewserver
|
||||
```
|
||||
|
||||
And the correct hostname, user, port and key will be chosen. However, before
|
||||
connecting, you must register your public key part on the server.
|
||||
|
||||
### Register the public key with the server
|
||||
|
||||
On the server, you should register the public key. This is achieved by putting
|
||||
the public key part of the key into the `/home/homebrewer/.ssh/authorized_keys`
|
||||
file.
|
||||
|
||||
You can do this like so (replace the public key part with the one you generated):
|
||||
|
||||
```bash
|
||||
$ sudo -su homebrewser
|
||||
$ cd $HOME && mkdir .ssh
|
||||
$ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOTWIy+Em89QR/Xs6RUmr+0U0F3GVXY/UA2MXs9MoqdY myuser@myhost" > .ssh/authorized_keys
|
||||
```
|
||||
|
||||
You must then ensure that your SSH server is accepting keys as a method of
|
||||
authentication. You should edit the `/etc/ssh/sshd_config` file which is the
|
||||
main configuration file for the SSH server.
|
||||
|
||||
You need to ensure the following is present:
|
||||
|
||||
```bash
|
||||
PubkeyAuthentication yes
|
||||
```
|
||||
|
||||
After editing the file, save your changes and then validate the configuration:
|
||||
|
||||
```bash
|
||||
$ sudo sshd -t
|
||||
```
|
||||
|
||||
No output should be shown if everything is validating correctly. This is
|
||||
important to do before restarting the SSH server in case you lock yourself out
|
||||
of the server.
|
||||
|
||||
You can restart the SSH server with:
|
||||
|
||||
```bash
|
||||
$ sudo systemctl restart sshd
|
||||
```
|
||||
|
||||
Now it should be possible to connect from your client with:
|
||||
|
||||
```bash
|
||||
$ ssh myhomebrewserver
|
||||
```
|
||||
|
||||
If you have any issues, please see the [Troubleshooting SSH] section.
|
||||
|
||||
[Troubleshooting SSH]: #troubleshooting-ssh
|
||||
|
||||
## Troubleshooting SSH
|
||||
|
||||
### Remember the moving parts
|
||||
Despite our best intentions, we are often confronted with a failed login attempt:
|
||||
|
||||
```
|
||||
$ ssh myhomebrewserver
|
||||
Permission denied (publickey).
|
||||
```
|
||||
|
||||
This is not the most helpful message. In order to go about solving this issue,
|
||||
we need to focus our detective work on the client/server architecture and try
|
||||
to discover which side is responsible for the problem. Hopefully the following
|
||||
tips can help you in this process.
|
||||
|
||||
### On the server
|
||||
|
||||
#### Public key
|
||||
#### Permissions
|
||||
#### SSH server is running
|
||||
#### SSH server configuration
|
||||
Here are some questions to ask yourself:
|
||||
|
||||
* Is your public key registered on the server in the `$HOME/.ssh/authorized_keys` folder?
|
||||
|
||||
* Are the folder permissions correct? (see this [SO thread](https://superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder))
|
||||
|
||||
* Is the SSH server running? (`sudo systemctl status sshd`)
|
||||
|
||||
* Is the `/etc/ssh/ssd_config` correct?
|
||||
* Use the [sshd_config](https://man.openbsd.org/sshd_config) as a
|
||||
reference. Don't forget to run `sudo sshd -t` to validate your
|
||||
changes. After validating, always restart the SSH server after
|
||||
making configuration changes
|
||||
|
||||
### On the client
|
||||
|
||||
#### Permissions
|
||||
#### Is your public key there?
|
||||
#### Is the server up?
|
||||
#### Config check
|
||||
#### What does the agent say?
|
||||
Here are some questions to ask yourself:
|
||||
|
||||
### Other scenarios
|
||||
* What does `ssh -vvvvv myhomebrewserver` tell you?
|
||||
|
||||
#### Git
|
||||
* Are the folder permissions correct? (see this [SO thread](https://superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder))
|
||||
|
||||
* Is the SSH server available at the port you expect? (`sudo nmap -p 22 myhomebrewserver`)
|
||||
|
||||
* Is your `$HOME/.ssh/config` correct?
|
||||
|
||||
* What is registered with the local `ssh-agent`?
|
||||
* Check which keys are registered with `ssh-add -L`. If you
|
||||
see unrecognised keys, you can kill and restart the agent:
|
||||
* `sudo pkill ssh-agent`
|
||||
* ` eval "$(ssh-agent -s)"`
|
||||
* `ssh-add ~/.ssh/id_ed25519`
|
||||
|
||||
## Conclusions
|
||||
|
||||
As we can see, SSH is no simple topic! There are many moving parts and a number
|
||||
of topics which require familiarity in order to be able to get remote access to
|
||||
your server.
|
||||
|
||||
## Further Reading
|
||||
|
||||
* [/etc/ssh/sshd_config reference](https://man.openbsd.org/sshd_config)
|
||||
* [SSH server hardening](http://docs.hardentheworld.org/Applications/OpenSSH/)
|
||||
|
Loading…
Reference in New Issue
Block a user