01 Das Terminal öffnen
Früher war die Kommandozeile der ganze Computer. Heute muss man sie erst "heraufbeschwören". Im Kurs läuft fast alles auf einem Ubuntu-Server (Hostinger VPS KVM 2) im Browser-Terminal, am Ende zusätzlich im lokalen Mac-Terminal.
Win drücken, cmd tippen, Enter: die Eingabeaufforderung startet.
Cmd + Leertaste, dann Terminal tippen und Enter.
Für den SSH-Teil empfiehlt Niklas Windows-Nutzern das Windows Subsystem for Linux: damit bekommst du eine echte Bash auf dem Windows-Rechner und kannst alle Linux-Befehle 1:1 mitmachen.
02 Orientierung und Navigation
Die drei Fragen am Anfang jeder Session: Wo bin ich? Was liegt hier? Wie komme ich woanders hin?
Zeigt den Inhalt des aktuellen Verzeichnisses ("list").
root@srv1311594:~# ls documents downloads music
Wichtige Varianten aus dem Kurs:
$ ls -a # auch versteckte Dateien (beginnen mit einem Punkt) $ ls -hl # Liste mit Rechten, Besitzer, Größe (h = menschenlesbar) $ ls -ahl # beides kombiniert
Das Windows-Gegenstück zu ls: zeigt Dokumente, Downloads usw. an, genau das, was du auch im Explorer siehst.
pwd3:41"Print Working Directory": zeigt, wo du gerade bist.
root@srv1311594:~# pwd /root
/root ist das Home-Verzeichnis des Root-Users. Die Tilde ~ im Prompt ist die Abkürzung dafür.
cd4:11"Change Directory": wechselt das Verzeichnis. Mit Tab vervollständigst du Namen, statt sie auszuschreiben.
$ cd documents # in einen Unterordner $ cd .. # eine Ebene nach oben $ cd # ohne Argument: direkt ins Home-Verzeichnis $ cd ../documents/demo # relativer Pfad (von hier aus gedacht) $ cd /root/documents/demo # absoluter Pfad (beginnt mit /), klappt von überall
/ und funktioniert, egal wo du gerade stehst. Im Kurs schlägt der relative Pfad prompt fehl, sobald Niklas ihn aus einem anderen Ordner wiederholt (6:59).03 Dateien und Ordner anlegen, verschieben, löschen
Der Grundwortschatz für alles, was du sonst per Drag & Drop im Finder oder Explorer machst.
mkdir3:58"Make Directory": legt Ordner an, auch mehrere auf einmal.
$ mkdir Documents Downloads Pictures Music $ mkdir demo
touch4:23Legt eine leere Datei an.
$ touch beispiel.txt
mv4:50"Move" hat zwei Funktionen: verschieben und umbenennen. Es gibt kein eigenes Rename-Kommando.
$ mv beispiel.txt demo/ # Datei in den Ordner demo verschieben $ mv Documents documents # Ordner umbenennen (Ziel existiert nicht) $ mv Pictures images # umbenennen $ mv images downloads/ # verschieben (Ziel ist ein existierender Ordner!) $ mv config config.old # klassischer Trick: Backup vor dem Überschreiben
cp -r7:58"Copy": kopiert Dateien. Mit -r (rekursiv) auch ganze Ordner samt Inhalt. Im Kurs entsteht so eine Arbeitskopie der Server-Logs zum Herumspielen:
$ ls /var/log/ # erst mal reingucken $ cp -r /var/log ~ # kompletten Log-Ordner ins Home-Verzeichnis kopieren
Später kopiert Niklas als Nutzer niklas das Skript aus /root zu sich:
niklas$ cp top_attackers.sh ~
"Remove": löscht endgültig. Kein Papierkorb, keine Rückfrage.
$ rm sus.txt # eine Datei löschen $ rm -rf log # ganzen Ordner rekursiv löschen, ohne Nachfrage (force)
rm -rf /var/log würde die echten Server-Logs löschen, rm -rf ~ dein komplettes Home-Verzeichnis, rm -rf / das ganze System. Der alte Foren-"Gag", Anfängern genau das zu empfehlen, ist so gemein wie wirksam. Vor jedem rm -rf zweimal auf den Pfad schauen (14:29).04 Dateien ansehen, bearbeiten, durchsuchen
Das Übungsobjekt im Kurs: auth.log, das SSH-Login-Protokoll des Servers, voll mit echten Einbruchsversuchen von Bots.
cat8:30Gibt den kompletten Inhalt einer Textdatei ins Terminal aus.
$ cat auth.log $ cat sus.txt $ cat top_attackers.sh $ cat id_hostinger.pub # öffentlichen SSH-Schlüssel anzeigen
Bei riesigen Dateien scrollt alles durch und du siehst nur das Ende. Dann lieber less oder nano.
nano9:06Einsteigerfreundlicher Texteditor im Terminal. Speichern und Beenden: Ctrl+X, dann Y, dann Enter.
$ nano auth.log $ nano ~/.bashrc $ nano top_attackers.sh $ nano config # SSH-Config auf dem Mac (Niklas nimmt vim, empfiehlt dir nano)
less12:11Read-Only-Ansicht zum bequemen Blättern: nicht zum Arbeiten, nur zum Angucken. Beenden mit q.
$ less sus.txt
vim36:48Niklas' Lieblingseditor, "von der Bedienung her ein bisschen weniger intuitiv". Seine Empfehlung für Einsteiger: nimm ruhig nano stattdessen.
$ vim config
grep9:49Durchsucht Text nach einem Muster, "super nützlich, gerade um Logs zu durchsuchen".
$ grep Apfelkuchen auth.log # findet den eingeschmuggelten Testsatz $ grep 123.20.181.121 auth.log # alle Zeilen mit dieser IP-Adresse $ grep -c 123.20.181.121 auth.log # -c zählt nur die Treffer: 44 $ grep top3a .bashrc # auch praktisch: Config-Dateien durchsuchen $ ls -hl / | grep root$ # $ = Zeile endet mit "root" (Regex)
Den Parameter -c entdeckt Niklas live in der Anleitung: man grep.
man10:44"Manual": die eingebaute Bedienungsanleitung zu fast jedem Befehl. Blättern mit den Pfeiltasten, raus mit q.
$ man fail2ban $ man grep
man befehl. Da stehen alle Parameter, wie das -c bei grep.file20:44Verrät, was für ein Dateityp etwas ist.
$ file .bashrc .bashrc: ASCII text
Nebenbei die Lektion: .bashrc taucht bei ls nicht auf. Dateien, die mit einem Punkt beginnen, sind unter Linux versteckt. Sichtbar werden sie mit ls -a (dann siehst du auch .ssh, .bash_history und Co.).
history21:24Zeigt die zuletzt ausgeführten Kommandos, dieselbe Liste, durch die du mit ↑ blätterst.
$ history
05 Software installieren mit apt
"Apt ist sozusagen der App Store für Linux. Linux hat nämlich den App Store erfunden."
apt install10:18Installiert Pakete aus den Ubuntu/Debian-Quellen.
$ apt install fail2ban # sperrt IPs nach mehreren falschen Passwörtern $ apt install sl # die Steam-Lokomotive (siehe Block 10)
auth.log zeigt hunderte Passwort-Rateversuche von Bots. fail2ban blockt solche IPs automatisch nach ein paar Fehlversuchen. Die Standardeinstellungen reichen für den Anfang. (Auf fremden Anleitungen siehst du oft sudo apt install …: im Kurs entfällt das sudo, weil direkt als root gearbeitet wird.)06 Pipes und Umleitungen
Das Herzstück des Kurses: kleine Befehle zu mächtigen Ketten zusammenstecken. "Mit Pipes kann man sehr viel machen in der Kommandozeile."
Lenkt die Ausgabe eines Befehls in eine Datei. Existiert sie schon, wird sie kommentarlos überschrieben.
$ grep 123.20.181.121 auth.log > ~/sus.txt $ echo "apfelkuchen" > sus.txt # zack, alles Vorherige weg. "Willkommen bei Linux."
Wie >, aber hängt unten an, statt zu überschreiben. "Das verwende ich schon relativ oft."
$ grep 123.20.181.121 /var/log/auth.log >> ~/sus.txt
Der erste Versuch schlägt im Kurs fehl ("No such file or directory"), weil er im falschen Verzeichnis steht: deswegen hier der absolute Pfad zur Log-Datei.
echo12:39Gibt Text aus. In Kombination mit > der schnellste Weg, etwas in eine Datei zu schreiben, und in Skripten das Mittel für Ausgaben.
$ echo "apfelkuchen" > sus.txt
Der klassische Pipe-Operator: gibt den Output eines Kommandos nicht in eine Datei, sondern an das nächste Kommando weiter.
$ cat /var/log/auth.log | grep "Failed password" $ ps aux | grep sshd # läuft der SSH-Daemon? Sehr beliebtes Praxis-Beispiel
awk16:18Schneidet Spalten aus Zeilen. NF ist die Anzahl der Felder, $(NF-3) also das viertletzte Feld, genau dort steht in den "Failed password"-Zeilen die IP-Adresse.
$ cat /var/log/auth.log | grep "Failed password" | awk '{print $(NF-3)}'
Im Kurs geht der erste Versuch schief ('print {$(NF-3)}', Klammer an der falschen Stelle). Die geschweifte Klammer muss um das ganze print herum: '{print $(NF-3)}'.
Die drei Helfer für Auswertungen in der Pipe:
$ … | sort # sortiert die Zeilen (gruppiert gleiche IPs untereinander) $ … | uniq -c # fasst direkt aufeinanderfolgende Duplikate zusammen und zählt sie $ … | sort -nr # numerisch (-n) und absteigend (-r) sortieren $ … | head -n3 # nur die ersten 3 Zeilen
uniq erkennt nur benachbarte Duplikate. Ohne vorheriges Sortieren würden verstreute Einträge derselben IP mehrfach gezählt.Die Top-3-Angreifer-Pipeline17:53Alles zusammengesteckt, "schöne Terminal-Magic": Welche 3 IP-Adressen haben am häufigsten versucht, sich einzuloggen?
$ cat /var/log/auth.log | grep "Failed password" | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head -n3 87 101.132.128.224 56 144.76.70.84 21 123.20.181.121
Lies die Kette von links nach rechts: Log ausgeben → auf Fehlversuche filtern → IP-Spalte ausschneiden → sortieren → zählen → nach Anzahl absteigend sortieren → Top 3 behalten.
07 Aliase und die .bashrc
Lange Befehle will niemand zweimal tippen. Ein Alias macht aus der Riesen-Pipeline ein Mini-Kommando.
alias18:02Definiert ein eigenes Kürzel. Die Anführungszeichen und das Dollarzeichen in der Pipeline müssen mit Backslash escaped werden, sonst wertet die Shell sie sofort aus statt sie zu speichern:
$ alias top3attackers="cat /var/log/auth.log | grep \"Failed password\" | awk '{print \$(NF-3)}' | sort | uniq -c | sort -nr | head -n3" $ top3attackers
\$ würde $(NF-3) sofort als Kommando ausgeführt (im Kurs die Fehlermeldung "NF-3: command not found").~/.bashrc19:23Ein Alias gilt nur für die aktuelle Session. Neues Terminal → "command not found". Dauerhaft wird er erst über die Config-Datei der Shell:
$ nano ~/.bashrc # ans Ende der Datei: alias top3a="cat /var/log/auth.log | grep \"Failed password\" | awk '{print \$(NF-3)}' | sort | uniq -c | sort -nr | head -n3" # speichern: Ctrl+X, Y, Enter. Ab dem nächsten Terminal: $ top3a
.bashrc = für immer. Die Datei ist versteckt (Punkt am Anfang) und wird bei jedem Terminal-Start ausgeführt.08 Bash-Skripte: vom Befehl zum Programm
"Hier verschwimmen die Grenzen von der Computernutzung bis hin zur Programmierung." Aus dem Alias wird ein richtiges Skript.
top_attackers.sh22:04Mit nano top_attackers.sh angelegt. So sieht das fertige Skript aus dem Kurs aus:
#!/usr/bin/env bash
echo "Analyzing SSH logs ..."
sleep 1
TOP_N=3
echo
echo "Top ${TOP_N} IP addresses with most failed login attempts:"
echo "--------------------------------------------------------"
cat /var/log/auth.log | grep "Failed password" | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head -n${TOP_N}
echo
echo "Done."
Die Bausteine:
#!/usr/bin/env bash (die "Shebang"-Zeile): sagt dem Computer, womit die Datei ausgeführt werden soll.
sleep 1: eine Sekunde warten, "reine Show".
TOP_N=3: eine Variable, mit ${TOP_N} wieder eingesetzt. Niklas' Ideen-Hinweis: als Parameter übergeben wäre eine coole Erweiterung.
\", \$) haben im Skript nichts verloren. Sie waren nur fürs Escaping innerhalb der Alias-Anführungszeichen nötig. Im Skript erzeugen sie die Fehler "backslash not last character on line" (28:18).Ausführen (erst nach chmod +x, siehe Block 9):
$ ./top_attackers.sh
09 Benutzer und Rechte (Permissions)
Der Block, in dem sich Niklas "erfolgreich die Finger verbrennt": erst 777 auf /root, später rächt sich genau das beim SSH-Login.
whoami24:36Zeigt, als welcher Benutzer du gerade unterwegs bist.
$ whoami root
adduser24:45Legt einen neuen Benutzer an, fragt interaktiv Passwort und Stammdaten ab.
$ adduser niklas
"Switch User": wechselt in eine Shell des anderen Benutzers. exit bringt dich zurück.
root# su niklas niklas$ whoami niklas niklas$ exit # zurück zur root-Shell
Als niklas bedeutet ~ plötzlich /home/niklas, nicht mehr /root. Und cd /root liefert erstmal "Permission denied", genau wie es sein soll.
ls -hl lesen: das rwx-Format23:44Beispielzeile: -rw-r--r-- 1 root root 341 … top_attackers.sh
Erste Stelle: d = Verzeichnis. Danach drei Dreiergruppen: Besitzer, Gruppe, alle anderen, jeweils r (lesen), w (schreiben), x (ausführen). Hier: Besitzer darf lesen und schreiben, alle anderen nur lesen, niemand darf ausführen.
| Recht | Bedeutung | Wert |
|---|---|---|
| r | lesen (read) | 4 |
| w | schreiben (write) | 2 |
| x | ausführen (execute) | 1 |
Die Werte werden pro Gruppe addiert: 7 = 4+2+1 = alles, 6 = lesen+schreiben, 4 = nur lesen. 777 heißt also: jeder darf alles.
"Change Mode": ändert die Rechte, numerisch oder symbolisch.
$ chmod 777 root # jeder darf alles in /root (schlechte Idee!) $ chmod +x top_attackers.sh # Skript ausführbar machen $ chmod 644 /var/log/auth.log # Besitzer rw, alle anderen r $ chmod 700 root # der Fix: nur der Besitzer darf rein
chmod 777 /root verweigert SSH später den Schlüssel-Login, denn wenn jeder ins Verzeichnis schreiben darf, könnte auch jeder fremde Keys in authorized_keys hinterlegen. SSH akzeptiert das erst wieder nach chmod 700 (40:42). Rechte großzügig aufreißen löst kurzfristig Probleme und schafft langfristig größere.10 Prozesse (und die Steam-Lokomotive)
Was läuft gerade auf der Maschine? Und was passiert, wenn man eine Endlosschleife nicht mehr abbrechen kann?
ps aux15:29Listet alle laufenden Prozesse. In Kombination mit grep der Klassiker, um zu prüfen, ob ein Programm läuft:
$ ps aux $ ps aux | grep sshd # läuft der SSH-Daemon? Ja.
Der Linux-Gag für alle, die sich bei ls vertippen: eine ASCII-Dampflok fährt durchs Bild, und man muss "nervig lange warten".
$ apt install sl $ sl $ while true; do sl; done # Lok in Endlosschleife, "wie ein Bildschirmschoner"
sl ignoriert es absichtlich. Die Endlos-Lok legte im Kurs das Web-Terminal lahm, Ausweg war nur der Neustart-Button im Hostinger-Panel (32:08).11 Netzwerk-Befehle
"Auch die Kommandozeile ist ein wunderbarer Weg, das Internet zu benutzen." Untersuchungsobjekt: die Website fokus.so.
ping32:35Prüft, ob ein Host erreichbar ist und wie schnell er antwortet. Stoppen mit Ctrl+C.
$ ping fokus.so
curl32:50Holt eine URL ab und zeigt die Antwort im Terminal.
$ curl fokus.so # liefert hier nur Platzhalter-HTML (Seite rendert per JavaScript) $ curl ifconfig.me # "schönes Kommando": verrät deine eigene öffentliche IP $ curl -4 ifconfig.me # -4 erzwingt IPv4 (ohne kam eine IPv6-Adresse zurück)
dig33:02"Domain Information Groper": löst einen Domainnamen per DNS in die IP-Adresse auf.
$ dig fokus.so
whois33:17Fragt ab, wem eine IP-Adresse oder Domain gehört. Im Kurs führt die Spur der fokus.so-IP nach Litauen, gehostet natürlich bei Hostinger.
$ whois <IP-Adresse>
12 SSH: vom eigenen Rechner auf den Server
Das letzte große Kapitel: raus aus dem Browser-Terminal, rein ins lokale Terminal, per SSH auf den Server, erst mit Passwort, dann mit Schlüssel und Config.
ssh34:23Verbindet dich mit einem entfernten Server. Beim ersten Mal bestätigst du den Fingerprint mit yes.
mac$ ssh [email protected] [email protected]'s password: # Eingabe bleibt unsichtbar, das ist normal!
Später, mit Config und Key, reicht:
mac$ ssh hostinger-kvm2 $ logout # Verbindung beenden (oder exit) mac$ ssh -v hostinger-kvm2 # verbose: zeigt beim Debuggen, was SSH gerade versucht
~/.ssh/config36:36Damit du nicht jedes Mal IP und Nutzer tippst: ein Eintrag in der SSH-Config (angelegt mit nano config bzw. vim im Verzeichnis ~/.ssh, die alte Datei vorher per mv config config.old gesichert).
Host hostinger-kvm2
HostName 72.62.253.243
User root
IdentityFile ~/.ssh/id_hostinger
ssh-keygen37:23Erzeugt ein Schlüsselpaar. Mit -f gibst du Speicherort und Namen an, im Kurs ein eigener Key nur für diesen Server:
mac$ ssh-keygen -f ~/.ssh/id_hostinger
Der erste Versuch mit relativem Pfad (.ssh/id_hostinger) scheiterte mit "No such file or directory", der absolute Pfad mit ~ funktionierte. Ergebnis sind zwei Dateien:
id_hostinger # privater Schlüssel: NIEMALS herzeigen oder verschicken
id_hostinger.pub # öffentlicher Schlüssel: darf jeder sehen, kommt auf den Server
ssh-copy-id38:40Installiert den öffentlichen Schlüssel auf dem Server (in ~/.ssh/authorized_keys). Alternative wäre Copy-Paste über das Hostinger-Panel unter Settings → SSH keys.
mac$ ssh-copy-id -i ~/.ssh/id_hostinger [email protected] # ein letztes Mal Passwort eingeben, danach: "1 key(s) added"
ssh-add39:32Lädt einen privaten Schlüssel in den SSH-Agenten, einer von Niklas' Debug-Versuchen, als der Login trotz Key weiter nach dem Passwort fragte.
mac$ ssh-add ~/.ssh/id_hostinger
Die echte Ursache war serverseitig: die 777-Rechte auf /root aus Block 9. Nach chmod 700 root klappte der Key-Login sofort.
scp42:13"Secure Copy": kopiert Dateien über SSH zwischen Rechner und Server. Dank Config-Eintrag reicht der Kurzname:
mac$ scp hostinger-kvm2:~/top_attackers.sh . # holt das Skript vom Server ins aktuelle Verzeichnis, danach im Finder sichtbar
13 Tastatur-Shortcuts aus dem Kurs
Die Handgriffe, die Niklas ständig nebenbei benutzt. Sie machen den Unterschied zwischen mühsam und flüssig.
Namen vervollständigen statt ausschreiben (4:16)
Durch die letzten Befehle blättern (6:55)
Terminal leeren, entspricht
clear (4:35)Rückwärts in der History suchen, z.B. "Failed password" tippen (15:53)
Laufenden Befehl abbrechen (bei ping ja, bei sl absichtlich nicht) (31:53)
In nano speichern und beenden (9:33)
less und man-Seiten beenden (10:48)