SSH-Server

Siehe auch

Wichtige Eigenschaften von SSH:

  • Authentifizierung der Gegenstelle.

  • Die symmetrische Verschlüsselung der Datenübertragung mit sitzungsabhängigen Schlüsseln erschwert eine Entschlüsselung der Kommunikation durch Dritte massiv.

  • Manipulation der übertragenen Daten wird verhindert und ermöglicht Datenintegrität.

Änderungen an der Konfiguration des SSH-Servers sollten immer in einer zweiten SSH-Session getestet werden, um ein versehentliches Aussperren zu verhindern. In der ersten SSH-Session also Änderungen vornehmen und den SSH-Daemon neu starten, aber Test der Settings, Login, Logout usw. im zweiten Terminal vornehmen.

SSH-Server härten

Die folgenden Einstellungen lassen sich in der /etc/ssh/sshd_config vornehmen, um die Sicherheit je nach Anforderung weiter zu erhöhen oder den SSH-Server anzupassen. Nach Änderung der Einstellungen muss der SSH-Server neu gestartet werden, was auch bei laufender SSH-Session funktioniert.

AllowTcpForwarding no       # hindert Malware (aber auch alles andere) an Tunneling
ClientAliveCountMax 0       # keine KeepAlive-Messages senden
ClientAliveInterval 300     # 5 Minuten Idle-Timeout, danach Logout
HostbasedAuthentication no  # .rhosts und /etc/hosts.equiv-Dateien abschalten (SSHv2)
IgnoreRhosts yes            # .rhosts und .shosts-Dateien abschalten
LoginGraceTime 60           # Disconnect-Timeout nach erfolglosem Login
LogLevel VERBOSE            # Logging erhöhen (Pflicht für Fail2ban)
MaxAuthTries 3              # Anzahl der erfolglosen Login-Versuche, bis der Server die Verbindung trennt, von 6 auf 2 reduzieren
MaxSessions 4               # wie der Name schon sagt...
MaxStartups 10:30:60        # Maximale Anzahl von Concurrent Unauthorized Connections (start:rate%:full)
PasswordAuthentication no   # Anmeldung per Passwort abschalten
PermitEmptyPasswords no     # keine leeren Passwörter zulassen
PermitRootLogin no          # Login mit root-Rechten abschalten - Achtung, Ersatz-Benutzer sollte bereitstehen
PermitUserEnvironment no    # das Setzen von Environment-Optionen (Pfaden etc.) durch Benutzer verhindern
Port 56669                  # SSH-Port auf 56669 ändern (keine Sicherheit, aber reduziert die Anzahl der Brute-Force SSH-Loginversuche deutlich)
PubkeyAuthentication yes    # Anmeldung per Zertifikat zulassen
UsePAM yes                  # PAM nutzen
X11Forwarding no            # Tunneling von X11-Traffic per sshd-Forwarding verbieten

Wer den SSH-Port ändert, muss dies auch per SELinux erlauben:

yum -y install policycoreutils-python
dnf -y install policycoreutils-python-utils

semanage port --add --type ssh_port_t --proto tcp 56669

Änderungen an Verschlüsselungsoptionen wie Ciphers, MACs oder KexAlgorithms empfehlen wir nicht. Stattdessen sollten hier die systemweite Crypto-Policies konfiguriert werden, die auch vom SSH-Daemon verwendet werden.

Siehe auch

Benutzerzugriff auf SSH steuern

per TCP-Wrapper

Der Zugriff auf den SSH-Daemon lässt sich mittels /etc/hosts.allow und /etc/hosts.deny steuern, den sogenannten TCP Wrappers-Dateien. Der Servicename zur Steuerung lautet hier sshd. Soll der SSH-Service nur aus der Domäne linuxfabrik.ch erreichbar sein, trägt man in der /etc/hosts.deny ein:

sshd:ALL EXCEPT .linuxfabrik.ch

