Verschlüsselung, Secure Shell

Grundlagen

Siehe dazu auch https://www.cryptool.org/de/

Verschlüsselungsarten

Symmetrische Verschlüsselung

  • Auf beiden Seiten ist der eine, selbe Schlüssel hinterlegt

  • Einsatz bei Pre Shared Key ⇒ WLAN

  • Schwierige Schlüsselverwaltung

  • Wichtige Verschlüsselungsverfahren: AES (WPA2 bei WLAN), Blowfish, 3DES

Asymmetrische Verschlüsselung

  • Laut Kerkhoff: Selbst wenn der Algorithmus in die Hände des Feindes fällt, dürfen keine Rückschlüsse auf den Schlüssel gezogen werden können

  • Das Schlüsselpaar besteht aus dem privaten Schlüssel, der NIEMALS das System verlassen darf, der öffentliche Schlüssel wird weitergegeben

  • Ablauf einer Verschlüsselung:

    • Der Sender verschlüsselt die Nachricht mit dem Public-Key der Empfängers

    • Der Empfänger entschlüsselt sie mit seinem eigenen Private-Key

  • Wichtige Verschlüsselungsverfahren: RSA, DH (IKE-Handshake), ECDSA (Unter Mitwirkung der NSA entstanden!), DSA

  • Risiken: Zu geringe Schlüssellänge (inbesondere bei RSA wichtig), oft kein Schutz gegen Man-In-The-Middle (MITM) Angriffe ⇒ Fingerabruck prüfen!

  • Anwendungen, die u.a. RSA verwenden: Secure Shell, Pretty Good Privacy (GnuPG)

Die Secure Shell

  • ssh (ersetzt rlogin und rsh) ⇒ Fernadministration (remote control)

  • scp (ersetzt rcp) ⇒ remote copy

  • sftp (ersetzt mit reduziertem Befehlssatz einen klassische ftpd)

Aufbau einer Vertrauensbasis

  1. Zuerst einmal wird auf dem Server der eigene krytografische Fingerabdruck vom eigenen Schlüsselpaar extrahiert, damit Clients später die Identität des Servers überprüfen können. Je nach Distribution werden unterschiedlich viele Schlüssel für die verschiedenen Verschlüsselungsalgorithmen vorgehalten:

    => ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub
    
    => ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
    
  2. Beim ersten Verbingsaufbau von Clients via mit ssh, scp oder sftp wird der öffentliche Schlüssel automatisch vom Server heruntergeladen und ein Fingerabruck daraus generiert, der nun mit dem Fingerabdruck, der auf dem Server ausgegeben wurde, verglichen werden muss. Stimmt er überein, Unterschreibt der Client mit yes die Echtheit der Serveridentität.
    Danach wird die IP-Adresse bzw. der Hostname des Servers zusammen mit dem eben heruntergeladenen Public-Key des Servers in der benutzerdefinierten Datei ~/.ssh/known_hosts gespeichert.

    Dieser vertrauensbildende Vorgang kann auch vom Admin durchgeführt werden, die systemweite Datenbankdatei ist dann: /etc/ssh/known_hosts

  3. Stimmt etwas mit der Serveridentität nicht, weil eine andere Netzwerkkarte eingebaut wurde, ein anderer Verschlüsselungsalgorithmus zum Einsatz kommt oder tatsächlich ein MITM-Angriff vorliegt, äußert sich das in etwa so:

    artix:[tux]:~$ ssh 192.168.2.200
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    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 RSA key sent by the remote host is
    SHA256:3yTKcd6THD+8tc3+tHfmXWYMRjNnm+vd6qW7rqQNUaM.
    Please contact your system administrator.
    Add correct host key in /home/tux/.ssh/known_hosts to get rid of this message.
    Offending ED25519 key in /home/tux/.ssh/known_hosts:47
    Host key for localhost has changed and you have requested strict checking.
    Host key verification failed.
    artix:[tux]:~$
    
  4. Der Client bestimmt, welches Verschlüsselungsverfahren angewendet wird, will er RSA für die Kommunikation, schiebt er das Ganze so an:

    ssh  -o  HostKeyAlgorithms=ssh-rsa-cert-v01@openssh.com,\
                    ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,\
                    ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss  tux@deb7
    
    (Oft funktioniert auch die Kurzform: "HostKeyAlgorithms=ssh-rsa")
    
  1. Die Clientseitige Datenbankdatei ~/.ssh/known_hosts kann durchsucht u. bearbeitet werden:

    1. Bei nicht gehashten Adressen/Hostnamen: grep/vi

    2. Bei gehashten Adressen/Hostnamen: ssh-keygen -F <HOST> bzw: ssh-keygen -R <HOST> Letztere Zeile entfernt (-R, remove) einen bestimmten Host aus der Liste der wohlbekannten, vertrauten Server. Dies wird benötigt, um das unter 3. geschilderte Problem mit der Serveridentität zu beheben.

