2021-12-08 00:37:05 +00:00
|
|
|
---
|
|
|
|
|
title: Securing SSH
|
|
|
|
|
date: 2021-12-07T22:41:02Z
|
|
|
|
|
author: "ahmza"
|
|
|
|
|
draft: false
|
|
|
|
|
weight:
|
|
|
|
|
|
|
|
|
|
tags: ["HomeLab", "SSH", "RemoteAccess"]
|
|
|
|
|
description: "Ever wanted to make your SSH connections more secure. Read this"
|
|
|
|
|
canonicalURL: "https://blog.ahmza.com/Page%28/posts/securing-ssh.md%29"
|
|
|
|
|
|
|
|
|
|
cover:
|
2021-12-12 23:50:18 +00:00
|
|
|
image: "/img/Secure-SSH/Padlock.png"
|
2021-12-08 00:37:05 +00:00
|
|
|
alt: "ssh-alt image" # alt text
|
|
|
|
|
caption: "<text>" # display caption under cover
|
|
|
|
|
relative: false # when using page bundles set this to true
|
|
|
|
|
showtoc: true
|
|
|
|
|
searchHidden: false
|
|
|
|
|
---
|
|
|
|
|
# **Introduction**
|
|
|
|
|
SSH is a widely used protocol to access remote devices. The problem
|
|
|
|
|
with SSH is at the authentication stage, Brute force attacks are one of
|
|
|
|
|
the ways an SSH connection can be compromised. A malicious actor will
|
|
|
|
|
constantly hammer the remote host with different passwords until it can
|
|
|
|
|
gain access. With further configuration of SSH we can make the service
|
|
|
|
|
a lot more secure.
|
|
|
|
|
|
|
|
|
|
# **Configure SSH**
|
|
|
|
|

