GNU / Linux für Fachinformatiker (Systemintegration), Teil 2

Siehe Teil 1

Unterrichtsmaterialien

Begriffe / Programme für grafische Oberflächen

  • Grafikserver: xorg

    • Xorg vt07
    • export DISPLAY=:0; ...
  • Display-Manager

    • lightdm, gdm, lxdm, nodm, ...
    • Startet den Grafikserver und fragt idR. Benutzerlogins ab
  • Session-Manager

    • Startet die Komponenten des grafischen Desktops (Menüleiste, Programmautostart, ...)
  • Window-Manager

    • Zichnet "Fensterdekoration" / "Titelleiste"
    • Verwaltet Größenänderungen u. Position von Fenstern

Dienstprogramme

  • setxkbmap (Tatstaturbelegung)

    • setxkbmap de, setxkbmap us
  • xrandr (Bildschirmauflösung)

    • Beispiel: xrandr --output eDP-1 --mode 1024x768
    • Beispiel: xrandr --output eDP-1 --rotate left
  • xinput

    • xinput list-props "Gerätename"

    • xinput set-prop "Gerätename" "Propertyname" Wert

      z.B.: xinput set-prop "Microsoft Vmbus HID-compliant Mouse" "libinput Natural Scrolling Enabled" 1

Diagnose / Debugging

  • xev (Input-Events zeigen)

Aufgabe numerische Zugriffsmodi

Legt die Dateien a, b, c, d, e an. Ändert mit chmod die Zugriffsmodi (Berechtigungen) so, dass folgendes Bild entsteht:

-----w---- 1 damago damago 0  9. Jan 09:58 a
----r-x--- 1 damago damago 0  9. Jan 09:58 b
---x---r-- 1 damago damago 0  9. Jan 09:58 c
--w-----w- 1 damago damago 0  9. Jan 09:58 d
-r-------t 1 damago damago 0  9. Jan 09:58 e

Benutzt die numerische ("oktale") Angabe für den Zugriffsmodus. Beachtet, das "t" in der letzten Datei.

Antwort bitte als Screenshot oder Shellkommando per Teams-Chat.

Zusatzaufgabe

d----w---- 1 damago damago 0  9. Jan 10:11 a
p---r-s--- 1 damago damago 0  9. Jan 10:11 b
---S---r-- 1 damago damago 0  9. Jan 10:12 c
s-w-----w- 1 damago damago 0  9. Jan 10:14 d
lrwxrwxrwx 1 damago damago 1  9. Jan 10:11 e -> e

Shellscripting

  • Befehle genauso wie in der interaktiven Shell
  • Scriptdateien beginnen mit #!/bin/sh bzw. #!/bin/bash
  • Scriptdateien sollten Ausführungsrechte haben
  • Häufig liegen Scriptdateien nicht im normalen Ausführungspfad wie "/bin" oder "/usr/bin". Zum Ausführen auf der Shell muss dann der Pfad der Datei mit angegeben werden, im einfachsten Fall: ./scriptdatei

Aufgabe Scripting

Schreibt ein Shellscript, das

  1. nach eurem Namen fragt
  2. den Namen von der Tastatur liest und
  3. euch dann mit eurem Namen begrüßt.

Eingaben können mittels read in eine Variable gelesen werden.

Hinweise

  1. Variablen werden beim Auslesen mit $dollarzeichen geschrieben, bei der Zuweisung ohne.

  2. read hat keine eigene man-Page. Es ist ein Builtin der Shell, und wird z.B. in der man-Page der "dash" unter "Builtins" dokumentiert (man-Pages können mittels / durchsucht werden).

Zusatz

Der Befehlt head -n1 liest ebenfalls genau eine Zeile vom Terminal. Benutzt eine "Command Substitution" ($(...)) um den Namen in eine Variable zu lesen, ohne read zu benutzen.

Aufgabe Kontrollstrukturen