Konfiguration der Secure Shell

  • Dateiname: /etc/ssh/sshd_config (Wegen dem Daemon ist ein *d* im Dateinamen)

  • Eine wichtige Einstellung, die root-Login verbietet: PermitRootLogin no

  • Falls ein Login mittels eigenen Schlüsselpaaren erzwungen werden soll: PasswordAuthentication no

  • Festlegen, welche Nutzer Zugriff bekommen sollen: Parameter AllowUsers, DenyUsers, AllowGroups und DenyGroups

  • Einen Verschlüsselungsalgorithmus nicht mehr anbieten, Zeile löschen: HostKey /etc/ssh/ssh\_host_ecdsa_key

  • Dateiname: /etc/ssh/ssh_config (Ohne *d*!)

  • Bequemlichkeitseinstellung (Der Client kann dann -X weglassen): ForwardX11 yes

  • Festlegen, dass Clients einen anderen als den voreingestellten (einkompilierten) Verschlüsselungsalgorithmus nutzen sollen: HostKeyAlgorithms ssh-rsa-cert-v01@openssh.com,… (s.o.)

Eigenes clientseitiges Schlüsselpaar erzeugen

Zur Orientierung: Das Ganze geschieht auf dem Client, er legt zum Schluss lediglich seinen öffentlichen Schlüssel unter dem Namen authorized_keys auf dem Server ab.

  • Ziele:

    • Zweifaktorauthentifizierung

    • Automatischer Login für Backup-Tools wie rdiff-backup

  • Erzeugung eines eigenen Schlüsselpaares auf dem Client (= CentOS) ohne Passphrase für Autologin

    ssh-keygen -t rsa  -b 4096  -N ""
    
  • Kopieren des Inhaltes von ~/.ssh/id_rsa.pub auf den entfernten Server in die Datei ~/.ssh/authorized_keys, es handelt sich hierbei um den öffentlichen Schlüssel – nur er darf herausgegeben werden!
    1. Kopieren auf manuelle Art (alles auf dem Client):

      • Sicherstellen, dass es auf dem Server den Ordner ~/.ssh gibt:

        tux@client> ssh tux@server "mkdir -p ~/.ssh"
        
      • Die Public-Key-Datei kopieren und umbenennen (ACHTUNG: Nur beim ersten Mal, sonst droht Datenverlust!)

        tux@client> scp ~/.ssh/id_rsa.pub  tux@server:.ssh/authorized_keys
        
    2. Komfortables Kopieren ebenfalls auf dem Client):

      ssh-copy-id tux@server
      
  • Tipps fürs Testen:

    • Der besseren Übersicht halber erst einmal mit gleichen Benutzernamen arbeiten: tux@clienttux@server (Entsprechend wird auf beiden Seiten automatisch /home/tux/.ssh erwartet)

    • Nach erfolgreichem Login nicht auf dem Server eingeloggt bleiben (Man will ja wahrscheinlich noch nicht wirklich den Server fernadministrieren, sondern erst einmal die Client-History zu Dokumentationszwecken sichten.):

      exit
      history 20 > ssh-versuche-histfile-01.txt
      

Automatisches Synchronisieren von Verzeichnissen

Motivation: Dank des eigenen passphraselosen Schlüssels kann nun leicht einen Master/Slave-Mirror eingerichtet werden. Die Synchonisierung kann später von cron ausgeführt werden.

  1. Ziel- und Quell-Verzeichnis definieren bzw. anlegen:

    1. Lokaler Ausgangspunkt: ~/Dokumente

    2. Entfernter Zielordner (auf Debian/Rasbian): mkdir /home/tux/Backup/Dokumente/

  2. Installation der Software auf beiden Seiten:

    1. Verschlüsselung via sshd (= erfüllte Voraussetzung)

    2. Vom Samba-Team stammendes rsync

  3. Ein einfacher Aufruf, der alle Dateien auf dem Server löscht, die nicht auf der sendenden Seite beim Client existieren kann so aussehen:

#rsync  ARCHIVING  MASTER/SLAVE   SENDER=CLIENT               EMPFÄNGER=SERVER
rsync     -a        --delete      ~/Dokumente/      tux@deb7:/home/tux/Backup/Dokumente/
#                                            ^
#                                            |
#                                     Wenn dieser "Directory"-Slash fehlt, wird
#                          der Ordener als Unterverzeichnis in den Zielordner kopiert!

History-Mitschnitt für Experimente.

Anmerkung: Im folgenden Historyauszug ist beim ersten rsync-Aufruf (Zeile 06) weder ein Login-Prompt noch eine Ausgabe, was im Einzelnen getan wird, zu sehen. Beim zweiten Aufruf (Zeile 15) wird die Option ``-v`` (verbose) verwendet, die für den Testfall mehr Anschaulichkeit bringt.

01 [tux@cent7 ~]$ echo 123 > Dokumente/datei01.txt
02 [tux@cent7 ~]$ echo 123 > Dokumente/datei02.txt
03 [tux@cent7 ~]$ echo 123 > Dokumente/datei03.txt
04 [tux@cent7 ~]$
05 [tux@cent7 ~]$
06 [tux@cent7 ~]$ rsync -a --delete ~/Dokumente/ tux@deb7:/home/tux/Backup/Dokumente/
07 [tux@cent7 ~]$
08 [tux@cent7 ~]$
09 [tux@cent7 ~]$ ### Testen, ob das Master-Slave-Verhalten funktioniert; wird eine Datei auf dem
10 [tux@cent7 ~]$ #   Master gelöscht, zieht das eine entsprechende Löschaktion auf dem Slave nach
11 [tux@cent7 ~]$ #   sich:
12 [tux@cent7 ~]$
13 [tux@cent7 ~]$ rm Dokumente/datei01.txt
14 [tux@cent7 ~]$
15 [tux@cent7 ~]$ rsync -a -v --delete ~/Dokumente/ tux@deb7:/home/tux/Backup/Dokumente/
16 sending incremental file list
17 ./
18 deleting datei01.txt
19
20 sent 83 bytes  received 15 bytes  196.00 bytes/sec
21 total size is 8  speedup is 0.08
22 [tux@cent7 ~]$

Fragen/Aufgaben zur Wiederholung

  1. Nennen Sie die beiden Dateien (benutzerdefiniert und systemweit), die die clientseitigen Vertrauenstellungen zu ssh-Servern beinhalten.

    a) ~/.ssh/known_hosts
    b) /etc/known_hosts
    
  2. Wie lautet die Kommandozeile, mit der Sie sich ein eigenes ssh-Schlüsselpaar erzeugen können?

    ssh-keygen -t rsa -b 4096
    
  3. Welchen Namen muss die Public-Key-Datei Ihres eigenen Schlüsselpaares auf dem Server aufweisen, wenn Sie sich dort mittels dieses Paares authentifizieren wollen? (Volle Pfadangabe)

    ~/.ssh/authorized_keys
    
  4. Wie heißen die Konfigurationsdateien von sshd und ssh?

    /etc/ssh/sshd_config   ( D = Daemon )
    /etc/ssh/ssh_config
    
  5. Mit welcher Direktive kann man in der Konfigurationsdatei des sshd einen ssh-Login von root verhindern?

    PermitRootLogin no
    
  6. Welchen TCP-Port verwendet standardmäßig der sshd?

    22    ( siehe /etc/services )
    

Tunnelbau mit SSH

Grafische Anwendungen verschlüsselt weiterleiten

Im einfachsten Falle lässt sich X11 durchtunneln, dazu braucht es nur die Option ‚-X‘ (das alte, klassische X11-Forwarding ist vollkommen unverschlüsselt!):

ssh -X  tux@cent7
=> nautilus &
=> yast2 &        (bei SuSE Linux)

Lokaler SSH-Tunnel für HTTP

Prinzipiell lässt sich auf diese Art jede HTTP-Kommunikation absichern, so könnte man z.B. aus dem Verzeichnis ~/public_html heraus mittels

$ python -m http.server

einen Webserver starten, der am Port 8000 lauscht.

Der Clientzugriff kann nach dem offenzuhaltenden ssh-Login (Option ‚-L‘ = lokale Portweiterleitung) z.B. mit wget via verschlüsselten Tunnel und dem zugehörigen Port 8888 erfolgen:

