Sichere SSH Konfiguration

In diesem Beitrag erläutere ich meine SSH Konfiguration für Server und Clients. Ich erkläre außerdem wie man sie einrichtet. Sie schränkt die erlaubten kryptographischen Algorithmen auf als sicher geltende ein. Meine Auswahl der Algorithmen basiert auf dem Artikel Secure Secure Shell.

Ich beschreibe zuerst die verschiedenen verwendeten Optionen und wie man sie Konfiguriert. Am Ende habe ich nochmal die kompletten Konfigurationsdateien zum einfachen kopieren eingefügt.

Bei der Konfiguration muss extrem vorsichtig vorgegangen werden, da man sich u.U. auch komplett vom Server aussperren kann. Ich übernehme dafür keine Haftung.

Server

Starten wir mit der Serverkonfiguration, welche in der Datei /etc/ssh/sshd_config hinterlegt ist. Ich erläutere zuerst die einzelnen Optionen und beschreibe welche Konfiguration außerhalb der Konfigurationsdatei notwendig ist. Am Ende des Beitrages habe ich nochmals die komplette Server-Konfiguration eingefügt und beschreibe auch wie diese geladen werden kann.

Der SSH Server hört standardmäßig auf Port 22, was ich auch so belassen habe. Falls ein Server mehrere IP-Adressen hat, kann mit ListenAddress eingeschränkt werden auf welchen IP-Adresse der SSH Server eine Verbindung akzeptieren soll.

# Port to listen on
Port 22

# IP to listen on
#ListenAddress ::
#ListenAddress 0.0.0.0

KexAlgorithms schränkt die erlaubten Algorithmen für einen Schlüsseltausch ein. Ich erlaube hier nur ed25519 als Algorithmus, die Begründung hierfür findet sich im oben verlinkten Artikel.

# Allow only secure key exchange algorithms
KexAlgorithms curve25519-sha256@libssh.org

Protocol 2 bedeutet, dass nur die neuere SSH Version verwendet werden soll und nicht die unsichere Version 1. HostKey definiert welche Schlüssel bzw. Algorithmen der Server für die Authentifizierung verwenden soll – hier ed25519 und RSA. Die Begründung für meine Auswahl befindet sich wieder im verlinkten Artikel.

# Allow only SSH version 2
Protocol 2

# Allow only secure server authentication algorithms
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

Um diese Algorithmen zu verwenden löschen wir zuerst alle vorhandenen Host Schlüssel vom Server. Anschließend generieren wir neue – mit ausreichender Länge für RSA.

$ cd /etc/ssh/
$ sudo rm ssh_host_*key*
$ sudo ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" < /dev/null
Generating public/private ed25519 key pair.
Your identification has been saved in ssh_host_ed25519_key
Your public key has been saved in ssh_host_ed25519_key.pub
The key fingerprint is:
SHA256:NyxgQMDgtQcMCrMMWlAgCbbexBefl562QVo2xL62pNg root@server
The key's randomart image is:
+--[ED25519 256]--+
|@X*=o.  ..       |
|@+=.o.o o..      |
|++ + ooo.B       |
|. o o. .Boo      |
| . .   .S==      |
|        .*o.     |
|      o +..      |
|     . E .       |
|                 |
+----[SHA256]-----+
$ sudo ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key -N "" < /dev/null
Generating public/private rsa key pair.
Your identification has been saved in ssh_host_rsa_key
Your public key has been saved in ssh_host_rsa_key.pub
The key fingerprint is:
SHA256:js+jmapYIhg4QA5PeMQa96PIrBPEWYPNVs2HzrjYNMI root@server
The key's randomart image is:
+---[RSA 4096]----+
|.=* ..o .        |
|*++*   + .       |
|o**.. + .        |
|++ Eo+ o         |
|B. .=.o S        |
|+=.. o o         |
|=..   . .        |
|++     =.        |
|......+.o.       |
+----[SHA256]-----+