Erweitert das Begrüßungsscript folgendermaßen

  1. neben dem eingelesenen Namen soll auch eine Variable "stunde" gesetzt werden

    • Um die aktuelle Stunde herauszubekommen kann das Programm date verwendet werden
    • die Variable wird dann einfach via Command Substitution gesetzt
    • Zum Testen soll zunächst in der Grußausgabe einfach die Stunde mit aufgeführt werden (z.B. "11 Uhr: Hallo Friedbert!")

    Hinweis: Ihr müsst hier selbst recherchieren, wie man date dazu bekommt, nur die Stunde der aktuellen Uhrzeit auszugeben.

  2. Das Programm test kann Zahlen vergleichen (man-Page). Ergebnis eines Vergleichs ist der "Return-Code" des Programms. Dieser ist auf der Kommandozeile nicht sichtbar.

    Mit dem && Operator können Kommandos verkettet werden. Das zweite Kommando wird dann nur ausgeführt, wenn das erste einen erfolgreichen Return-Code liefert: test ... && echo Guten Morgen

    • Schreibt das Script mit einem test und && so weiter, dass zu jeder Stund kleiner 13 ein "Guten Morgen" ausgegeben wird und zu jeder Stunde größer/gleich 13 ein "Guten Abend"
  3. Mit if ... then ... else ... fi kann man Verzweigungen aufgrund eines Return Codes bauen.

    • Hinter dem if-Schlüsselwort kommt ein Programmaufruf, der entweder erfolgreich oder fehlerhaft beendet: if test...

    • bei Erfolg werden die Kommandos in einem then-Block ausgeführt:

      if ...
      then
        ...
        ...
    • Optional kann ein else-Block angegeben werden, der ausgeführt wird, wenn das Bedingungsprogramm mit einem Fehler beendet:

      if ...
      then
        ...
        ...
      else
        ...
        ...
    • Abgeschlossen wird das eine solche if-Gruppe mit dem Schlüsselwort fi ("if" rückwärts)

      if ...
      then
        ...
        ...
      else
        ...
        ...
      fi
    • Aufgabe: Schreibt die Uhrzeit-Weiche mit if-Bedingungen.

  4. Innerhalb eines then- bzw. else-Blocks kann eine weitere if-Abfrage stehen (if ... then ... fi). Dies bezeichnet man als "Verschachtelung", bzw. "Verschachtelte Bedingung":

    if ...
    then
      ...
      if ...
      then
        ...
        ...
      fi
      ...
    else
      ...
      ...
    fi

    Hier müsst ihr darauf achten, die Anweisungen aus dem äußeren und dem inneren if-Block nicht zu vermischen.

    • Unterscheidet in verschachtelten if-Blöcken folgende Uhrzeiten:

      • 0 - 9 Uhr: Guten Morgen
      • 10 - 13 Uhr: Mahlzeit
      • 14 - 18 Uhr: Guten Tag
      • 19 - 24 Uhr: Guten Abend
    • Zusatz: Zwischen 23:00 und 4:00 Uhr soll die Begrüßung "Huuuhuuu" sein.

    • Zusatz: Schaut euch das elif-Schlüsselwort an um die Verschachtelungstiefe der if-Abfragen zu reduzieren.

Aufgabe read:

Lest mit read aus einer Zeile die Variablen "eins" "zwei" "drei" und "vier" ein.

Gebt alle vier Variable einzeln aus, und beantwortet folgende Fragen:

  1. Welche Eingabe muss ich machen, damit die Variable "drei" den wert "schnabbeldifoo" bekommt?

  2. Welche Werte nehmen die Variablen an, wenn in der Eingabe fünf oder sechs verschiedene Worte übergeben werden?

Anmerkungen zu read

~$ echo alpha beta gamma |read eins zwei drei

→ Das Pipe-Konstrukt zwingt die Shell dazu, read in einem Unterprozess auszuführen. Deshalb stehen mir die gelesenen Variablenwerete nich in der Aufrufshell zur Verfügung.

Ein Heredoc kann helfen:

~$ read eins zwei drei <<EOF
alpha beta gamma
EOF