$ ssh -L 8888:localhost:8000 zielserver
$ ...
$ wget http://localhost:8888/my-important-file.txt

Weiterführende Dokumente:

Verschlüsselung mit GnuPG

Anders als beim zertifikatsbasierten, pyramidenförmigen Vertrauensmodell von X.509 liegt hier keine solch starke Bindung an übergeordnete Autoritäten vor. Das Motto lautet „Ich vertraue nur denen, den ich vertrauen möchte.“ Jeder hat sozusagen seinen persönlichen Schlüsselbund im web of trust.

Schlüssel erzeugen und signieren

  • Eigenen Schlüsselbund erzeugen:

    apt install haveged  # Vorher guten Zufallszahlengenerator installieren
    gpg --gen-key    (Bestätigung am Schluss mit 'F' [fertig])
    
  • Public-Key exportieren

    gpg --export --armor -o axelPemmann.pub "Axel Pemmann"
    
  • Rückrufszertifikat erzeugen (Am besten NICHT in eine Datei speichern, die man ja verschlüsselt ablegen müsste, sondern ausdrucken!

    gpg --gen-revoke -o axelPemmann-revoke.crt "Axel Pemmann"
    
  • Öffentlichen Schlüssel auf einen Key-Sever hochladen (oder einfach per Mail versenden, was die beste Lösung ist, weil sich auf den Key-Servern viele Schlüssel mit falscher Identität tummeln):

    gpg --send-key ...
    
  • Fingerprint für spätere Authentizitätsprüfung ausgeben (kontra MITM)

    gpg --fingerprint  "Axel Pemmann" > axelPemmann-fingerprint.txt
    
  • Schlüssel der Kommunikationspartner importieren

    gpg --import gerald.pub
    
    gpg --import maik.pub
    
    gpg --keyserver certserver.pgp.com --recv-key  0x47110815
    
    --> oder suchen via:  http://pgp.mit.edu/
    
  • Die importierten Schlüssel prüfen und signieren

    gpg --edit-key gerald
    
    gpg> list               (Schlüssel auflisten, optional)
    gpg> fpr  gerald        (Fingerabdruck des Partners ausgeben, optional)
    
    <--- SNIP: Per Telefon Fingerprint vegleichen  --->
    
    gpg> sign                (Unterzeichnung (j))
    gpg> check
    gpg> quit
    

Verschlüsselung

Nach dem gegenseitigen Austauschen des öffentlichen Schlüssels und dem entsprechenden Signieren (Key-Signing Party) kann es losgehen:

  • Eine Datei verschlüsseln

    gpg --output datei-richter.txt.gpg  --encrypt --recipient  richter  datei.txt
    
  • Entschlüsselung der Datei beim Partner

    gpg --decrypt  datei-pemmann.txt.gpg  [--output <DATEINAME>]
    
  • Heruntergeladene Dateien verifizieren

    gpg --verify source.tar.gz
    
  • Verschlüsselung und Archivierung mit gpg-zip (komplette Verzeichnisse)

    gpg-zip --encrypt --output GnuPG.cryptdir --gpg-args "-r axel@pemmann.de" GnuPG/
    
  • Entschlüsseln und Entpacken mit gpg-zip

    cd /tmp
    gpg-zip --decrypt ~/GnuPG.cryptdir
    

Signieren von Dateien

In Zeiten vermehrter Onlineaktivitäten ist es sinnvoll, Verträge o.ä. digital zu unterschreiben. Zur späteren Überprüfung der Unterschrift durch den Partner mittels gpg --verify ... muss er meinen öffentlichen Schlüssel erhalten und an seinen Schlüsselbund angehängt haben.

Für die Unterzeichnung ist die Option --detach-sign empfehlenswert, weil dadurch die Signatur nicht die Originaldatei verändert, sondern als abgetrennte, separate Datei mit übermittelt werden kann (= ‚.sig‘-Datei):

gpg  --detach-sign  -o  Vertrag-0815-unterschrieben.pdf.sig  Vertrag-0815-unterschrieben.pdf

Das Ganze kann man sich in eine kleine Programmdatei namens gpgsign.sh schreiben:

#!/bin/sh
# gpgsign.sh
# Diesem kleinen Skript muss als ersten Übergabeparameter einfach
# nur die zu signierende Datei mitgegeben werden.
gpg --detach-sign -o ${1}.sig --armor $1