Die Datei /etc/hosts.allow wird zuerst gelesen. Wird kein passender Match gefunden, kommt die /etc/hosts.deny zur Anwendung. Wird wieder kein passender Match gefunden, wird der Zugriff gewährt. Die Dateien lassen sich auch einzeln entfernen.

Weil es einfacher und sehr effektiv ist, empfehlen wir, nur die Allow-Liste zu pflegen und allen anderen in der Deny-Liste den Zugriff zu entziehen.

per /etc/sshd/sshd_config
/etc/ssh/sshd_config
AllowUsers root linus@host
AllowGroups ...
DenyUsers ...
DenyGroups ...
per /etc/passwd

Um den Benutzer linus auszuschliessen, kann man diesem auf dem SSH-Host auch den Shell-Zugriff entziehen:

usermod --shell=/bin/false linus

Tipp

Es ist allgemein empfohlen, den SSH-Zugang für root abzuschalten (PermitRootLogin no). In so einem Fall erstellt man sich einen Standard-Benutzer, packt diesen in die wheel-Gruppe, loggt sich mit diesem über SSH ein, arbeitet mit sudo oder wechselt mit su - in die root-Shell.

SFTP

Es gibt des öfteren die Anforderung, einen möglichst sicheren SFTP-Server aufzusetzen. Die SFTP-Benutzer sollen dabei ausschliesslich SSH-Keys verwenden, keine interaktive Shell per SSH öffnen und ihr SFTP-Verzeichnis auch nicht verlassen dürfen. Alle anderen SSH-Logins sollen von diesen Einschränkungen nicht betroffen sein. Aus Admin-Sicht soll das ganze möglichst auch ohne Zusatzsoftware wie VSFTP oder andere auskommen, sondern mit dem SSH-Daemon umgesetzt werden.

Geht. Zunächst sicherstellen, dass eine Authentifizierung mit Public-Keys möglich ist:

/etc/ssh/sshd_config
PubkeyAuthentication yes

Eine Benutzergruppe namens sftpusers anlegen:

groupadd sftpusers

Die einzelnen SFTP-Benutzer der Benutzergruppe sftpusers hinzufügen:

usermod --groups sftpusers linus

Die SSH Public-Keys der einzelnen SFTP-Benutzer in ihren jeweiligen Home-Verzeichnissen ablegen. Anschliessend:

chown linus:linus /home/linus/.ssh/authorized_keys
chmod 0600 /home/linus/.ssh/authorized_keys

Fehlt nur noch die Konfiguration des SSH-Daemon. Folgende Einstellungen ans Ende der /etc/ssh/sshd_config packen und danach den SSH-Server neu starten:

/etc/ssh/sshd_config
Subsystem sftp internal-sftp

Match Group sftpusers
  AllowTcpForwarding no
  ChrootDirectory /home
  ForceCommand internal-sftp
  PasswordAuthentication no
  X11Forwarding no
systemctl restart sshd

Das war es schon. Der Client kann sich jetzt verbinden:

sftp linus@host
sftp> pwd
sftp> ls
sftp> cd linus

Die wichtigsten SFTP-Kommandos…

… direkt auf dem SFTP-Server:
  • pwd: Aktuelles Verzeichnis ausgeben.

  • mkdir: Verzeichnis anlegen.

  • cd: Verzeichnis wechseln.

  • get /path/to/local/file: Lokale Datei auf den entfernten Client kopieren.

  • put /path/to/remote/file: Entfernte Datei auf den SFTP-Server kopieren.

  • exit: Verbindung beenden.

… gegen den Client:
  • lpwd: „local pwd“, aktuell genutztes Client-Verzeichnis ausgeben.

  • lmkdir: Client-Verzeichnis anlegen.

  • lcd: Client-Verzeichnis wechseln.

Die „local“-Varianten bedeuten also „Ausführung auf dem Client“. Alle anderen Kommandos werden auf dem SFTP-Server ausgefuehrt, wie bei SSH auch.

Siehe auch man sftp.

Port-Foward-only User

Manchmal benötigt man einen User-Account, der nur Port-Forwarding verwenden darf, also keinen Shell-Zugriff haben soll. Dazu muss zuerst ein UNIX User erstellt werden. Der User