Eine Command Substitution im Heredoc erlaubt das lesen von Programmrückgaben:

~$ read stunde minute sekunde <<EOF
$(date "+%H %M %s")
EOF

Aufgabe Scripting / Netzwerk

Der read-Befehl kann mehrere Variablen auf einmal einlesen. Diese werden an Leerzeilen separiert.

  1. Benutzt read um von einer Zeile die Variablen "method", "info" und "proto" zu lesen.

  2. gebt mittels cat eine Datei aus, die dem Dateinamen aus "info" entspricht.

  3. Richtet das Script als inetd-Service auf Port 1080 ein.

Beispiel für die Bedienung:

~$ echo foo /etc/inetd.conf bar |nc localhost 1080

-> soll die Datei inetd.conf auf dem Terminal ausgeben.

(Das macht jetzt noch nicht viel sinn, wird aber bald weiter entwickelt)

Mit Überprüfung:

Bevor cat die Datei ausgibt soll überprüft werden, ob diese existiert und gelesen werden kann. Hierzu kann das test-Programm benutzt werden.

  1. Schreibt eine if/test-Abfrage um zu überprüfen, ob die Datei "$info" existiert. Gebt die Datei in dem Fall wie bisher mit cat aus. Ansonsten soll ausgegeben werden "Not Found".

Aufgabe while-Schleife

Schreibt eine Scriptdatei mit einer einzelnen While-Schleife:

while TESTPROGRAMM; do
  KOMMANDO
  KOMMANDO
  ...
done

Die Schleife soll prüfen, ob die Datei "TEST" im Heimverzeichnis existiert und lesbar ist. Solange dies der Fall ist, soll die Schleife konstant einen Punkt (".") auf dem Terminal ausgeben. Das Programm endet, sobald die Datei TEST verschwindet oder Leserechte verliert.

Hinweis: zum testen muss die Datei "TEST" natürlich existieren.

Zusatz

Damit die Schleife nicht eine Billion Punkte ins Terminal schreibt, soll sie durch ein sleep ausgebremst werden. Außerdem sollen alle Punkte auf der selben Zeile aufgereiht werden.

Aufgabe Netzwerkdienst

Das inetd-Script aus der vorletzten Aufgabe soll angepasst werden. Nachdem die Variablen "method", "info" und "proto" gelesen wurden, sollen noch weitere Zeilen eingelesen werden, bis eine Leerzeile auftaucht.

Der Inhalt der gelesenen Zeilen wird ignoriert.

Schleifenbedingung ist, dass die zuletzt gelesene Zeile nicht leer ist (siehe man-Page zu test).

Die Ausgabe der "$info"-Datei erfolgt erst, nachdem eine Leerzeile gelesen wurde.

Fortsetzung

Bevor das Dokument mit cat ausgegeben wird (falls es ausgegeben wird) soll ein Response-Header gesendet werden. Dieser Besteht aus:

  1. Der Zeile HTTP/1.0 200 OK
  2. Einer Leerzeile

Falls das Dokument nicht gesendet wird, Soll die Antwort bestehen aus:

  1. Der Zeile HTTP/1.0 404 Not Found
  2. Einer Leerzeile

Fortsetzung

Wenn es sich bei dem angefragten Pfad um ein Verzeichnis handelt, soll das Programm ein Verzeichnislisting liefern.

Handelt es sich um eine Datei, soll weiter wie bisher die Datei ausgegeben werden.

Zusatz: Beim Verzeichnislisting soll jedem Eintrag das Wort: "Datei: " bzw. "Verzeichnis: " vorangestellt werden.

Aufgabe "Privilege Separation"

Benutzt useradd um einen Service-Account (UID < 1000) anzulegen. Dieses Dienstekonto soll über ein Heimverzeichnis unterhalb von "/srv" verfügen.

Postet im Teams-Chat den Programmaufruf dafür.

Zusatz:

useradd kann user- und gruppen-id selbst wählen. Zudem gibt es eine Möglichkeit bei der der Benutzername nur einmal auf der Kommandozeile stehen braucht (d.h. nicht für das Heimverzeichnis wiederholt weden muss).

Verschiedene Inetd-Dienste:

Wir setzen verschiedene Web-Dienste mit Privilege Separation auf. Später sollen diese über den Webserver laufen. Zunächst ist aber einfacher den inetd zu benutzen.

Setup-Code als Root-User

~# apt install openbsd-inetd
~# useradd -rmb /srv wiki
~# useradd -rmb /srv poll

Service-Installation Shellwiki:

~# runuser -u wiki bash
wiki...$ cd ~
wiki~$ git clone https://git.plutz.net/git/shellwiki

Service-Installation Webpoll:

~# runuser -u poll bash
poll...$ cd ~
poll~$ git clone https://git.plutz.net/git/webpoll
poll~$ mkdir data

Zusätzliche Zeilen in /etc/inetd.conf

81   stream   tcp   nowait   wiki   /srv/wiki/shellwiki/index.cgi   /srv/wiki/shellwiki/index.cgi --data=/srv/wiki/data  --debug=/dev/null
82   stream   tcp   nowait   poll   /srv/poll/webpoll/index.cgi     /srv/poll/webpoll/index.cgi   --data=/srv/poll/data  --debug=/srv/poll/debug.log

Nicht vergessen: systemctl restart inetd

Ergebnis

Am Ende soll das ganze so aussehen (im Live-System, bzw. vom Virtualisierer aus falls ihr nicht im Live-System arbeitet):

Live-System Windows-Desktop

Reverse Proxy im Apache2

Der Reverse-Proxy kann benutzt werden, um verschidene HTTP-Requests an unterschiedliche Webapplikationen (bzw. unterschiedliche Webserver) zu delegieren.

~# a2enmod   rewrite  proxy   proxy_http
~# systemctl  restart  apache2

/etc/apache2/sites-enabled/000-default.conf

<VirtualHost *:80>
  # ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  RewriteEngine on

  RewriteRule   ^/poll/(.*)$    http://localhost:82/$1        [P]
  RewriteRule   ^/(.*)$         http://localhost:81/$1        [P]

</VirtualHost>

Das gleiche mit Unix-Sockets

/etc/inetd.conf anpassen:

/srv/wiki/socket   stream   unix   nowait   wiki   /srv/wiki/shellwiki/index.cgi   /srv/wiki/shellwiki/index.cgi --data=/srv/wiki/data  --debug=/dev/null
/srv/poll/socket   stream   unix   nowait   poll   /srv/poll/webpoll/index.cgi     /srv/poll/webpoll/index.cgi   --data=/srv/poll/data  --debug=/srv/poll/debug.log   --base=/poll/

/etc/apache2/sites-enabled/000-default.conf anpassen:

  RewriteRule   ^/poll/(.*)$    unix:/srv/poll/socket|http://localhost/$1     [P]
  RewriteRule   ^/(.*)$         unix:/srv/wiki/socket|http://localhost/$1     [P]

Service-Sockets für Apache freigeben:

~# chgrp   www-data   /srv/poll   /srv/wiki
~# chmod   g+x   /srv/poll   /srv/wiki

Apache und Inetd neu starten

~# systemctl restart inetd
~# systemctl reload apache2

URL

Wie sind URLs aufgebaut?

http:// juhser:p4ssw0rd@ schnabbeldiwauw.au :80 /wordpress ?var=foo #Absatz1
^       ^      ^         ^                  ^   ^          ^        ^
|       |      |         |                  |   |          |        |
|       |      |         |                  |   |          |        Anker
|       |      |         |                  |   |          Query-String
|       |      |         |                  |   Local-Part / Server-Pfad
|       |      |         |                  Portnummer
|       |      |         Domainname
|       |      Passwort
|       Benutzername
Protokoll
Protokoll
auch Schema geannt (auch im Englischen "Schema"!)
Benutzername / Passwort
Beides optional
durch @-Zeichen der Domain / Hostname vorangestellt
Username kann allein stehen (ohne Passwort)
Passwort kann nicht allein stehen
Passwort (falls vorhanden) wird durch : vom Username abgesetzt
Domainname / Hostname
wird via DNS zu einer IP-Adresse aufgelöst
wird außerdem im http-Request im "Host"-Header übertragen