|
|
|
|
|
> **Famous last words:** Configuring SSH like many things in Linux is
|
|
|
|
|
as simple as editing a few config files
|
|
|
|
|
|
|
|
|
|
Always be sure to **create a backup file** it's very easy to end up
|
|
|
|
|
locking yourself out of a device.
|
|
|
|
|
|
|
|
|
|
I would recommend practising on a machine that is not critical.
|
|
|
|
|
|
|
|
|
|
## **Create SSH Keys**
|
|
|
|
|
SSH keys use public and private key encryption for authentication.
|
|
|
|
|
|
|
|
|
|
To create a set of keys, **on the client do:**
|
|
|
|
|
``` bash
|
|
|
|
|
ssh-keygen
|
|
|
|
|
```
|
|
|
|
|
You will be asked where you want to save the keys, **I recommend the \
|
|
|
|
|
default location** for less hair pulling later.
|
|
|
|
|
``` bash
|
|
|
|
|
Enter file in which to save the key (/home/user/.ssh/id_rsa):
|
|
|
|
|
```
|
|
|
|
|
You will be asked to enter a password for the ssh keys, be sure to use
|
|
|
|
|
a strong password.
|
|
|
|
|
``` bash
|
|
|
|
|
Enter passphrase (empty for no passphrase):
|
|
|
|
|
```
|
|
|
|
|
Once that is done you will see a confirmation screen like the one below
|
|
|
|
|
```
|
|
|
|
|
Output
|
|
|
|
|
Your identification has been saved in /home/user/.ssh/id_rsa
|
|
|
|
|
Your public key has been saved in /home/user/.ssh/id_rsa.pub
|
|
|
|
|
The key fingerprint is:
|
|
|
|
|
SHA256:tIurljnWJRBc1RnHUJQ5GtND7p9HWKnjV6zjE9AFR1Y user@host
|
|
|
|
|
The key's randomart image is:
|
|
|
|
|
+---[RSA 3072]----+
|
|
|
|
|
| . .....oX=o.oE|
|
|
|
|
|
| o =oB oo|
|
|
|
|
|
| . . +.+ o.|
|
|
|
|
|
| . . .... o+ |
|
|
|
|
|
| . S .+. +|
|
|
|
|
|
| .... ..o+.|
|
|
|
|
|
| +.o. .=o.|
|
|
|
|
|
| * .. .oo |
|
|
|
|
|
| o.o. .. |
|
|
|
|
|
+----[SHA256]-----+
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## **Copy SSH Keys**
|
|
|
|
|
> **Quick note:** user@host is the **username** on the **remeote host**
|
|
|
|
|
you would like to copy your public key to.
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
ssh-copy-id user@host
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**If asked to confirm the connection to the remote host answer yes**, this
|
|
|
|
|
happens when a new machine with an unknown identity wants to connect to
|
|
|
|
|
the client.
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Output
|
|
|
|
|
The authenticity of host 'host(host)' can't be established.
|
|
|
|
|
ECDSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx.
|
|
|
|
|
Are you sure you want to continue connecting (yes/no)? yes
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
You will then be asked to **enter a password** for the user on the remote
|
|
|
|
|
host
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Output
|
|
|
|
|
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
|
|
|
|
|
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
|
|
|
|
|
user@host's password:
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If successful you should be able to access the device using the SSH key
|
|
|
|
|
|
|
|
|
|
To verify this, SSH to the device and **it should ask for the Keys's
|
|
|
|
|
password not the users**
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
Enter passphrase for key '/home/user/.ssh/id_rsa':
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## **Modify SSH Config**
|
|
|
|
|
create a backup
|
|
|
|
|
``` bash
|
|
|
|
|
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
|
|
|
|
|
```
|
|
|
|
|
open the original file in a text editor
|
|
|
|
|
``` bash
|
|
|
|
|
sudo vim /etc/ssh/sshd_config
|
|
|
|
|
```
|
|
|
|
|
For a new user this might be daunting. Take your time and you will be
|
|
|
|
|
fine 😊
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
**Lines we want to modify**
|
|
|
|
|
|
|
|
|
|
> **Quick note:** you may need to uncomment some lines as well as add a
|
|
|
|
|
few
|
|
|
|
|
|
|
|
|
|
* Protocol 2 - add to line 15
|
|
|
|
|
* Port 2222 - modify line 17
|
|
|
|
|
* PermitRootLogin no - modify line 36
|
|
|
|
|
* Max Auth Tries 5 - modify line 38
|
|
|
|
|
* PasswordAuthentication no - modify line 60
|
|
|
|
|
* PermitEmptyPasswords no -modify line 61
|
|
|
|
|
* AllowUsers ahmza - add line 67
|
|
|
|
|
* ClientAliveInterval 180 - modify line 104
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
|
|
|
|
|
|
|
|
|
|
# This is the sshd server system-wide configuration file. See
|
|
|
|
|
# sshd_config(5) for more information.
|
|
|
|
|
|
|
|
|
|
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
|
|
|
|
|
|
|
|
|
# The strategy used for options in the default sshd_config shipped with
|
|
|
|
|
# OpenSSH is to specify options with their default value where
|
|
|
|
|
# possible, but leave them commented. Uncommented options override the
|
|
|
|
|
# default value.
|
|
|
|
|
|
|
|
|
|
Include /etc/ssh/sshd_config.d/*.conf
|
|
|
|
|
|
|
|
|
|
Protocol 2
|
|
|
|
|
|
|
|
|
|
Port 2222
|
|
|
|
|
#AddressFamily any
|
|
|
|
|
#ListenAddress 0.0.0.0
|
|
|
|
|
#ListenAddress ::
|
|
|
|
|
|
|
|
|
|
#HostKey /etc/ssh/ssh_host_rsa_key
|
|
|
|
|
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
|
|
|
|
#HostKey /etc/ssh/ssh_host_ed25519_key
|
|
|
|
|
|
|
|
|
|
# Ciphers and keying
|
|
|
|
|
#RekeyLimit default none
|
|
|
|
|
|
|
|
|
|
# Logging
|
|
|
|
|
#SyslogFacility AUTH
|
|
|
|
|
#LogLevel INFO
|
|
|
|
|
|
|
|
|
|
# Authentication:
|
|
|
|
|
|
|
|
|
|
#LoginGraceTime 2m
|
|
|
|
|
PermitRootLogin no
|
|
|
|
|
#StrictModes yes
|
|
|
|
|
MaxAuthTries 5
|
|
|
|
|
#MaxSessions 10
|
|
|
|
|
|
|
|
|
|
#PubkeyAuthentication yes
|
|
|
|
|
|
|
|
|
|
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
|
|
|
|
|
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
|
|
|
|
|
|
|
|
|
|
#AuthorizedPrincipalsFile none
|
|
|
|
|
|
|
|
|
|
#AuthorizedKeysCommand none
|
|
|
|
|
#AuthorizedKeysCommandUser nobody
|
|
|
|
|
|
|
|
|
|
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
|
|
|
|
#HostbasedAuthentication no
|
|
|
|
|
# Change to yes if you don't trust ~/.ssh/known_hosts for
|
|
|
|
|
# HostbasedAuthentication
|
|
|
|
|
#IgnoreUserKnownHosts no
|
|
|
|
|
# Don't read the user's ~/.rhosts and ~/.shosts files
|
|
|
|
|
#IgnoreRhosts yes
|
|
|
|
|
|
|
|
|
|
# To disable tunneled clear text passwords, change to no here!
|
|
|
|
|
PasswordAuthentication no
|
|
|
|
|
PermitEmptyPasswords no
|
|
|
|
|
|
|
|
|
|
AllowUsers ahmza
|
|
|
|
|
|
|
|
|
|
# Change to yes to enable challenge-response passwords (beware issues with
|
|
|
|
|
# some PAM modules and threads)
|
|
|
|
|
ChallengeResponseAuthentication no
|
|
|
|
|
|
|
|
|
|
# Kerberos options
|
|
|
|
|
#KerberosAuthentication no
|
|
|
|
|
#KerberosOrLocalPasswd yes
|
|
|
|
|
#KerberosTicketCleanup yes
|
|
|
|
|
#KerberosGetAFSToken no
|
|
|
|
|
|
|
|
|
|
# GSSAPI options
|
|
|
|
|
#GSSAPIAuthentication no
|
|
|
|
|
#GSSAPICleanupCredentials yes
|
|
|
|
|
#GSSAPIStrictAcceptorCheck yes
|
|
|
|
|
#GSSAPIKeyExchange no
|
|
|
|
|
|
|
|
|
|
# Set this to 'yes' to enable PAM authentication, account processing,
|
|
|
|
|
# and session processing. If this is enabled, PAM authentication will
|
|
|
|
|
# be allowed through the ChallengeResponseAuthentication and
|
|
|
|
|
# PasswordAuthentication. Depending on your PAM configuration,
|
|
|
|
|
# PAM authentication via ChallengeResponseAuthentication may bypass
|
|
|
|
|
# the setting of "PermitRootLogin without-password".
|
|
|
|
|
# If you just want the PAM account and session checks to run without
|
|
|
|
|
# PAM authentication, then enable this but set PasswordAuthentication
|
|
|
|
|
# and ChallengeResponseAuthentication to 'no'.
|
|
|
|
|
UsePAM yes
|
|
|
|
|
|
|
|
|
|
#AllowAgentForwarding yes
|
|
|
|
|
#AllowTcpForwarding yes
|
|
|
|
|
#GatewayPorts no
|
|
|
|
|
X11Forwarding yes
|
|
|
|
|
#X11DisplayOffset 10
|
|
|
|
|
#X11UseLocalhost yes
|
|
|
|
|
#PermitTTY yes
|
|
|
|
|
PrintMotd no
|
|
|
|
|
#PrintLastLog yes
|
|
|
|
|
#TCPKeepAlive yes
|
|
|
|
|
#PermitUserEnvironment no
|
|
|
|
|
#Compression delayed
|
|
|
|
|
ClientAliveInterval 180
|
|
|
|
|
#ClientAliveCountMax 3
|
|
|
|
|
#UseDNS no
|
|
|
|
|
#PidFile /var/run/sshd.pid
|
|
|
|
|
#MaxStartups 10:30:100
|
|
|
|
|
#PermitTunnel no
|
|
|
|
|
#ChrootDirectory none
|
|
|
|
|
#VersionAddendum none
|
|
|
|
|
|
|
|
|
|
# no default banner path
|
|
|
|
|
#Banner none
|
|
|
|
|
|
|
|
|
|
# Allow client to pass locale environment variables
|
|
|
|
|
AcceptEnv LANG LC_*
|
|
|
|
|
|
|
|
|
|
# override default of no subsystems
|
|
|
|
|
Subsystem sftp /usr/lib/openssh/sftp-server
|
|
|
|
|
|
|
|
|
|
# Example of overriding settings on a per-user basis
|
|
|
|
|
#Match User anoncvs
|
|
|
|
|
# X11Forwarding no
|
|
|
|
|
# AllowTcpForwarding no
|
|
|
|
|
# PermitTTY no
|
|
|
|
|
# ForceCommand cvs server
|
|
|
|
|
```
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
**Now lets explain what we just did**
|
|
|
|
|
* **Protocol 2** - released in 2006, SSH2 introduced improved
|
|
|
|
|
encryption algorithms.
|
|
|
|
|
* **Port 2222** - The port number can be whatever number you want.
|
|
|
|
|
Choose something other than 22 this will help hide your device from malicious actors
|
|
|
|
|
* **PermitRootLogin no** - If the root account were to be compromised
|
|
|
|
|
then the attacker has full control of the system so we stop it from being able to log in.
|
|
|
|
|
* **MaxAuthTries 5** - After 5 failed attempts the remote host blocks
|
|
|
|
|
requests from that IP for a period of time.
|
|
|
|
|
* **PasswordAuthentication no** - We have the SSH key installed so we
|
|
|
|
|
no longer need to have password authentication.
|
|
|
|
|
* **PermitEmptyPasswords no** - We don't want to allow empty passwords
|
|
|
|
|
to be used as authentication for obvious reasons.
|
|
|
|
|
* **AllowUsers username** - Add the usernames of users you want to be
|
|
|
|
|
able to connect to the remote host and other users trying to connect
|
|
|
|
|
will be dropped.
|
|
|
|
|
* **Client Alive Interval 180** - Drop the connection after a certain
|
|
|
|
|
period of inactivity
|
|
|
|
|
|
|
|
|
|
## **Check were able to connect**
|
|
|
|
|
restart sshd service
|
|
|
|
|
``` bash
|
|
|
|
|
sudo systemctl restart sshd
|
|
|
|
|
```
|
|
|
|
|
**Keep the current SSH connection open** and create a new session.
|
|
|
|
|
|
|
|
|
|
If you are able to connect to the remote hosts then you are all set. If
|
|
|
|
|
not then you still have the initial connection to the remote host to
|
|
|
|
|
roll back the changes and troubleshoot.
|
|
|
|
|
|
|
|
|
|
# **Success**
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
# **Setting up** ***Fail2Ban***
|
|
|
|
|
_Fail2Ban_ is an intrusion prevention tool. Although we are slowing
|
|
|
|
|
bots down with MaxAuthTries the attacker is still able to carry on
|
|
|
|
|
brute forcing. Which is what Fail2Ban is for, it actually blocks the
|
|
|
|
|
connections from that IP.
|
|
|
|
|
|
|
|
|
|
## **Install** ***Fail2Ban***
|
|
|
|
|
**We will install Fail2Ban on the remote host**
|
|
|
|
|
First upgrade any packages, then **install** ***Fail2Ban***
|
|
|
|
|
``` bash
|
|
|
|
|
sudo apt update && sudo apt upgrade
|
|
|
|
|
sudo apt install fail2ban
|
|
|
|
|
```
|
|
|
|
|
Now we need to enable the service so it starts when the remote host
|
|
|
|
|
starts
|
|
|
|
|
``` bash
|
|
|
|
|
sudo systemctl enable --now fail2ban
|
|
|
|
|
```
|
|
|
|
|
## **Configure** ***Fail2Ban***
|
|
|
|
|
The Fail2Ban config file we want to edit is called **jail.local** located in **/etc/fail2ban/**
|
|
|
|
|
open jail.local in your editor of choice
|
|
|
|
|
``` bash
|
|
|
|
|
sudo vim /etc/fail2ban/jail.local
|
|
|
|
|
```
|
|
|
|
|
The config for _Fail2Ban_ is a lot shorter than sshd so this should be
|
|
|
|
|
quick
|
|
|
|
|
```
|
|
|
|
|
[DEFAULT]
|
|
|
|
|
bantime = 8h
|
|
|
|
|
ignoreip = 127.0.0.1 <ip addresses to be ignored>
|
|
|
|
|
ignoreself = true
|
|
|
|
|
|
|
|
|
|
[sshd]
|
|
|
|
|
enabled = true
|
|
|
|
|
port = 2222
|
|
|
|
|
filter = sshd
|
|
|
|
|
logpath = /var/log/auth.log
|
|
|
|
|
maxretry = 3
|
|
|
|
|
findtime = 10m
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**[Default]** - Settings in here apply to all jails
|
|
|
|
|
|
|
|
|
|
* **bantime** - how long the ban will last
|
|
|
|
|
* **ignoreip** - IP addresses to ignore
|
|
|
|
|
* **ignoreself** - stops from locking itself out
|
|
|
|
|
|
|
|
|
|
**[sshd]** - this is the jail for sshd
|
|
|
|
|
|
|
|
|
|
* **enabled** - decides weather the jail is active or not
|
|
|
|
|
* **port** - the port number the service
|
|
|
|
|
* **filter** - tells the jail which filter to use from /etc/fail2ban/filter.d
|
|
|
|
|
* **logpath** - where the log you want fail2ban to read is
|
|
|
|
|
* **maxretry** - Times the client can attempt a login before being banned
|
|
|
|
|
* **findtime** - An amount of time which maxretry must occur to trigger a
|
|
|
|
|
ban for example in 10 minutes if 3 failed login attempts are made the
|
|
|
|
|
ban the IP
|
|
|
|
|
|
|
|
|
|
**Restart** ***Fail2Ban*** to load the configuration
|
|
|
|
|
``` bash
|
|
|
|
|
sudo systemctl restart fail2ban
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## **Testing** ***Fail2Ban***
|
|
|
|
|
To test Fail2Ban lets create a test user and set a password for the
|
|
|
|
|
user
|
|
|
|
|
``` bash
|
|
|
|
|
sudo useradd test
|
|
|
|
|
sudo passwd test
|
|
|
|
|
```
|
|
|
|
|
**open the sshd config**
|
|
|
|
|
``` bash
|
|
|
|
|
sudo vim /etc/ssh/sshd_config
|
|
|
|
|
```
|
|
|
|
|
modify the line **PasswordAuthentication** to say **yes** and add the test user to **AllowUsers**
|
|
|
|
|
``` bash
|
|
|
|
|
PasswordAuthentication yes
|
|
|
|
|
AllowUsers user test
|
|
|
|
|
```
|
|
|
|
|
**restart the sshd service**
|
|
|
|
|
``` bash
|
|
|
|
|
sudo systemctl restart sshd
|
|
|
|
|
```
|
|
|
|
|
Attempt to login to the remote host using the test account using an
|
|
|
|
|
incorrect password. After 3 failed attempts it should say connection
|
|
|
|
|
refused.
|
|
|
|
|
``` bash
|
|
|
|
|
ssh test@host -p 2222
|
|
|
|
|
```
|
|
|
|
|
_Fail2Ban_ should do something along the lines of ...
|
|
|
|
|

|
|
|
|
|
log back in as your normal user, remove the test user and restore the
|
|
|
|
|
sshd config.
|
|
|
|
|
|
|
|
|
|
**To remove the user**
|
|
|
|
|
``` bash
|
|
|
|
|
sudo userdel test
|
|
|
|
|
```
|
|
|
|
|
**restore the /etc/ssh/sshd_config file**
|
|
|
|
|
``` bash
|
|
|
|
|
sudo vim /etc/ssh/sshd_config
|
|
|
|
|
```
|
|
|
|
|
Set **PasswordAuthentication** back to **no** and remove test from **AllowUsers**
|
|
|
|
|
``` bash
|
|
|
|
|
PasswordAuthentication no
|
|
|
|
|
AllowUsers user
|
|
|
|
|
```
|
|
|
|
|
# **Conclusion**
|
|
|
|
|
well done, you managed to make it through all that !! At least now you
|
|
|
|
|
can be reassured that if them pesky brute-force attackers decide to
|
|
|
|
|
target your machine they wont have a fun time being in Jail 🤣 sorry
|
|
|
|
|
bad joke.
|
|
|
|
|
|
|
|
|
|
By now you have managed to setup an ssh key for a client and copy it to
|
|
|
|
|
a remote host, re-configure the sshd config to lockdown authentication
|
|
|
|
|
and last but not least install and configure Fail2Ban to block pesky
|
|
|
|
|
attackers.
|
|
|
|
|
|
|
|
|
|

|