“Die einzige Konstante ist die Veränderung.”
Heraclitus
Old dog new tricks
Things you might not know about openssh
Created by Marcus Rückert or just darix ;)
Über mich
SUSE Nutzer seit 5.1
Bei SUSE seit 2005-06
Packager, Reviewer, Admin
SUSE und openSUSE Infrastruktur
Konventionen
Alle Optionen sind jeweils eine Zeile. Bei einem Beispiel wie dem folgendem, einfach alle Backslash und nachfolgenden Zeilenmbrüche entfernen. Aus ...
# /etc/ssh/ssh_config || ~/.ssh/config
SomeOption somevalue, \
anothervalue
... wird ...
# /etc/ssh/ssh_config || ~/.ssh/config
SomeOption somevalue,anothervalue
Kommentare am Anfang der Codeblöcke zeigen in welcher Datei die Optionen benutzt werden koennen, Im Beispiel kann die Option entweder in /etc/ssh/ssh_config
oder ~/.ssh/config
benutzt werden.
Der SSH Client hat eine Konfigurationsdatei?
Unser Problem
Für die openSUSE VMs benutzen wir SSH Weiterleitungen mit xinetd . Damit haben wir aber viele SSH Verbindungen auf nicht Standardports wie:
ssh -p 1234 root@proxyhost.example.com
Besonders nervig ist dass scp
für das selbe eine andere Option benutzt:
scp -P 1234 somefile root@proxyhost.example.com:
Das muß einfacher gehen
# ~/.ssh/config
Host myvm
Port 1234
User root
Hostname proxyhost.example.com
ssh myvm
Die Zeiten ändern sich
Punkte, die wir vielleicht überdenken sollten
1024 bit keys
DSA
NIST Kurven
SHA1
MD5
RC4
Key Exchange Protocols
ECDH Kurven
curve25519-sha256: ECDH over Curve25519 with SHA2
diffie-hellman-group1-sha1: 1024 bit DH with SHA1
diffie-hellman-group14-sha1: 2048 bit DH with SHA1
diffie-hellman-group-exchange-sha1: Custom DH with SHA1
diffie-hellman-group-exchange-sha256: Custom DH with SHA2
ecdh-sha2-nistp256: ECDH over NIST P-256 with SHA2
ecdh-sha2-nistp384: ECDH over NIST P-384 with SHA2
ecdh-sha2-nistp521: ECDH over NIST P-521 with SHA2
Key Exchange Protocols
Können es noch ein paar Bit mehr sein?
curve25519-sha256: ECDH over Curve25519 with SHA2
diffie-hellman-group1-sha1: 1024 bit DH with SHA1
diffie-hellman-group14-sha1: 2048 bit DH with SHA1
diffie-hellman-group-exchange-sha1: Custom DH with SHA1
diffie-hellman-group-exchange-sha256: Custom DH with SHA2
ecdh-sha2-nistp256: ECDH over NIST P-256 with SHA2
ecdh-sha2-nistp384: ECDH over NIST P-384 with SHA2
ecdh-sha2-nistp521: ECDH over NIST P-521 with SHA2
This eliminates 2 because the NSA has supercomputers and possibly unknown attacks. 1024 bits simply don’t offer sufficient security margin.
Key Exchange Protocols
Guter Hash? Schlechter Hash?
curve25519-sha256: ECDH over Curve25519 with SHA2
diffie-hellman-group1-sha1: 1024 bit DH with SHA1
diffie-hellman-group14-sha1: 2048 bit DH with SHA1
diffie-hellman-group-exchange-sha1: Custom DH with SHA1
diffie-hellman-group-exchange-sha256: Custom DH with SHA2
ecdh-sha2-nistp256: ECDH over NIST P-256 with SHA2
ecdh-sha2-nistp384: ECDH over NIST P-384 with SHA2
ecdh-sha2-nistp521: ECDH over NIST P-521 with SHA2
This eliminates 2-4 because SHA1 is broken. We don’t have to wait for a second preimage attack that takes 10 minutes on a cellphone to disable it right now.
Key Exchange Protocols - Fazit
Am Ende bleiben uns curve25519-sha256 und diffie-hellman-group-exchange-sha256.
curve25519-sha256 ist das bessere Protokol und in einer idealen Welt wir würden nur noch das unterstützen. Um Tools wie (with Eclipse, WinSCP) nicht auszuschließen, könnnen wir diffie-hellman-group-exchange-sha256 auch unterstützen.
Key Exchange Protocols - empfohlene Konfiguration
# /etc/ssh/sshd_config
KexAlgorithms curve25519-sha256@libssh.org, \
diffie-hellman-group-exchange-sha256
# /etc/ssh/ssh_config || ~/.ssh/config
Host *
KexAlgorithms curve25519-sha256@libssh.org, \
diffie-hellman-group-exchange-sha256
Authentifizierung
Auf dem Server
Kein SSH1 mehr. Keine DSA Schlüssel. Falls noch nicht geschehen ED25519 anschalten.
# /etc/ssh/sshd_config
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
# /etc/ssh/sshd_config
AuthenticationMethods publickey,password publickey,keyboard-interactive
ED25519 openssl > 1
ssh-keygen -A
Authentifizierung
Auf dem Client
# /etc/ssh/ssh_config || ~/.ssh/config
Host *
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com, \
ssh-rsa-cert-v01@openssh.com, \
ssh-rsa-cert-v00@openssh.com, \
ssh-ed25519,ssh-rsa
Symmetric Ciphers
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
arcfour
arcfour128
arcfour256
blowfish-cbc
cast128-cbc
chacha20-poly1305@openssh.com
Symmetric Ciphers
Sicherheit
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
arcfour
arcfour128
arcfour256
blowfish-cbc
cast128-cbc
chacha20-poly1305@openssh.com
This eliminates 1 and 10-12 - both DES and RC4 are broken. Again, no need to wait for them to become even weaker, disable them now.
Symmetric Ciphers
Schlüssellänge und Blockgröße
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
arcfour
arcfour128
arcfour256
blowfish-cbc
cast128-cbc
chacha20-poly1305@openssh.com
This eliminates 14 because CAST has a 64 bit block size.
Symmetric Ciphers
Cipher modes
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
arcfour
arcfour128
arcfour256
blowfish-cbc
cast128-cbc
chacha20-poly1305@openssh.com
The recommended approach here is to prefer AE modes and optionally allow CTR for compatibility. CTR with Encrypt-then-MAC is provably secure..
Symmetric Ciphers - Fazit
Chacha20-poly1305 is preferred over AES-GCM because the SSH protocol does not encrypt message sizes when GCM (or EtM) is in use.
This allows some traffic analysis even without decrypting the data.
We will deal with that soon.
# /etc/ssh/sshd_config
Ciphers chacha20-poly1305@openssh.com, \
aes256-gcm@openssh.com, \
aes128-gcm@openssh.com, \
aes256-ctr,aes192-ctr,aes128-ctr
# /etc/ssh/ssh_config || ~/.ssh/config
Host *
Ciphers chacha20-poly1305@openssh.com, \
aes256-gcm@openssh.com, \
aes128-gcm@openssh.com, \
aes256-ctr,aes192-ctr,aes128-ctr
Message Authentication Codes
Encrypt-then-MAC : encrypt the message, then attach the MAC of the ciphertext.
MAC-then-encrypt : attach the MAC of the plaintext, then encrypt everything. (TLS)
Encrypt-and-MAC : encrypt the message, then attach the MAC of the plaintext. (SSH)
use Encrypt-then-MAC
Using MAC-then-encrypt have lead to many attacks on TLS while Encrypt-and-MAC have lead to not quite that many attacks on SSH.
the more you fiddle with an attacker provided message,
the more chance the attacker has to gain information through side channels.
In case of Encrypt-then-MAC, the MAC is verified and if incorrect, discarded. Boom, one step, no timing channels.
In case of MAC-then-encrypt, first the attacker provided message has to be decrypted and only then can you verify it.
Decryption failure (due to invalid CBC padding for example) may take less time than verification failure.
Encrypt-and-MAC also has to be decrypted first, leading to the same kind of potential side channels.
It’s even worse because no one said that a MAC’s output can’t leak what its input was. SSH by default, uses this method.
Available Message Authentication Codes
hmac-md5
hmac-md5-96
hmac-ripemd160
hmac-sha1
hmac-sha1-96
hmac-sha2-256
hmac-sha2-512
umac-64
umac-128
hmac-md5-etm@openssh.com
hmac-md5-96-etm@openssh.com
hmac-ripemd160-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-sha2-256-etm@openssh.com
hmac-sha2-512-etm@openssh.com
umac-64-etm@openssh.com
umac-128-etm@openssh.com
Message Authentication Codes
Sicherheit der Hashfunktion
hmac-md5
hmac-md5-96
hmac-ripemd160
hmac-sha1
hmac-sha1-96
hmac-sha2-256
hmac-sha2-512
umac-64
umac-128
hmac-md5-etm@openssh.com
hmac-md5-96-etm@openssh.com
hmac-ripemd160-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-sha2-256-etm@openssh.com
hmac-sha2-512-etm@openssh.com
umac-64-etm@openssh.com
umac-128-etm@openssh.com
No MD5 and SHA1. Yes, I know that HMAC-SHA1 does not need collision resistance but why wait? Disable weak crypto today.
Message Authentication Codes
Schlüssellänge und Größe des Tags
hmac-md5
hmac-md5-96
hmac-ripemd160
hmac-sha1
hmac-sha1-96
hmac-sha2-256
hmac-sha2-512
umac-64
umac-128
hmac-md5-etm@openssh.com
hmac-md5-96-etm@openssh.com
hmac-ripemd160-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-sha2-256-etm@openssh.com
hmac-sha2-512-etm@openssh.com
umac-64-etm@openssh.com
umac-128-etm@openssh.com
Tag size At least 128 bits. This eliminates umac-64-etm.
Message Authentication Codes - Fazit
# /etc/ssh/sshd_config
MACs hmac-sha2-512-etm@openssh.com, \
hmac-sha2-256-etm@openssh.com, \
hmac-ripemd160-etm@openssh.com, \
umac-128-etm@openssh.com, \
hmac-sha2-512,hmac-sha2-256, \
hmac-ripemd160,umac-128@openssh.com
# /etc/ssh/ssh_config || ~/.ssh/config
Host *
MACs hmac-sha2-512-etm@openssh.com, \
hmac-sha2-256-etm@openssh.com, \
hmac-ripemd160-etm@openssh.com, \
umac-128-etm@openssh.com, \
hmac-sha2-512,hmac-sha2-256, \
hmac-ripemd160,umac-128@openssh.com
Die komplette Konfiguration für den Client (openssl >= 1)
# /etc/ssh/ssh_config || ~/.ssh/config
Host *
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-ed25519,ssh-rsa
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
Die komplette Konfiguration für den Client (openssl < 1)
# /etc/ssh/ssh_config || ~/.ssh/config
Host *
KexAlgorithms diffie-hellman-group-exchange-sha256
HostKeyAlgorithms ssh-rsa-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-rsa
Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
Die komplette Konfiguration für den Server (openssl >= 1)
# /etc/ssh/sshd_config
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAuthentication yes
PasswordAuthentication no
# reenable if you want to use OTP together with ssh keys
ChallengeResponseAuthentication no
Die komplette Konfiguration für den Server (openssl < 1)
# /etc/ssh/sshd_config
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
KexAlgorithms diffie-hellman-group-exchange-sha256
Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAuthentication yes
PasswordAuthentication no
# reenable if you want to use OTP together with ssh keys
ChallengeResponseAuthentication no
Kontrolle ist besser
$ ssh -v user@hostname /bin/true
[snip]
debug1: kex: server->client chacha20-poly1305@openssh.com <implicit> none
debug1: kex: client->server chacha20-poly1305@openssh.com <implicit> none
[snip]
debug1: Server host key: ED25519 cf:c0:.... [MD5]
[snip]
Noch mal kurz Key Exchange
# Github needs diffie-hellman-group-exchange-sha1
# some of the time but not always.
Host github.com
KexAlgorithms curve25519-sha256@libssh.org, \
diffie-hellman-group-exchange-sha256, \
diffie-hellman-group-exchange-sha1, \
diffie-hellman-group14-sha1
Public Keys sind für alle
https://github.com/username.keys
SSH Schlüssel erzeugen
ssh-keygen -t ed25519 -o -a 100
ssh-keygen -t rsa -b 4096 -o -a 100
"-o -a 100
" (openssh >= 6.5)
brute force resistant format (-o). When saving a new-format private key (i.e. an ed25519 key or any SSH protocol 2 key when the -o flag is set), this option specifies the number of KDF (key derivation function) rounds used. Higher numbers result in slower passphrase verification and increased resistance to brute-force password cracking (should the keys be stolen).
Ich kenn dich zwar nicht aber ich vertrau dir mal
Benötigt manuelle Überprüfung der Schlüssel/Fingerprints
Mit der Zeit sammelt man eine große Anzahl von Schlüsseln in ~/.ssh/known_hosts
Und falls sich mal die Server- oder Clientkonfiguration ändert werden es noch mehr
Huh ein neuer SSH Key?
Jeder hat schon mal vergessen den SSH Schlüssel zu sichern vor der Neuinstallation
Manchmal will mal sie auch absichtlich austauschen
Nutzer müssen ~/.ssh/known_hosts
manuell pflegen, da nur ein Teil von "ssh-keygen -R
" abgedeckt ist
D.h. wir haben mindestens 2 fehlgeschlagene Verbindungen bei einem ausgetauschten Schlüssel
Schlüssel wechsel dich
Falls man immer dran gedacht hat die Schlüssel zu sichern, genügen die vll nicht mehr aktuellen Standards.
SSL Schlüssel wechseln alle 1-3 Jahre
Key Rotation Support in 6.8+
Das Wechseln von SSH Server Keys sollte nicht nervig sein
Die Nutzerseite - Setup
# ~/.ssh/known_hosts
@cert-authority *.example.com ssh-rsa AAAAB3[...]== Comment
Immer noch ein etwas dass wir ausserhalb des SSH Protokols kommunizieren müssen - aber nur noch einmal
Die Nutzerseite - Das erste Mal
darix@mylaptop:~ $ ssh unknownhost.example.com
darix@unknownhost:~ $
Die Nutzerseite - Lange nicht gesehen
darix@mylaptop:~ $ ssh oldmachinenewkey.example.com
darix@oldmachinenewkey:~ $
So sollte es immer sein oder?
Magie? nicht wirklich
ssh-keygen -f host_ca
cat host_ca.pub
ssh-keygen -s host_ca -I 'host:unknownhost.example.com' -h \
-n unknownhost.example.com -V +52w \
unknownhost.example.com_ssh_host_rsa_key.pub
scp unknownhost.example.com_ssh_host_rsa_key-cert.pub \
root@unknownhost.example.com:/etc/ssh/ssh_host_rsa_key-cert.pub
# /etc/ssh/sshd_config
HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
Und das ganze für alle anderen Schlüsseltypen (DSA, ED25519)
SSH Server Konfiguration neuladen
Und wo sind die Nachteile?
Beim Verbinden muß der volle Hostname benutzt werden
Zertifikate mit Ablaufzeit brauchen Monitoring/zeitnahen Austausch
Hostnamen sind im Zertifikat verdrahtet
Neuer CNAME, Neues Zertifikat
Theoretisch kann man den Hostname auch weglassen (MITM-Gefahr)
fullhostname workaround with ~/.ssh/config (Hostname)
Always lock down hostnames in cert to avoid MITM
Schlüsselaustausch - Der Anfang
SSH Certificate Authority aufsetzen
Aktuelle Schlüssel einsammeln und signieren
Zertifikate auf alle Server ausrollen
Kommunikation des öffentlichen Schlüssels an alle Nutzer.
Schlüsselaustausch - Jetzt richtig
Neue signierte Schlüsselpaare für alle Server erstellen und ausrollen
Nutzersicht:
Ein Nutzer der unseren Empfehlungen gefolgt ist?
Merkt nix. Alles funktioniert weiter.
Der Rest ...
... sieht ganz viele Warnungen wegen ausgetauschten Schlüsseln
~/.ssh/authorized_keys
Funktioniert im Prinzip
Wie blocke ich den SSH Schlüssel eines ehemaligen Mitarbeiters?
Wie verhindere ich dass ein Nutzer anderen Nutzern Zugang gibt?
If you manage to compromise the ~/.ssh/authorized_keys file, you can elevate what you can do. A global authorized_keys file makes this harder.
Wieder keine Magie nötig
ssh-keygen -f user_ca
scp user_ca.pub root@somehost.example.com:/etc/ssh/user_ca.pub
# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/user_ca.pub
SSH Server Konfiguration neuladen
ssh-keygen -s user_ca -I user_darix \
-n darix,root -V +52w darix_id_rsa.pub
Im Zweifel das ganze noch für die anderen Schlüsseltypen (DSA, ED25519)
scp darix_id_*-cert.pub darix@mylaptop.example.com:.ssh/
Was ändert sich?
ssh -i ~/.ssh/id_25519.pub somehost.example.com
sshd[10219]: Accepted publickey for darix from 1.2.3.4 port 39190 \
ssh2: ED25519 b4:3d:... [MD5]
ssh -i ~/.ssh/id_25519-cert.pub somehost.example.com
sshd[10241]: Accepted publickey for darix from 1.2.3.4 port 39194 \
ssh2: ED25519-CERT ID user_darix (serial 0) CA RSA 58:5a:... [MD5]
ssh -i ~/.ssh/id_25519-cert.pub nobody@somehost.example.com
sshd[6377]: error: Certificate invalid: name is not a listed principal
Logging format requires newer openssh (6.6 verified)
Du kommst hier nicht rein
ssh-keygen -k -f /etc/ssh/revoke.crl darix_id_rsa.pub
ssh-keygen -ku -f /etc/ssh/revoke.crl darix_id_ed25519.pub
# /etc/ssh/sshd_config
RevokedKeys /etc/ssh/revoke.crl
ansible all -m copy \
-a 'src=/etc/ssh/revoke.crl dest=/etc/ssh/revoke.crl'
sshd[11462]: error: WARNING: authentication attempt with a revoked \
RSA key 99:41... [MD5]
sshd[11462]: error: WARNING: authentication attempt with a revoked \
RSA-CERT key 99:41... [MD5]
Da war noch was
TrustedUserCAKeys funktioniert nur wenn man die Nutzernamen im Zertifikat einträgt (-n [listofusernames])
Man kann Clientzertifikate auch mit ~/.ssh/authorized_key
benutzen
Empfehlung: Wenn möglich authorized_keys deaktivieren in sshd_config
Alle Optionen verfügbar in authorized_keys können auch beim Erstellen eines Clientzertifikates angegeben werden.
Um zu sehen was ein Clientzertifikat erlaubt:
ssh-keygen -L -f id_25519-cert.pub
With authorized_keys you dont have to lock down the users with "-n [listofusernames]"
Thank you for flying with openSUSE