useradd portfwdonly

Und danach folgende SSH-Einstellungen gesetzt werden.

/etc/ssh/sshd_config
Match User portfwdonly
    # deny all
    AllowAgentForwarding no
    AllowStreamLocalForwarding no
    ForceCommand echo 'Port forwarding only account. Shell access is not allowed. Please use the "-N" option for ssh.'
    PermitTTY no
    PermitTunnel no
    PermitUserRC no
    X11Forwarding no

    # allow explicitly
    PermitOpen 127.0.0.1:3306 localhost:3306

Zu beachten ist, dass der User sowohl Port-Forwarding als auch Reverse Port-Forwarding mit den freigegebenen Ports verwenden darf.

Performance

Mit folgendem Skript lässt sich die Geschwindigkeit einiger SSH-Chiffren im Vergleich testen (benötigt einen passwort-losen SSH-Zugang auf den eigenen Host). Die Performance ist stark abhängig von der darunterliegenden / verwendeten Hardware:

#!/usr/bin/env bash
for i in $(ssh -Q cipher); \
    do dd if=/dev/zero bs=1M count=1000 status=progress 2> /dev/null \
        | ssh -c "aes256-gcm@openssh.com" localhost "bash -c 'time -p cat' > /dev/null" 2>&1 \
        | grep real \
        | gawk '{print "'"$i"': "1000 / $2" MByte/s, " $2 " s" }' \
        && sleep 1;
done

Resultat auf einer OpenStack Cloud-VM:

aes256-gcm@openssh.com: 248.139 MByte/s, 4.03 s
aes128-gcm@openssh.com: 248.139 MByte/s, 4.03 s
aes256-ctr: 247.525 MByte/s, 4.04 s
chacha20-poly1305@openssh.com: 242.131 MByte/s, 4.13 s
aes256-cbc: 241.546 MByte/s, 4.14 s
3des-cbc: 240.385 MByte/s, 4.16 s
aes192-ctr: 234.742 MByte/s, 4.26 s
aes128-cbc: 233.645 MByte/s, 4.28 s
aes128-ctr: 230.947 MByte/s, 4.33 s
aes192-cbc: 227.273 MByte/s, 4.40 s
rijndael-cbc@lysator.liu.se: 194.553 MByte/s, 5.14 s

Resultat auf einer VM in KVM auf einem Notebook mit Intel-Prozessor und NVMe:

aes256-cbc: 1369.86 MByte/s, 0.73 s
chacha20-poly1305@openssh.com: 1265.82 MByte/s, 0.79 s
aes192-ctr: 1234.57 MByte/s, 0.81 s
3des-cbc: 1204.82 MByte/s, 0.83 s
aes192-cbc: 1176.47 MByte/s, 0.85 s
aes128-gcm@openssh.com: 1162.79 MByte/s, 0.86 s
aes128-cbc: 1149.43 MByte/s, 0.87 s
aes256-ctr: 961.538 MByte/s, 1.04 s
aes256-gcm@openssh.com: 925.926 MByte/s, 1.08 s
aes128-ctr: 925.926 MByte/s, 1.08 s

Troubleshooting

Postponed publickey for root from 10.26.6.74 port 54321 ssh2

Die RSA-Keys stimmen, ssh-copy-id verwendet bzw. Dateiberechtigungen auf alle Keys stimmen, und SELinux motzt auch nicht? Dann liegt es daran, dass man das Schlüsselpaar auf der Client-Maschine unter einem anderen Benutzer (z.B. linus) erzeugt hat als für den Benutzer, mit dem man sich auf der Zielmaschine anmelden möchte (z.B. root). Hier hilft die explizite Angabe des zu kopierenden SSH-Keys per ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.26.6.74.

Wie erhält man den SSH-Fingerprint zu einem SSH-Server?

Am einfachsten, man löscht den Eintrag in seiner ~/.ssh/known_hosts und verbindet sich neu.

Built on 2024-11-18