Von hinten nach vorn definiert

  • Top-Level-Domain (.de, .au, .com, .org, ...)
  • Second-Level-Domain (gehört idR. dem Seitenbetreiber)
  • Subdomain (z.B. www.damago.eu, de.wikipedia.org)
Local-Part
wird allein vom Server interpretiert
wird gerne als Verzeichnispfad verstanden
ist die Adresse eines "Dokuments" auf dem Server
Query-String (Optional)
Teil des Local-Part
Wird eigentlich allein vom Server-Interpretiert

Wird vom Browser benutzt um Formulareingaben zu übergeben

  • Formualreingabe in form variable=wert

    • Eine "Variable" entspricht einem Formularfeld
  • mehrere Variablen werden durch &-Zeichen getrennt
Anker (optional, hinter dem #-Zeichen)
wird allein vom Browser verarbeitet
Der Server erfährt nicht, welcher Seitenanker gerade betrachtet wird

Andere Protokolle

einige Beispiele

  • sftp://user@hostname/home/user
  • Bittorren: magnet:?xt=urn:btih:1a2b3c4d5e6f789...&optionale&informationen

    • Besteht aus Protokoll-Teil und Dokumenten-Informationen ähnlich einem "Query-String"
    • Kein Port, kein Hostname, da verteiltes Netzwerk
  • smb://hostname/Freigabe/Unter/verzeich/nis

    • Unter Windows: \\hostname\Freigabe\Unter\verzeich\nis

Unterscheidung URL / URI

Die URL ist eine vollständige Dokumentenadresse: https://plutz.net/training/damago_2025_11/

Die URI kann eine vollständige URL sein, kann aber auch ein abgekürzter Teil davon sein, der je nach Situation genutzt wird, um eine Vollständige URL herzuleiten.

Z.B. braucht ein Hyperlink auf einer Webseite nur den Local-Part enthalten um ein Dokument zu identifizieren. Der Browser weiß dann, dass das Dokument auf der selben Domain (über das selbe Protokoll) abgerufen wird.

Nextcloud

Software aufsetzen

~# useradd   -rmb   /srv   nextcloud
~# runuser  -u  nextcloud  bash
nextcloud....$  cd ~
nextcloud~$ wget https://download.nextcloud.com/server/releases/latest.zip
nextcloud~$ unzip latest.zip

Webserver aufsetzen

Apache muss

  1. php Scripte ausführen können
  2. einzelne VHosts in separatem User-Kontext ausführen
~# apt   install   libapache2-mod-php8.4   libapache2-mpm-itk

Apache Vhost config:

<VirtualHost *:80>
  # Vhost-Konfigurationen werden anhand des Hostnamens im HTTP-Request unterschieden
  ServerName    nextcloud

  # Zur Übersicht sollte jede "Site" eigene Log-Dateien nutzen
  ErrorLog ${APACHE_LOG_DIR}/nextcloud-error.log
  CustomLog ${APACHE_LOG_DIR}/nextcloud-access.log combined

  # User-Trennung nicht in der NC-Doku enthalten
  # Wird ermöglicht durch mpm-itk
  AssignUserID  nextcloud       nextcloud

  DocumentRoot /srv/nextcloud/nextcloud/

  # Eigenheit vom Apache: Unabhänig von Dateisystemberechtigungen managed der Apache welche Verzeichnisse via HTTP ausgeliefert werden dürfen.
  <Directory /srv/nextcloud/nextcloud/>
    Require all granted
  </Directory>
</VirtualHost>

Zum Testen der Eintrag in /etc/hosts 127.0.0.1 nextcloud

Fehlende PHP-Bibliotheken

Die Nextcloud-Dokumentation listet die Namen der benötigten PHP-Bibliotheken, aber nicht die Namen der Debian-Pakete in denen diese enthalten sind. Die Paketnamen müssen wir durch apt-cache searh ... ermitteln, bzw. raten.

~# apt   install   php-xml   php-mbstring   php-zip   php-gd   php-curl   php-sqlite3

Nicht vergessen den Apachen neu zu starten.

Einrichtung im Browser

Auf einer Maschine, die den Hostnamen richtig auflösen kann (d.h. Eintrag in /etc/hosts, bzw. via DNS): http://hostname/

Beim einrichten des Data-Verzeichnisses darauf achten, dass

  • das Verzeichnis für Nextcloud schreibbar ist
  • das Verzeichnis zusammen mit sonstigen Benutzerdaten gesichert wird (aka. Datensicherheit, etc...)

Verschlüsselung: SSL

SSL CA.svg
  • CA liefert Public Key in allen Browsern aus
  • Site-Betreiber lassen Public Key von CA signieren
  • Browser überprüfen unbekannte Public Keys anhand von CA

    • ein signierter Public Key wird "Zertifikat" genannt

Beachte die Unterscheidung:

Public Key
Nur der Cryptographische Schlüssel
Zertifikat
Der Public Key und die signierten Informationen

SSL-Zertifikat erstellen

Aus Sicht des Site-Betreibers:

  1. Private/Public-Schlüsselpaar erstellen
  2. "Certificate Signing Request" generieren

    • bis dahin lokal auf dem Rechner
    • enthält Informationen, die signiert werden sollen

      • "CN" / "Common Name": Domainname
      • Organisation (EV-Zertifikate)
      • Email-Adresse
      • ...
  3. CA signiert Signing Request mit ihren Private Key

    • → Resultat ist das Zertifikat der Site
  4. Webserver konfigurieren um ...

    • den Private Key (aus Schritt 1) zu nutzen
    • das signierte Zertifikat (aus Schritt 3) vorzuweisen

Aus Sicht der CA:

  1. Private/Public-Schlüsselpaar erstellen
  2. Public Key → Self Signed Certificate

    • Zertifikat enthält signierte Informationen

      • "CN" / "Common Name": Freitextname der CA
  3. Zertifikat (aus Schritt 2) in Browser einspielen
  4. Profit!

    • Certificate Signing Requests der Sites mit Private-Key (aus Schritt 1) signieren
    • → Zertifikate ausstellen

Shell-Session

 ~$ openssl genrsa >RootCA.key
 ~$ openssl req -x509 -key RootCA.key -subj /CN="Green Grocerer's SSL Certificate's" -days 14 >RootCA.crt

-days liegt bei Root-Zertifikaten idR. bei 3 - 10 Jahren

Zerifikat bewundern:

~$ openssl x509 -text <RootCA.crt |less

Zertifikat einspielen:

  1. Chromium klicken

  2. Firefox klicken

  3. /etc/ssl/certs bzw.

    ~# cp RootCA.crt /usr/share/ca-certificates/
    ~# echo RootCA.crt >>/etc/ca-certificates.conf
    ~# update-ca-certificates
  4. In Windows:

    \> certmgr.msc Importieren nach "Vertrauenswürdige Stammzertifizierungsstellen"

Firefox ohne klicken:
/etc/firefox/policies/policies.json

{ "policies": { "Certificates": { "Install": [ "/etc/ssl/...", "/usr/share/ca-certificates/..." ] } } }

Chromium ohne klicken:
für jeden Useraccount einzeln

~$ certutil -d ~/.pki/nssdb/  -A -t -C,, -n "Freitextname" -i /etc/ssl/...

Site-Zertifikat erstellen:

~$ openssl genrsa >meinedoma.in.key
~$ openssl req -new -subj /CN=meinedoma.in -key meinedoma.in.key >meinedoma.in.req

Signieren als CA:

~$ openssl x509 -req -CA RootCA.crt -CAkey RootCA.key <meinedoma.in.req >meinedoma.in.crt

Mit SAN extension:

~$ printf '%s\n' '[SAN]' 'subjectAltName=DNS:meinedoma.in' >meinedoma.in.conf

~$ openssl x509 -req -CA RootCA.crt -CAkey RootCA.key -extensions SAN -extfile meinedoma.in.conf <meinedoma.in.req >meinedoma.in.crt

SSL-Server mit ncat:

~$ ncat -klp 1024 -e ~/service.sh --ssl-cert meinedoma.in.crt --ssl-key meinedoma.in.key

OpenSSL Hilfe:

~$ openssl --help 2>&1 |less
~$ openssl req -help 2>&1 |less

Makefile - Muss bei Benutzung "Makefile" heißen. Aufruf z.B. als ~$ make meinedoma.in.crt.

Apache SSL Setup

  • *.crt-Dateien der Sites kopieren z.B. nach /etc/ssl/local/ (RootCA.crt wird dort nicht gebrauch)

  • *.key-Dateien der Sites kopieren nach /etc/ssl/private/

    • Achtung: RootCA.key hat dort nichts zu suchen!
    • private/-Ordner eignet sich, weil nicht global lesbar
    • key-Dateien sollten nur von dem jeweils relevanten Service lesbar sein
  • SSL-Konfiguration pro VHost, siehe /etc/apache2/sites-available/default-ssl.conf

    • SSLCertificateFile, SSLCertificateKeyFile
~$ a2enmod ssl
~$ a2ensite default-ssl
   (oder wie auch immer die VHost-Config heißt)
~$ systemctl restart apache2

Apache SSL-Redirect und ACME

  • Alle VHosts werden nur noch für SSL konfiguriert

    • SSL-VHosts müssen deaktiviert sein, solange Zertifikate noch nicht vorhanden sind
  • die Einzige nicht-SSL-Konfiguration beantwortet ACME-Challenges und löst für andere Anfragen einen HTTPS-Redirect aus:

    <VirtualHost *:80>
     Alias         /.well-known/acme-challenge/    /var/lib/dehydrated/acme-challenges/
    
     <Location /.well-known/acme-challenge>
     Require     all     granted
     </Location>
    
     <LocationMatch        "^/(?!\.well-known/acme-challenge)">
     Redirect    301     https://%{HTTP_HOST}%{REQUEST_URI}
     </LocationMatch>
    </VirtualHost>
  • SSL-Zertifikate werden über ACME automatisch erstellt und signiert.

    1. ACME-Client installieren (~# apt install dehydrated)
    2. Automatisch, "anonym" Account erstellen (~# dehydrated --register --accept-terms)
    3. Domainnamen konfigurieren (in /etc/dehydrated/domains.txt)

      • Ein Zertifikat pro Zeile
      • mehrere Domainnamen pro Zertifikat möglich
      • mehrere Zertifikate möglich
      • Datei enthält nur Domainnamen
    4. dehydrated -c ausführen um Schlüssel zu generieren und Zertifikate anzufordern

      • Challenge-Dateien auf dem HTTP-Server beweisen der CA, dass wir eine Domain kontrollieren (siehe Config-Datei im obigen Stichpunkt)
  • Sobald die Zertifikate erstellt sind können die SSL-VHosts aktiviert werden (a2ensite)

    • SSL-Zertifikate können in der VHost-Konfiguration direkt aus /var/lib/dehydrated/certs/... benutzt werden
  • Ggf. muss dehydrated -c regelmäßig ausgeführt werden um die Zertifikate aktuell zu halten

Hausaufgabe

Konfiguriere Apache mit SSL. So wie in den letzten beiden Tagen. Für lokale Domains ist nur ein betrieb mit privater CA möglich. Schickt mir folgenden Screenshot. Um zu zeigen, dass die Dienste über das Netzwerk erreichbar sind, soll der Screenshot im Microsoft Edge angelegt werden.

Hausaufgabe_Apache_SSL.png

Log-Auswertung

... grep / sed / sort / wc / usw...

Unter dem Link https://plutz.net/training/damago_2026_01/plutz.net_sshlogs.txt.gz finden sich SSH-Logs eines Internetservers für die letzten drei Tage. Die Datei ist komprimiert und muss vor der Weiterverarbeitung mit gzip, o.ä. dekomprimiert werden.

Wie können wir sehen, von welchen IP-Adressen bzw. -Netzen hier SSH-Angriffe ausgehen.

{ grep 'Disconnected from' plutz.net_sshlogs.txt |cut -d' ' -f11;
  grep 'Received disconnect' plutz.net_sshlogs.txt |cut -d' ' -f9;
  grep 'Connection closed by .* user' plutz.net_sshlogs.txt  |cut -d\  -f12;
} |grep -E '[0-9.]{7,15}' |sort |uniq -c |sort -n \
| while read num ip; do
  loc=$(geoiplookup $ip);
  printf '%4i %s\n' $num "$loc";
done |sort -k5  \
| while read num loc; do
  if [ "$oloc" != "$loc" ]; then
    printf %5i\ %s\\n $acc "$oloc";
    acc=$num; else acc=$((acc + num));
  fi
  oloc="$loc";
done |sort -n |less

Aufgabe SSH-Host-Keys

Auf dem SSH-Server

~# ls -lh /etc/ssh
~# apt purge openssh-server
~# ls -lh /etc/ssh
~# apt install ssh
~# ls -lh /etc/ssh

Auf dem (Windows-)Client

\> ssh live@IP.ADR.ES.SE
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

Nach dem Löschen der "offending" keys in .ssh/known_hosts kann man den Host-Key neu bestätigen.

Auf dem Server lässt sich ein Fingerprint ausgeben via:

~$ ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub

(Dateiname variiert je nach Schlüsseltyp)

VM-Setup

Grafische Verbindung zwischen Linux-Desktops

  1. Der SSH-Server läuft wie bisher in Hyper-V mit externem Switch SERVER

  2. Auf einer zweiten VM booten wir das Live-System (externer Switch) CLIENT

Auf dem Client den Thunar (Dateimanager) öffnen

  • in der Adresszeile: sftp://SER.VER.IP.ADR/

  • → Popup vom Dateimanager bittet nach Bestätigung der Server-"Identität" ( == Host-Key-Fingerprint)

    • Falls der Fingerprint nicht Lesbar ist (Bug im Thunar), zu Sicherheit eine Connection mit ssh SER.VER.IP.ADR auf der Command-Line ausführen
  • → Zur Sicherheit Auf dem Server die Idenität überprüfen: SERVER~$ ssh-keygen -l -f /etc/ssh/ssh_host_XXXXXX_key.pub

  • Identität verifizieren und Bestätigen

  • → Dateimanager fragt beim nächten Versuch nach User und Passwort

SSH Linux ↔ Linux

client~$ ssh-keygen
...
client~$ ssh-copy-id  user@server
-> Fragt einmal nach Passwort
client~$ ssh user@server
-> keine Passwortabfrage

Dateien via SSH übertragen

  • scp DATEI user@host:PFAD
  • scp user@host:DATEI PFAD
  • Grafischer Dateimanager: sftp://user@HOST
  • sshfs user@host: lokaler_ordner/
  • mc (Midnight-Commander) → F9-Menü → sftp-Verbindung
  • sftp user@host

    • Einziger sftp-Client, der per Dafault in Windows existiert
    • > get DATEI
    • > put DATEI
    • > get -R Ordner
    • Es gibt immer ein lokales und ein remote Arbeitsverzeichnis

      • > pwd, > lpwd
      • > cd ...., > lcd ....
      • > ls, > lls
  • Per Pipeline

    • ~$ ssh user@host cat remote_datei > datei
    • ~$ cat datei | ssh user@host cat \>remote_datei
    • Achtung: Shell-Escaping wird kompliziert!