Bitte beachtet, dass sich durch den letzten Schritt die HostKeys des Servers ändern. Ihr bekommt somit eine Warnung, wenn ihr euch das nächste Mal mit dem Server verbindet, dass sich der Host Key des Servers geändert hat. Um diesen überprüfen zu können berechnen wir nun den Hash der ed25519 und RSA Keys und notieren diese.

$ ssh-keygen -lf ssh_host_ed25519_key.pub
256 SHA256:NyxgQMDgtQcMCrMMWlAgCbbexBefl562QVo2xL62pNg user@host (ED25519)
$ ssh-keygen -lf ssh_host_rsa_key.pub
4096 SHA256:js+jmapYIhg4QA5PeMQa96PIrBPEWYPNVs2HzrjYNMI user@host (RSA)

Auf älteren Systemen wie Debian Jessie wird der Hash als md5 ausgegeben. Um beim erneuten Verbinden den HostKey vergleichen können wird aber der SHA256 Hash benötigt. Der Hash kann in diesem Falle auch mit nachfolgendem Befehl berechnet werden – Das „=“ am Ende der Ausgabe kann ignoriert werden.

$ awk '{print $2}' ssh_host_ed25519_key.pub | base64 -d | sha256sum -b | awk '{print $1}' | xxd -r -p | base64
zD+K1cChDUaxA/d1bv6ok8b2rACe2DiiwJO6wspWBik=
$ awk '{print $2}' ssh_host_rsa_key.pub | base64 -d | sha256sum -b | awk '{print $1}' | xxd -r -p | base64
Fp+MTtblJoPBAStfnpJ8JBeGWJhW1foHoOKpkSmeMws=

Beim nächsten Verbinden wird folgende Warnung angezeigt, dass sich der Host Key des Servers geändert hat.

$ ssh user@host
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    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.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:NyxgQMDgtQcMCrMMWlAgCbbexBefl562QVo2xL62pNg.
Please contact your system administrator.
Add correct host key in /home/user/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /home/user/.ssh/known_hosts:1
  remove with:
  ssh-keygen -f "/home/user/.ssh/known_hosts" -R host
ED25519 host key for host has changed and you have requested strict checking.
Host key verification failed.

Der alte Host Key kann mit dem in der Warnung angezeigten Befehl einfach gelöscht werden.

$ ssh-keygen -f "/home/user/.ssh/known_hosts" -R host
# Host host found: line 1
/home/user/.ssh/known_hosts updated.
Original contents retained as /home/user/.ssh/known_hosts.old

Beim erneuten Verbinden wird nun nachgefragt ob der neue Key akzeptiert werden soll. Bevor dies bestätigt wird sollte geprüft werden, ob der angezeigte Hashwert mit dem notierten des neuen Keys übereinstimmt.

$ ssh user@host
The authenticity of host 'host (xxx.xxx.xxx.xxx)' can't be established.
ED25519 key fingerprint is SHA256:NyxgQMDgtQcMCrMMWlAgCbbexBefl562QVo2xL62pNg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'host' (ED25519) to the list of known hosts.

Aus Sicherheitsgründen sollte es für Clients nur erlaubt sein sich mittels Public-Key Authentication anzumelden und nicht mittels Passwörter.

# Allow only public key authentication
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

Es ist sinnvoll nur den Benutzern eine SSH Verbindung zu erlauben die dies auch benötigen. AllowGroups erlaubt nur Benutzern dieser Gruppe eine Verbindung über SSH.

# Only allow SSH for users member of group ssh-user
AllowGroups ssh-user

Dazu muss die Gruppe erstellt und anschließend alle Benutzer welche Zugriff erhalten sollen hinzugefügt werden.

$ sudo groupadd ssh-user
$ sudo usermod -a -G ssh-user <username>

Wenn ein Benutzer keinen Zugriff mehr haben soll muss er natürlich aus der Gruppe gelöscht werden. Dies kann mit nachfolgendem Befehl erledigt werden.

