265 lines
14 KiB
Markdown
265 lines
14 KiB
Markdown
# Pushing SSH a bit further
|
||
|
||
## What is SSH
|
||
|
||
### Origins
|
||
|
||
SSH is *the* current standard for remote logins but you might want to read up a bit on what was used before SSH existed.
|
||
[This](https://www.jeffgeerling.com/blog/brief-history-ssh-and-remote-access) is a pretty good blog post on the history of SSH.
|
||
You should never use the following the following programs anymore but it's good to be aware of their historic existance.
|
||
|
||
* rlogin
|
||
* rsh
|
||
* rcp
|
||
* telnet (still has some legitimate usage such as with munin)
|
||
|
||
The main advantage of SSH is it's encryption.
|
||
It works similarly to SSL which you use all the time to do most of your web browsing.
|
||
When using encryption it becomes **very** hard to sniff the data traveling between the client and the server.
|
||
There are two versions of SSH, version 1 and version 2, and you should only use version 2 as the former is not considered [secure]() anymore.
|
||
The recommended encryption used by most SSH servers is [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard).
|
||
If you're interested in understanding the mathematics behind AES, [this](https://www.youtube.com/channel/UC1usFRN4LCMcfIV7UjHNuQg) class is exceptionally good but not for the faint of heart.
|
||
It's not mandatory to fully understand the math behind encryption to use it though.
|
||
The main takeaway would be the number of **bit's used** where **higher** is **better**.
|
||
By default ssh uses a very secure cipher but you can specify which one you want with the `-c` flag to `ssh`.
|
||
Do keep in mind that the server needs to support the cipher you're requesting.
|
||
|
||
## SSH keys
|
||
|
||
SSH encryption and SSH keys are not the same thing.
|
||
**Keys** are used for **authentication** with a server.
|
||
Once the client is authenticated and granted access to the server, the encryption is set to **encrypt** the **traffic** from client to server and visa versa.
|
||
SSH keys are [asymmetric](https://en.wikipedia.org/wiki/Public-key_cryptography) key pairs where you have two simple text files.
|
||
One with the **private** part, which is used for **decrypting**, and one **public** part which is used for **encrypting**.
|
||
Both parts together form one **key pair**.
|
||
If you're interested in the maths behind key pairs, have a look at this 15min [video](https://www.youtube.com/watch?v=4zahvcJ9glg&t=1s), it's a lot easier than you expect!
|
||
|
||
![key pairs](./assets/key_encryption.png)
|
||
|
||
### Generating keys
|
||
|
||
SSH comes with `ssh-keygen` to generate keys.
|
||
Keys are by default stored in `~/.ssh/` and named `id_rsa` for the **private** part, and `id_rsa.pud` for the **public** part.
|
||
**Important**, each generated key is **unique** so if you overwrite a key you made previously that old key is **gone!**.
|
||
There is **no way** to recover that old key anymore, gone is gone.
|
||
I highly advise you to keep backup's of your important keys, preferably in multiple locations.
|
||
GNOME [Seahorse](https://wiki.gnome.org/Apps/Seahorse/) or [keepass2](https://keepass.info/) are good password managers you can use to store both passwords and key pairs.
|
||
|
||
An ssh key can be generated by running the `ssh-keygen` command.
|
||
You'll be prompted with a dialog that will ask to name and where to save the key pair, plus whether you want a password for that key or not.
|
||
For automated logins you should not set a password as it would defeat the purpose but you **must** realise that everyone that has access to the **private** key will be able to log in to each server the key is deployed to.
|
||
Keeping this file safe becomes very important.
|
||
|
||
**Remember the bandit SSH key level?**
|
||
|
||
```
|
||
➜ ~ git:(master) ✗ ssh-keygen
|
||
Generating public/private rsa key pair.
|
||
Enter file in which to save the key (/home/waldek/.ssh/id_rsa): my_ssh_key
|
||
Enter passphrase (empty for no passphrase):
|
||
Enter same passphrase again:
|
||
Your identification has been saved in my_ssh_key.
|
||
Your public key has been saved in my_ssh_key.pub.
|
||
The key fingerprint is:
|
||
SHA256:ndWgt3PjUjrdfaBMudQFJM8xCrjPKXlvg9TRYsWz2UQ waldek@helloworld
|
||
The key's randomart image is:
|
||
+---[RSA 2048]----+
|
||
| .. oo=.E|
|
||
| . o B++.|
|
||
| .. +o+*.|
|
||
| .. ++++..|
|
||
| S+o+*o* |
|
||
| o *+.X +.|
|
||
| + oB o +|
|
||
| . +o .|
|
||
| . . |
|
||
+----[SHA256]-----+
|
||
➜ ~ git:(master) ✗
|
||
```
|
||
|
||
The current default is to generate an [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) key of 2048 bits which is currently considered secure.
|
||
You can change the scheme and bit depth with the `-t` and `-b` arguments respectively.
|
||
Have a look at the `man ssh-keygen` pages for more info.
|
||
|
||
### Deploying keys
|
||
|
||
Just generating a key is not that useful, we need to know how to **use** them.
|
||
In order to understand that we need to have a look at how an ssh connection works.
|
||
When you try to establish an ssh connection you can add a `-v` flag to make the output more verbose.
|
||
You'll see output along the lines of this:
|
||
|
||
```
|
||
➜ qualifying git:(master) ✗ ssh student@localhost -v
|
||
OpenSSH_7.9p1 Debian-10+deb10u2, OpenSSL 1.1.1d 10 Sep 2019
|
||
debug1: Reading configuration data /home/waldek/.ssh/config
|
||
debug1: Reading configuration data /etc/ssh/ssh_config
|
||
debug1: /etc/ssh/ssh_config line 19: Applying options for *
|
||
debug1: Connecting to localhost [127.0.0.1] port 22.
|
||
debug1: Connection established.
|
||
debug1: identity file /home/waldek/.ssh/id_rsa type 0
|
||
debug1: identity file /home/waldek/.ssh/id_rsa-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_dsa type -1
|
||
debug1: identity file /home/waldek/.ssh/id_dsa-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ecdsa type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ecdsa-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ed25519 type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ed25519-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_xmss type -1
|
||
debug1: identity file /home/waldek/.ssh/id_xmss-cert type -1
|
||
debug1: Local version string SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2
|
||
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.9p1 Debian-10+deb10u2
|
||
debug1: match: OpenSSH_7.9p1 Debian-10+deb10u2 pat OpenSSH* compat 0x04000000
|
||
debug1: Authenticating to localhost:22 as 'student'
|
||
debug1: SSH2_MSG_KEXINIT sent
|
||
debug1: SSH2_MSG_KEXINIT received
|
||
debug1: kex: algorithm: curve25519-sha256
|
||
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
|
||
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
|
||
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
|
||
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
|
||
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:iALTEcfl6AjvOnT0TWBNrp/PsuWem/ZiP+uGRVEeFaE
|
||
debug1: Host 'localhost' is known and matches the ECDSA host key.
|
||
debug1: Found key in /home/waldek/.ssh/known_hosts:1
|
||
debug1: rekey after 134217728 blocks
|
||
debug1: SSH2_MSG_NEWKEYS sent
|
||
debug1: expecting SSH2_MSG_NEWKEYS
|
||
debug1: SSH2_MSG_NEWKEYS received
|
||
debug1: rekey after 134217728 blocks
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_rsa RSA SHA256:tOuvE+Qq1B/eXyGcyIfs0MVXaaSI/GNYjLqO3D+Tz+k
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_dsa
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_ecdsa
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_ed25519
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_xmss
|
||
debug1: SSH2_MSG_EXT_INFO received
|
||
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521>
|
||
debug1: SSH2_MSG_SERVICE_ACCEPT received
|
||
debug1: Authentications that can continue: publickey,password
|
||
debug1: Next authentication method: publickey
|
||
debug1: Offering public key: /home/waldek/.ssh/id_rsa RSA SHA256:tOuvE+Qq1B/eXyGcyIfs0MVXaaSI/GNYjLqO3D+Tz+k
|
||
debug1: Authentications that can continue: publickey,password
|
||
debug1: Trying private key: /home/waldek/.ssh/id_dsa
|
||
debug1: Trying private key: /home/waldek/.ssh/id_ecdsa
|
||
debug1: Trying private key: /home/waldek/.ssh/id_ed25519
|
||
debug1: Trying private key: /home/waldek/.ssh/id_xmss
|
||
debug1: Next authentication method: password
|
||
student@localhost's password:
|
||
```
|
||
|
||
The connection will try any form of authentication allowed by the server in order of most secure to least secure.
|
||
Publickeys are considered more secure than passwords so it will try that first.
|
||
You can see this at the following line `debug1: Will attempt key: /home/waldek/.ssh/id_rsa RSA SHA256:tOuvE+Qq1B/eXyGcyIfs0MVXaaSI/GNYjLqO3D+Tz+k`.
|
||
The `student` account does not have the matching public key as an authorized key so the client tries a password login next `debug1: Next authentication method: password`.
|
||
|
||
On the server side the sshd process will look for a matching **public** key in the users home directory.
|
||
By default it will try every line in the `~/.ssh/authorized_keys` file for authentication.
|
||
If a match is found, you'll be granted access, if not it will try an other authentication method until every method allowed by the server is exhausted and you'll be denied access.
|
||
The verbose output of a successful login with a key pair can be seen below.
|
||
|
||
```
|
||
➜ ~ git:(master) ✗ ssh student@localhost -v
|
||
OpenSSH_7.9p1 Debian-10+deb10u2, OpenSSL 1.1.1d 10 Sep 2019
|
||
debug1: Reading configuration data /home/waldek/.ssh/config
|
||
debug1: Reading configuration data /etc/ssh/ssh_config
|
||
debug1: /etc/ssh/ssh_config line 19: Applying options for *
|
||
debug1: Connecting to localhost [127.0.0.1] port 22.
|
||
debug1: Connection established.
|
||
debug1: identity file /home/waldek/.ssh/id_rsa type 0
|
||
debug1: identity file /home/waldek/.ssh/id_rsa-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_dsa type -1
|
||
debug1: identity file /home/waldek/.ssh/id_dsa-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ecdsa type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ecdsa-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ed25519 type -1
|
||
debug1: identity file /home/waldek/.ssh/id_ed25519-cert type -1
|
||
debug1: identity file /home/waldek/.ssh/id_xmss type -1
|
||
debug1: identity file /home/waldek/.ssh/id_xmss-cert type -1
|
||
debug1: Local version string SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2
|
||
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.9p1 Debian-10+deb10u2
|
||
debug1: match: OpenSSH_7.9p1 Debian-10+deb10u2 pat OpenSSH* compat 0x04000000
|
||
debug1: Authenticating to localhost:22 as 'student'
|
||
debug1: SSH2_MSG_KEXINIT sent
|
||
debug1: SSH2_MSG_KEXINIT received
|
||
debug1: kex: algorithm: curve25519-sha256
|
||
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
|
||
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
|
||
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
|
||
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
|
||
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:iALTEcfl6AjvOnT0TWBNrp/PsuWem/ZiP+uGRVEeFaE
|
||
debug1: Host 'localhost' is known and matches the ECDSA host key.
|
||
debug1: Found key in /home/waldek/.ssh/known_hosts:1
|
||
debug1: rekey after 134217728 blocks
|
||
debug1: SSH2_MSG_NEWKEYS sent
|
||
debug1: expecting SSH2_MSG_NEWKEYS
|
||
debug1: SSH2_MSG_NEWKEYS received
|
||
debug1: rekey after 134217728 blocks
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_rsa RSA SHA256:tOuvE+Qq1B/eXyGcyIfs0MVXaaSI/GNYjLqO3D+Tz+k
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_dsa
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_ecdsa
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_ed25519
|
||
debug1: Will attempt key: /home/waldek/.ssh/id_xmss
|
||
debug1: SSH2_MSG_EXT_INFO received
|
||
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521>
|
||
debug1: SSH2_MSG_SERVICE_ACCEPT received
|
||
debug1: Authentications that can continue: publickey,password
|
||
debug1: Next authentication method: publickey
|
||
debug1: Offering public key: /home/waldek/.ssh/id_rsa RSA SHA256:tOuvE+Qq1B/eXyGcyIfs0MVXaaSI/GNYjLqO3D+Tz+k
|
||
debug1: Server accepts key: /home/waldek/.ssh/id_rsa RSA SHA256:tOuvE+Qq1B/eXyGcyIfs0MVXaaSI/GNYjLqO3D+Tz+k
|
||
debug1: Authentication succeeded (publickey).
|
||
Authenticated to localhost ([127.0.0.1]:22).
|
||
debug1: channel 0: new [client-session]
|
||
debug1: Requesting no-more-sessions@openssh.com
|
||
debug1: Entering interactive session.
|
||
debug1: pledge: network
|
||
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
|
||
debug1: Remote: /home/student/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
|
||
debug1: Remote: /home/student/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
|
||
debug1: Sending environment.
|
||
debug1: Sending env LC_CTYPE = en_GB.UTF-8
|
||
debug1: Sending env LANG = en_GB.UTF-8
|
||
Linux helloworld 4.19.0-17-amd64 #1 SMP Debian 4.19.194-1 (2021-06-10) x86_64
|
||
|
||
The programs included with the Debian GNU/Linux system are free software;
|
||
the exact distribution terms for each program are described in the
|
||
individual files in /usr/share/doc/*/copyright.
|
||
|
||
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
|
||
permitted by applicable law.
|
||
student@helloworld:~$
|
||
```
|
||
|
||
## Standard usage
|
||
|
||
## Tweaking the sshd configuration file
|
||
|
||
All server configuration is done in the `/etc/ssh/sshd_config` file.
|
||
Starting version TO_CHECK you can use the modern `/etc/ssh/sshd_config.d/` folder system to override default system configuration.
|
||
This way any changes to the standard configuration made by the package maintainers won't mess with your custom preferences and tweaks.
|
||
|
||
### Version
|
||
|
||
A modern sshd configuration will only allow version 2 but you can check or specify this in the configuration file.
|
||
You'll probably never have to set this yourself but do keep it in mind when you're confronted with old installations.
|
||
|
||
```
|
||
Protocol
|
||
Specifies the protocol versions sshd(8) supports. The possible values are ‘1’ and
|
||
‘2’. Multiple versions must be comma-separated. The default is ‘2’. Protocol 1
|
||
suffers from a number of cryptographic weaknesses and should not be used. It is
|
||
only offered to support legacy devices.
|
||
|
||
Note that the order of the protocol list does not indicate preference, because the
|
||
client selects among multiple protocol versions offered by the server. Specifying
|
||
“2,1” is identical to “1,2”.
|
||
```
|
||
|
||
## Tunnels
|
||
|
||
## SFTP
|
||
|
||
## Autossh
|
||
|
||
## SSHFS
|
||
|
||
## SSHuttle
|
||
|