$ sudo deluser <username> ssh-user

Als nächstes werden die erlaubten symmetrischen kryptographischen (Ciphers) sowie MAC (MACs) Algorithmen aufgelistet. Meine Auswahl basiert auch hier wieder auf der im verlinkten Artikel weiter oben.

# Allow only secure symmetric ciphers
Ciphers chacha20-poly1305@openssh.com

# Allow only secure message authentication codes
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

Die nachfolgenden Parameter sind meist in der Standardkonfiguration vorhanden. Ich habe allerdings X11Forwarding deaktiviert, da ich es nicht nutze. PermitRootLogin prohibit-password sagt, dass sich root nicht über ein Passwort anmelden darf. Die Option prohibit-password wurde mit OpenSSH 7.0 eingeführt. Für Distributionen welche eine ältere Version nutzen (wie z.B. Debian Jessie oder Raspbian, welches auf Debian Jessie basiert) muss die alternative Option without-password verwendet werden. Sie hat die gleiche Funktionalität.

# Use Privilege Separation for security reasons
UsePrivilegeSeparation yes

# Logging
SyslogFacility AUTH
LogLevel INFO

# Time to wait for complete login
LoginGraceTime 120

# Allow root logins only with public-keys
PermitRootLogin prohibit-password

# Enhance security
StrictModes yes

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes

# Disable host based authentication
HostbasedAuthentication no

# Disable empty passwords
PermitEmptyPasswords no

# Disable X11 Forwarding
X11Forwarding no

# Print last login
PrintLastLog yes

# Do not print the message of the day
PrintMotd no

# Keep session alive
TCPKeepAlive yes

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# Allow sftp
Subsystem sftp /usr/lib/openssh/sftp-server

# Use PAM to allow mail notification at login
UsePAM yes

Client

Die Konfigurationsdatei auf Clientseite spiegelt die gesetzten Parameter auf Serverseite wieder ist aber kürzer. Sie befindet sich in der Datei /etc/ssh/ssh_config. Ich beschreibe hier wie beim Server die einzelnen Parameter und welche Konfiguration außerhalb der Konfigurationsdatei notwendig ist. Am Ende des Beitrages befindet sich nach der Server-Konfiguration auch eine Kopie der kompletten Client-Konfiguration.

Es erlaubt mittels KexAlgorithms den gleichen Schlüsseltauschalgorithmus wie der Server.

# For all hosts
Host *

# Allow only secure Key Exchange Algorithms
KexAlgorithms curve25519-sha256@libssh.org

Es wird auch nur die Authentifizierung über Public-Keys mit im oben verlinkten Artikel empfohlenen Algorithmen erlaubt.

# Do not allow password authentication
PasswordAuthentication no
ChallengeResponseAuthentication no

# Allow authentication with public keys
PubkeyAuthentication yes
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa

Damit sich der Client mittels Public-Keys beim Server anmelden kann muss er sich vorher einen geeigneten Schlüssel generieren und den öffentlichen Teil dem Server hinterlegen. Wie dies funktioniert habe ich im Artikel SSH Authentifizierung mittels Public-Keys beschrieben.

Die angegebenen Ciphers und MACs spiegeln die auf der Serverseite wieder.

# Allow only secure symmetric ciphers
Ciphers chacha20-poly1305@openssh.com

# Allow only secure MACs
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

Der Zweck der restlichen Optionen ist ungenutzte Features zu deaktivieren, das locale des Clients an den Server zu senden und die bekannten Server zu verschleiern.

# Disable unused features
UseRoaming no

# Pass locale to server
SendEnv LANG LC_*

# Obfuscate known hosts
HashKnownHosts yes

Zur einfacheren Verwaltung von SSH-Verbindungen kann auf Clientseite eine extra Konfigurationsdatei angelegt werden. Wie dies funktioniert beschreibe ich im Artikel Konfigurationsdatei zum Verwalten von SSH Verbindungen.

Konfigurationsdateien

Wenn oben genannte Schritte durchgeführt wurden können die nachfolgenden Konfigurationsdateien auf Client- und Serverseite übernommen werden. Sie sind eine Zusammenfassung der einzelnen Konfigurationsschnipsel. Ich weise hier nochmals darauf hin das man damit sehr vorsichtig sein sollte, da man sich unter Umständen vom Server ausschließen kann.

Server

Die Konfiguration des Servers ist in der Datei /etc/ssh/sshd_config hinterlegt. Nachfolgend meine komplette Konfigurationsdatei.

# Carstens SSH configuration file

# Port to listen on
Port 22

# IP to listen on
#ListenAddress ::
#ListenAddress 0.0.0.0

# Allow only secure key exchange algorithms
KexAlgorithms curve25519-sha256@libssh.org

# Allow only SSH version 2
Protocol 2

# Allow only secure server authentication algorithms
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# Allow only public key authentication
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

# Only allow SSH for users member of group ssh-user
AllowGroups ssh-user

# Allow only secure symmetric ciphers
Ciphers chacha20-poly1305@openssh.com

# Allow only secure message authentication codes
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

# Use Privilege Separation for security reasons
UsePrivilegeSeparation yes

# Logging
SyslogFacility AUTH
LogLevel INFO

# Time to wait for complete login
LoginGraceTime 120

# Allow root logins only with public-keys
PermitRootLogin prohibit-password

# Enhance security
StrictModes yes

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes

# Disable host based authentication
HostbasedAuthentication no

# Disable empty passwords
PermitEmptyPasswords no

# Disable X11 Forwarding
X11Forwarding no

# Print last login
PrintLastLog yes

# Do not print the message of the day
PrintMotd no

# Keep session alive
TCPKeepAlive yes

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# Allow sftp
Subsystem sftp /usr/lib/openssh/sftp-server

# Use PAM to allow mail notification at login
UsePAM yes

Damit die Änderungen beim Server wirksam werden muss im Anschluss noch die Konfiguration des ssh Servers neu geladen werden.

$ sudo service ssh reload

Client

Die Konfiguration des Clients ist in der Datei /etc/ssh/ssh_config hinterlegt. Nachfolgend meine komplette Konfigurationsdatei.

# Carstens SSH configuration file

# For all hosts
Host *

# Allow only secure Key Exchange Algorithms
KexAlgorithms curve25519-sha256@libssh.org

# Do not allow password authentication
PasswordAuthentication no
ChallengeResponseAuthentication no

# Allow authentication with public keys
PubkeyAuthentication yes
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa

# Allow only secure symmetric ciphers
Ciphers chacha20-poly1305@openssh.com

# Allow only secure MACs
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

# Disable unused features
UseRoaming no

# Pass locale to server
SendEnv LANG LC_*

# Obfuscate known hosts
HashKnownHosts yes

Sie wird automatisch verwendet, wenn die nächste SSH Verbindung aufgebaut wird.

4 Gedanken zu „Sichere SSH Konfiguration“

  1. Hallo Carsten,

    im Abschnitt „Client“ steht folgender Satz:
    Die Konfiguration des Clients ist in der Datei /etc/ssh/sshd_config hinterlegt.
    Das müsste aber
    Die Konfiguration des Clients ist in der Datei /etc/ssh/ssh_config hinterlegt.
    heißen.

    Danke für die gut Vorlage !
    Stefan Scherer

  2. Hallo Carsten,
    Die MACs hmac-ripemd160-etm@openssh.com und hmac-ripemd160 werden unter Ubuntu LTS 18.04 nicht mehr unterstützt und der SSH Server lässt sich damit nicht restarten. Nachdem ich diese aus der Konfigurations entfernt hat, funktioniert es wunderbar.

    Vielen Dank für diese gute Anleitung.
    Oliver

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert