Subsections of Admin / Linux
Gitlab
Subsections of Gitlab
Gitlab in Docker mit SSH Standardport
Im Docker basierten Setup von Gitlab wird ein SSH Daemon mitgeliefert, der im Normalfall aber auf einem anderen Port laufen muss wie der native SSH-Daemon vom Betriebssystem. Möchte man den SSH Daemon von Gitlab öffentlich betreiben und hat nur eine öffentliche IP-Adresse zur Verfügung gibt es verschiedene Möglichkeiten (die letzte wird hier beschrieben):
- Gitlab-SSH auf anderem Port als den des Betriebssystem lauschen lassen
- System-SSH auf anderen Port binden um 22 für Gitlab frei zu räumen
- System-SSH mit Gitlab-SSH verknüpfen (wird hier beschrieben)
Erklärung
Gitlab stellt für den eigenen SSH-Daemon ein Script bereit, das alle registrierten SSH-Keys zurückmeldet. Diese werden vom SSH-Daemon genutzt um zu prüfen, ob ein zu verbindener Klient generell zugelassen werden kann. Dieses vorgehen ist generell beim OpenSSH-Server möglich, nur weiß der des Betriebssystems nichts von Dingen die im Docker Container passieren. Der nötige Befehl wird mittels Wrapper-Script und docker exec
zur Verfügung gestellt, damit der Betriebssystem-SSH-Daemon die Keys abfragen kann. Der Gitlab-Befehl erhält alle nötigen Informationen über die SSH Verbindung um diese für weitere Verarbeitungen heranziehen zu können.
Script und Konfiguration
SSH-Daemon Konfiguration
Zunächst benötigen wir einen System-Benutzer git der im Regelfall in der Distribution bereits angelegt ist. Der Pfad zum Script kann angepasst werden, falls man docker-volumes nutzt und das Script lieber wo anders liegen haben möchte (z.B. /usr/local/bin/). Im SSH-Daemon wird folgendes konfiguriert:
# File: /etc/ssh/sshd_config
Match User git
AuthorizedKeysCommand /srv/docker/containers/gitlab/scripts/gitlab_authorized_keys
# muss root sein, weil das gitlab_authorized_keys root:root gehoert!
AuthorizedKeysCommandUser root
Es bietet sich an die bestehende Verbindung nicht zu trennen, bevor nach dem Restart ein erfolgreicher Verbindungsaufbau durchgeführt wurde! Falsche Konfigurationen in der sshd_config können zum Aussperren führen…
systemctl restart sshd.service
Gitlab Authorized-Keys
Dieses Script wird vom SSH-Daemon initial abgerufen um die Keys zu lesen. Es ist wichtig, dass der Pfad angepasst wird, je nachdem wo euer Gitlab seine Daten speichert. Dies kann z.B. auch ein Docker Volume sein (/var/lib/docker/volumes/ghitlab/data/.ssh/authorized_keys).
Das verwendete Script enthält folgendes:
# File /srv/docker/containers/gitlab/scripts/gitlab_authorized_keys
#!/bin/bash
# docker exec -u git gitlab cat /var/opt/gitlab/.ssh/authorized_keys
f="/srv/docker/containers/gitlab/data/.ssh/authorized_keys"
if [[ -f "${f}" ]];then
cat /srv/docker/containers/gitlab/data/.ssh/authorized_keys
fi
In dem authorized_keys File von Gitlab stehen alle gültigen SSH Keys, allerdings wird beim Verbinden das Ausführen eines Scripts erzwungen (siehe command=…):
# File: /srv/docker/containers/gitlab/data/.ssh/authorized_keys
command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell key-1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3Nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
Gitlab-Shell Wrapper-Script
Somit wird unser SSH-Daemon dieses Script ausführen wollen. Deshalb legen wir unser Wrapper-Script an den gewünschten Ort (/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell):
# File: /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell
#!/bin/bash
docker exec -u git -i -e SSH_CONNECTION="$SSH_CONNECTION" -e SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitlab /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell $*
Wichtig sind noch die Berechtigungen. Diese sollten noch korrigiert werden um sicherzustellen, dass nur git das Skript ausführen kann.
chown git:git /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell
chmod 0750 /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell
Außerdem muss der git-Benutzer noch in die Gruppe docker, damit er auf den Docker-Socket zugreifen kann (docker exec …):
usermod -a -G docker git
Test der Funktion
Mit funktionierendem Agent / SSH-Key:
git clone git@my.gitlab.server.com:repo/something.git
Sollte etwas nicht funktionieren kann im Journal nachgesehen werden:
journalctl -u sshd.service -f
Links
Linux
Subsections of Linux
How To
Subsections of How To
ASDF Nutzung und Beispiele
Die hier installierten Versionen können bereits morgen veraltet sein. Am besten die möglichen Versionen auflisten lassen und entsprechend des Bedarfs installieren…
Befehle
Versionen eines Plugins anzeigen
asdf list all <NAME>
asdf list all golang
asdf list all python
Plugins
Python
Es werden ggf. weitere Anwendungen wie z.B. make benötigt, beim Einrichten werden aussagekräftige Fehlermeldungen ausgegeben…
asdf plugin add python https://github.com/asdf-community/asdf-python.git
asdf install python 3.12.2
asdf global golang 3.12.2
Golang
asdf plugin add golang https://github.com/asdf-community/asdf-golang.git
asdf install golang 1.22.0
asdf global golang 1.22.0
Hardware und Details via CLI-Tools ermitteln
Mit leichtgewichtigen Tools erhält man viel Informationen zur genutzten Hardware. Es braucht nicht immer große Software-Pakete oder gar GUIs ;)
Die Befehle werden mit root-Rechten ausgeführt. Nutze “sudo” oder su (switch user), wenn du nicht als root eingeloggt bist.
CPU / Prozessor
lscpu
Architektur: x86_64
CPU Operationsmodus: 32-bit, 64-bit
Byte-Reihenfolge: Little Endian
Adressgrößen: 39 bits physical, 48 bits virtual
CPU(s): 8
Liste der Online-CPU(s): 0-7
Thread(s) pro Kern: 2
Kern(e) pro Sockel: 4
Sockel: 1
NUMA-Knoten: 1
Anbieterkennung: GenuineIntel
Prozessorfamilie: 6
Modell: 94
Modellname: Intel(R) Xeon(R) CPU E3-1260L v5 @ 2.90GHz
Stepping: 3
CPU MHz: 900.140
Maximale Taktfrequenz der CPU: 3900,0000
Minimale Taktfrequenz der CPU: 800,0000
BogoMIPS: 5802.42
Virtualisierung: VT-x
L1d Cache: 128 KiB
L1i Cache: 128 KiB
L2 Cache: 1 MiB
L3 Cache: 8 MiB
NUMA-Knoten0 CPU(s): 0-7
Vulnerability Itlb multihit: KVM: Mitigation: VMX disabled
Vulnerability L1tf: Mitigation; PTE Inversion; VMX conditional cache flushes, SMT vulnerable
Vulnerability Mds: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Meltdown: Mitigation; PTI
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2: Mitigation; Full generic retpoline, IBPB conditional, IBRS_FW, STIBP conditional, RSB filling
Vulnerability Srbds: Mitigation; Microcode
Vulnerability Tsx async abort: Mitigation; Clear CPU buffers; SMT vulnerable
Markierungen: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx
est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2
smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d
Block-Devices (Festplatten, SSDs, NVMEs)
Mit lsblk können eine Vielzahl von Informationen abgerufen werden (–output). Eine Liste erhält man mit (-h|–help).
Der Parameter –nodeps (-d) sorgt dafür, dass man nur “Hauptgeräte” wie Festplatten, aber keine Partitionen, RAIDs, LVMs angezeigt bekommt.
ROTA
zeigt an, ob das Gerät rotierende Teile hat (Festplatten).
lsblk --output name,model,serial,rota --nodeps
NAME MODEL SERIAL ROTA
sda SAMSUNG_MZ7KM1T9HAJM-00005 S2XXXXXXXXXXXX 0
sdb SAMSUNG_MZ7KM1T9HAJM-00005 S2XXXXXXXXXXXX 0
sdc WDC_WD80EFZX-68UW8N0 xxxxxxxx 1
sdd WDC_WD30EFRX-68EUZN0 WD-WMCxxxxxxxxx 1
sde WDC_WD30EFRX-68EUZN0 WD-WMCxxxxxxxxx 1
sdf WDC_WD30EFRX-68EUZN0 WD-WMCxxxxxxxxx 1
sdg WDC_WD30EFRX-68EUZN0 WD-WMCxxxxxxxxx 1
S.M.A.R.T. Werte von Block Devices
Ist der Health-Status, die Menge der Lesefehler oder Laufzeit relevant, ist das Auslesen der SMART-Werte von nöten. Alle gängigen Distributionen halten hierfür Pakete bereit. Unter Archlinux und Ubuntu nennt dieses sich smartmontools.
# Ubuntu
apt update && apt install smartmontools
# Archlinux
pacman -Syu smartmontools
smartctl -a /dev/sda
smartctl 7.4 2023-08-01 r5530 [x86_64-linux-5.15.81-1-lts] (local build)
Copyright (C) 2002-23, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Model Family: Samsung based SSDs
Device Model: SAMSUNG xxxxxx-xxxxxxx
Serial Number: xxxxxxxxxxxxxxxxxxxx
LU WWN Device Id: 5 xxxxx xxxxxxxxx
Firmware Version: xxxxxxx
User Capacity: 1.920.383.410.176 bytes [1,92 TB]
Sector Size: 512 bytes logical/physical
Rotation Rate: Solid State Device
TRIM Command: Available, deterministic, zeroed
Device is: In smartctl database 7.3/5528
ATA Version is: ACS-2, ATA8-ACS T13/1699-D revision 4c
SATA Version is: SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is: Sat Feb 3 20:36:53 2024 CET
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
..........
SMART Attributes Data Structure revision number: 1
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct 0x0033 100 100 010 Pre-fail Always - 0
9 Power_On_Hours 0x0032 089 089 000 Old_age Always - 51508
12 Power_Cycle_Count 0x0032 099 099 000 Old_age Always - 36
177 Wear_Leveling_Count 0x0013 099 099 005 Pre-fail Always - 82
179 Used_Rsvd_Blk_Cnt_Tot 0x0013 100 100 010 Pre-fail Always - 0
180 Unused_Rsvd_Blk_Cnt_Tot 0x0013 100 100 010 Pre-fail Always - 15335
181 Program_Fail_Cnt_Total 0x0032 100 100 010 Old_age Always - 0
182 Erase_Fail_Count_Total 0x0032 100 100 010 Old_age Always - 0
183 Runtime_Bad_Block 0x0013 100 100 010 Pre-fail Always - 0
184 End-to-End_Error 0x0033 100 100 097 Pre-fail Always - 0
187 Uncorrectable_Error_Cnt 0x0032 100 100 000 Old_age Always - 0
190 Airflow_Temperature_Cel 0x0032 060 052 000 Old_age Always - 40
195 ECC_Error_Rate 0x001a 200 200 000 Old_age Always - 0
197 Current_Pending_Sector 0x0032 100 100 000 Old_age Always - 0
199 CRC_Error_Count 0x003e 099 099 000 Old_age Always - 1
202 Exception_Mode_Status 0x0033 100 100 010 Pre-fail Always - 0
235 POR_Recovery_Count 0x0012 099 099 000 Old_age Always - 24
241 Total_LBAs_Written 0x0032 099 099 000 Old_age Always - 180868725074
242 Total_LBAs_Read 0x0032 099 099 000 Old_age Always - 135827340303
243 SATA_Downshift_Ct 0x0032 100 100 000 Old_age Always - 0
244 Thermal_Throttle_St 0x0032 100 100 000 Old_age Always - 0
245 Timed_Workld_Media_Wear 0x0032 100 100 000 Old_age Always - 65535
246 Timed_Workld_RdWr_Ratio 0x0032 100 100 000 Old_age Always - 65535
247 Timed_Workld_Timer 0x0032 100 100 000 Old_age Always - 65535
251 NAND_Writes 0x0032 100 100 000 Old_age Always - 232084360256
..........
PCI Devices
Je genauer die Ausgabe sein soll, desto mehr “-v”.
Nach Menge der Ausgabe lohnt sich die Umleitung in eine Datei, oder nach less, um den Inhalt in Ruhe lesen zu können…
lspci
lspci -v
lspci -vvvvv | less
lspci -vvvvv > pci.out; less pci.out
USB Devices
Das gleich Prozedere wie bei PCI-Devices…
lsusb
Mainboard, RAM, Prozessor, BIOS
dmidecode
biosdecode
Links
Linux Betriebssystem migrieren (remote & lokal)
Binär-Dump war gestern. Linux migrieren mit Rsync (remote und lokal).
Vorwort
Um ein Betriebssystem (Linux basiert) mit Daten auf einen anderen Host, oder eine andere Festplatte zu synchronisieren und wieder lauffähig zu machen, gibt es viele Herangehensweisen.
In dieser Anleitung soll dies Anhand eines Ubuntus und rsync veranschaulicht werden.
Die folgenden Szenarien werden beleuchtet:
- Ubuntu soll auf eine andere Festplatte kopiert und im Anschluss von dieser gebootet werden
- eine lokal laufende Maschine soll auf einen Remote Host kopiert werden
In beiden Fällen wird die Migration mithilfe von GRML durchgeführt. Hierbei handelt es sich um eine Live-CD (auf Basis von Debian) die kostenfrei heruntergeladen und genutzt werden kann: https://grml.org/download/ Grundsätzlich funktioniert diese Anleitung aber auch mit Ubuntu, Arch Linux, oder anderen ISO.
Alle hier gezeigten Schritte müssen mit Sinn und Verstand durchgeführt werden.
Beim verdrehen von Parametern oder falscher Anwendung droht Datenverlust!
Ich schließe jegliche Haftung aus und rate dazu die offiziellen Dokumentationen der Software zu lesen um ein tieferes Verständnis für die Anwendung zu erlangen.
Kopieren einer lokalen Installation auf weitere Festplatte
Prinzipiell kann die Kopie auch im gebooteten Zustand des originalen Betriebssystems erfolgen.
Ich rate hierbei allerdings davon ab, weil sich während des Betriebs Daten ändern können.
Eine saubere Übertragung erreicht man, wenn ein Live-System gebootet wurde und das Quellsystem nicht in Nutzung ist!
Die Festplatten werden wie folgt gemappt:
- sda (alt)
- sdb (neu)
neue Festplatte Partitionieren
Die Partitionstabelle kann kopiert und wieder eingespielt werden. Falls GPT verwendet wird, müssen die UUIDs ersetzt werden!
sfdisk -d /dev/sda > part_table
grep -v ^label-id part_table | sed -e 's/, *uuid=[0-9A-F-]*//' -i part_table | sfdisk /dev/sdb
In manchen Fällen kann die neue Platte auch größer, oder kleiner ausfallen.
In diesem Fall kann die Partitionierung auch manuell durchgeführt werden. Ob GPT oder MSDOS hängt vom persönlichen Geschmack ab.
Im Hinblick auf stetig größer werdende Speichermedien bietet sich die Verwendung von GPT aber an.
parted -s /dev/sdb mklabel gpt
parted -s /dev/sdb mkpart "EFI system partition" fat32 1MiB 261MiB
parted -s /dev/sdb set 1 esp on
parted -s /dev/sdb mkpart primary 261MiB 100%free
Dateisystem erzeugen und mounten
Hier wird davon ausgegangen, dass die zweite Partition der alten Festplatte das / (rootfs) bereitstellt.
Falls noch andere Mountpoints auf der Platte existieren, müssen diese im Nachgang eingegangen werden!
mkfs.ext4 /dev/sdb2
mkdir -p /mnt/{old,new}
mount /dev/sda2 /mnt/old
# optional (falls weitere Mountpoints!)
# mount /dev/sda3 /mnt/old/home
# mount /dev/sda5 /mnt/old/var
mount /dev/sdb2 /mnt/new
Dateien synchronisieren
Bitte unbedingt auf die abschließenden Slashes ("/") bei den Ordnern achten!
rsync -aHv --numeric-ids /mnt/old/ /mnt/new/
FStab korrigieren
Aufgrund der neuen UUIDs der Dateisysteme auf der neuen Platte, müssen diese in der FSTab hinterlegt werden. Die UUIDs ermittelt man wie folgt:
blkid
/dev/sda2: UUID="823779fc-3231-4189-8a64-eee8e2d616e0" BLOCK_SIZE="4096" TYPE="ext4"
/dev/sdb2: UUID="aa6c1ffb-c522-4620-b4a5-dc45da6f2613" BLOCK_SIZE="4096" TYPE="ext4"
Je nach Menge der Mountpoints kann die Liste deutlich länger sein.
Alle Einträge der FSTab müssen dann berücksichtigt werden.
# File-Name: /mnt/new/etc/fstab
# vor Änderung UUID=823779fc-3231-4189-8a64-eee8e2d616e0 (sda2)
UUID=aa6c1ffb-c522-4620-b4a5-dc45da6f2613 / ext4 rw,relatime 0 0
# hier ggf. die weiteren Mountpoints hinterlegen
UUID=00000000-0000-0000-0000-000000000000 /home ext4 rw,relatime 0 0
Chroot, Installation von Grub
Für die Installation von Grub auf die neue Festplatte sind verschiedene Laufzeit-Ordner notwendig, die System-Dateien der Live-Umgebung, aber auch Block-Devices (z.B. /dev/sd*) bereitstellen.
Abschließend betritt man mit seiner Shell die Kopie des System auf der neuen Festplatte und installiert Grub auf selbiger.
# mounten der notwendigen Ordner
for i in proc sys dev run;do
mount --bind /$i /mnt/new/$i
done
# Wechsel der Shell
chroot /mnt/new /bin/bash
# Grub Konfiguration generieren
update-grub
# Grub auf neuer Festplatte installieren
grub-install /dev/sdb
# Chroot verlassen
exit
# herunterfahren
shutdown -h now
Nach dem Herunterfahren kann die alte Festplatte abgeschlossen und von der neuen gebootet werden.
Kopieren einer lokalen Installation auf Remote Host
Grundsätzlich verhält sich das Kopieren auf einen Remote Host, wie die lokale Variante.
Aufgrund der Tatsache dass die UUIDs der Dateisysteme sich doppeln dürfen und diese nur lokal eindeutig sein müssen, kann die Einrichtung etwas vereinfacht werden.
Zunächst liest man die UUIDs der Quell-Partitionen aus, denn diese werden wiederverwendet, damit man die FStab auf dem Remote-Host nicht korrigieren muss (bei gleicher Partitionsstruktur):
blkid
/dev/sda1: UUID="fcfca092-1654-1094-affd-a0293affcdee" BLOCK_SIZE="4096" TYPE="ext4"
/dev/sda2: UUID="01938725-dfea-cddc-ffff-0582aefc3a1a" BLOCK_SIZE="4096" TYPE="ext4"
Partitionierung übertragen
sfdisk -d /dev/sda > part_table
# Die Ausgabe wird durch den StdOut-Kanal und mittels SSH auf den Remote-Host gesendet. Die Ausgabe wird mittels Pipe an sfdisk geleitet
grep -v ^label-id part_table | sed -e 's/, *uuid=[0-9A-F-]*//' -i part_table | ssh root@my.remote.host 'cat - | sfdisk /dev/sdb'
Dateisystem(e) anlegen
# Dateisystem mit der alten UUID auf Remote-Host anlegen
mkfs.ext4 -U fcfca092-1654-1094-affd-a0293affcdee /dev/sda1
mkfs.ext4 -U 01938725-dfea-cddc-ffff-0582aefc3a1a /dev/sda2
Dateisystem(e) mounten
mount /dev/sda2 /mnt/
mkdir /mnt/boot
mount /dev/sda1 /mnt/boot
# optional (falls weitere Mountpoints!)
# mount /dev/sda3 /mnt/home
# mount /dev/sda5 /mnt/var
Dateien synchronisieren
rsync -aHv --numeric-ids / root@my.remote.host:/mnt/
Chroot, Installation von Grub
# mounten der notwendigen Ordner
for i in proc sys dev run;do
mount --bind /$i /mnt/$i
done
# Wechsel der Shell
chroot /mnt/ /bin/bash
# Grub Konfiguration generieren
update-grub
# Grub auf Festplatte installieren
grub-install /dev/sda
# Chroot verlassen
exit
# neu starten
reboot
Links
ZFS auf Arch Linux installieren / updaten
Vorwort
Durch fehlerhafte Konfiguration kann das System in einen nicht bootbaren Stand geraten!
Vor einem Reboot sollten alle Probleme gelöst werden!
Aufgrund der Lizenz von ZFS ist eine native Integration in den Linux Kernel nicht möglich.
Deshalb gibt es diverse Projekte die eine nachträgliche Installation ermöglichen.
In diesem Beispiel wird das ZFS Linux Modul und die damit verbundenen Tools aus dem AUR installiert.
Hierbei wird ZFS mit seinem Tools aus dem Quellcode kompiliert, was je nach Hardware mehrere Minuten dauern kann.
Dabei ist zu beachten, dass bei jedem Kernel Update das ZFS-Paket erneut gebaut werden muss um zur Kernel-Version zu passen!
Es ist daher empfehlenswert den Linux-LTS Kernel zu verwenden und das Paket zu pinnen, damit nicht jedes Update durchgeführt wird.
Das ZFS Paket aus dem AUR kann auch kurzzeitig nicht auf den neuen Kernel angepasst sein und dann nicht ohne Anpassungen installiert werden…
Installation
Zuerst wird linux-lts und die entsprechenden Header installiert. Das Paket linux sollte gelöscht werden:
sudo pacman -Syu linux-lts linux-lts-headers
sudo pacman -R linux linux-headers
yay -S zfs-linux-lts
sudo mkinitcpio -p linux-lts
Beim Tausch von Linux zu Linux-LTS muss der bootloader angepasst werden. Dieser kann sehr unterschiedlich sein.
Bei Nutzung von Grub:
sudo grub-mkconfig -o /boot/grub/grub.cfg
Paket Pinning
In der Datei /etc/pacman.conf
die Zeile IgnorePkg wie folgt ergänzen:
IgnorePkg = linux-lts linux-lts-headers
Dadurch werden Updates ignoriert und die Pakete nicht automatisch mit aktualisiert. Updates müssen dann erzwungen werden, wobei dies in Zusammenspiel mit dem Update des zfs-linux-lts Pakets passieren muss.
Updates
Weil das Paket zfs-linux-lts auf eine bestimmte Kernel-Version gepinnt ist, kann ein Update etwas komplizierter sein.
Denn das aktuell installierte Kernel-Paket wird vom aktuellen ZFS benötigt, ZFS kann aber nicht aktualisiert werden, weil es eine neuere Kernel-Version benötigt (Henne-Ei-Problem).
Deshalb muss zunächst das ZFS Paket gelöscht werden, der Kernel aktualisiert und dann ZFS re-installiert werden:
yay -R zfs-linux-lts zfs-utils
sudo pacman -Syu linux-lts linux-lts-headers
yay -S zfs-linux-lts
sudo mkinitcpio -p linux-lts
Links
Security
Subsections of Security
LUKS Volume mit USB Keystick verknüpfen
Diese Anleitung setzt eine bestehende Installation mit LUKS voraus.
Die Installation wird hier nicht vorgenommen.
Idee
Es wird ein neuer Schlüssel zum LUKS Container hinzugefügt und dieser auf einer beliebigen Position eines USB Stick gespeichert. Beim Booten wird dieser dann ausgelesen und zum Öffnen der verschlüsselten Festplatte genutzt.
Hinweise
Wichtig zu wissen ist, sofern die /boot Partition nicht verschlüsselt ist, die Position des Schlüssels ausgelesen werden kann, da diese in der grub.cfg und ggf. im Init-RamFS liegt, sofern man in der Crypttab weitere Dateisysteme mit dem USB-Stick öffnen möchte.
Möchte man dies umgehen, ist die Verschlüsselung der /boot Partition nötig und eine Eingabe des Kennworts im Bootloader (z.B. Grub) nötig.
Dieses Szenario wird hier nicht thematisiert, kann aber genau so konfiguriert werden.
Durch die Passwort-Eingabe im Bootload wird /boot geöffnet, “/” und ggf. weitere Volumes werden dann über den Schlüssel des USB-Sticks geöffnet.
- Archlinux
- Debian / Ubuntu
- in der Regel auch andere Distributionen (mit Anpassungen)
Konfiguration
Software installieren
pacman -Syu ntfs-3g parted
apt-get update && apt-get install ntfs-3g parted
Partitionierung
Es wird eine Partitionstabelle und eine Partition angelegt und mit NTFS formatiert. Dies kann hilfreich sein, damit Dritte, wenn Sie den USB-Stick irgendwo anschließen, ggf. ein Dateisystem angezeigt bekommen und keinen Verdacht schöpfen.
Hierbei muss persönlich abgewogen werden, ob man das Dateisystem vorher noch mit Daten vollschreibt, oder den -f Parameter deaktiviert um das gesamte Dateisystem zu initalisieren.
Je nach Tiefe einer USB-Stick Analyse könnte der Key so ermittelt werden.
# Partitionstabelle anlegen um eine Partition mit Fake Dateisystem zu erzeugen
parted -s /dev/sdc mklabel msdos
# Partition anlegen
parted -s /dev/sdc mkpart primary 1m 100%free
# NTFS Dateisystem erzeugen (kann aber auch jedes andere FS sein!)
# -f aktiviert den Schnellmodus
mkfs.ntfs -f /dev/sdc1
# UUID der Partition (PARTUUID) auslesen (wird später benötigt!)
# blkid | grep sdc
/dev/sdc1: BLOCK_SIZE="512" UUID="xxxxxxxxxxxxxxxx" TYPE="ntfs" PARTUUID="xxxxxxxx-01"
Schlüssel erzeugen und auf USB Stick schreiben
Der Schlüssel wird in diesem Beispiel 4096 Bit groß und in die Datei /root/keyfile geschrieben.
dd liest einen Block von 4096 Bytes aus der Datei /dev/random und schreibt diesen in das Keyfile.
Danach wird mit dd das Keyfile gelesen und an eine beliebige Stelle der Partition geschrieben.
Hierbei ist die Blocksize wieder 4096, aber mittels seek wird bestimmt, wie viele Blocksizes übersprungen werden sollen.
In diesem Beispiel sind es 1234 * 4096 Bytes, bedeutet es wird ab der Position (4194304. Byte geschrieben. - 4194304 / 1024 (Byte/KiByte)/ 1024 (KiByte / MiByte) / 1024 (MiByte / GiByte) - wodurch der Stick mindestens 4 GiByte groß sein muss …).
Bei einem kleineren USB Stick kann auch ein Wert wie zum Beispiel 7 verwendet werden.
Die Verschiebung (Offset) ist aber im späteren Verlauf wichtig und sollte sich notiert werden!
# neuen Schlüssel erzeugen erzeugen
dd if=/dev/random of=/root/keyfile bs=4096 count=1
# Keyfile auf Partition schreiben
dd of=/dev/sdc1 if=/root/keyfile bs=4096 seek=1234
Key zu LUKS hinzufügen
Es wird angenommen, dass /dev/sda2 die verschlüsselte Systempartition ist.
Diese kann je nach lokaler Konfiguration (HDD,SSD, NVME, RAID, LVM, …) abweichen!
Unbedingt auf die korrekten Werte beim skip achten, der dem seek Wert beim Schreiben auf den USB-Stick entspricht.
# aktuelle Slotbelegung ausgeben
cryptsetup luksDump /dev/sda2
# Keyfile als Schlüssel hinzufügen
cryptsetup luksAddKey /dev/sda2 /root/keyfile
# erneut Slotbelegung ausgeben und ermitteln, welcher dazu gekommen ist
cryptsetup luksDump /dev/sda2
# testen des Keys (ermittelter Slot, z.B. 5)
cryptsetup luksOpen --test-passphrase --key-slot 5 /dev/sda2 -d <(dd if=/dev/sdc1 bs=4096 count=1 skip=1234)
Host Konfiguration anpassen
optionale Nutzung von Crypttab
NAME UUID=DISK_UUID /dev/disk/by-partuuid/xxxxxxxx-01 luks,tries=3,keyfile-size=4096,keyfile-offset=4194304
Grub Konfiguration
# UUID der Partition prüfen, diese wurde bereits am Anfang der Anleitung ermittelt. Nun wird noch mal geprüft ob diese stimmt:
ls -hla /dev/disk/by-partuuid/xxxxxxxx-01
lrwxrwxrwx 1 root root 10 16. Nov 22:57 /dev/disk/by-partuuid/xxxxxxxx-01 -> ../../sdc1
# Grub konfigurieren, der Syntax ist wie folgt:
# cryptkey=$PFAD_ZUR_PARTITION$:$SEEK_BYTES:$KEYSIZE
# Die SEEK_BYTES = seek * key_size (z.B. 1234 * 4096 =
/etc/default/grub
cryptkey=/dev/disk/by-partuuid/xxxxxxxx-01:4194304:4096
Grub Konfiguration generieren
grub-mkconfig -o /boot/grub/grub.cfg
update-grub
Initramfs generieren
# -p linux oder -p linux-lts, je nachdem welches Paket installiert ist
mkinitcpio -p linux
update-initramfs -k all -u
salted SHA512 Passwort Hashes generieren
Hier ein paar Möglichkeiten wie man einfach Passwort-Hashes generieren lassen kann, viele nativ ohne Installation von Paketen.
Oft wird mkpasswd vorgeschlagen, was sich aber nicht auf jeder Distribution gleich verhält, daher ein paar praktische Alternativen.
Python
python -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))'
# oder in der Shell als Alias
alias gen_sha512="python -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))'"
OpenSSL
Sollte im Regelfall bereits installiert sein, weil es für SSL/TLS Verbindungen benötigt wird.
openssl passwd -6
# oder mit festgelegtem Salt
openssl passwd -6 --salt ABCDEF
mkpasswd
Funktioniert mit Debian / Ubuntu
apt update
apt install whois
mkpasswd -m sha-512
# oder wenn der salt selbst bestimmt werden soll
mkpasswd -m sha-512 --salt=abcdefgh
HTPasswd
Manche Distributionen ziehen verhältnismäßig viele Abhängigkeiten nach, weswegen diese Option nicht immer attraktiv ist.
Einfach selber entscheiden ob die anderen Wege nicht sinnvoller sind.
Außerdem existiert die Option erst in Apache >= 2.5 (https://httpd.apache.org/docs/trunk/programs/htpasswd.html).
htpasswd -n -d -5 $USERNAME
transparent verschlüsselte VMs mit Libvirt
Vorwort
Diese Anleitung soll einen kurzen Überblick ermöglichen, wie mittels Libvirt und LUKS Images virtueller Maschinen verschlüsseln kann.
Hierbei findet die Verschlüsselung nicht in der virtuellen Maschine selbst statt, sondern wird außerhalb angewendet, sodass das Gastsystem nichts von der Verschlüsselung mitbekommt (transparent).
Somit ist keine VNC- / Spike- / serielle Verbindung beim booten, oder gar ein Dropbear Server von nötigen um das Gastsystem zu booten.
Libvirt vorbereiten
Secret anlegen
Zuerst muss ein Kennwort (bzw. ein Keyfile) generiert werden, was zum Öffnen des LUKS-Containers genutzt wird. Jedes Image hat zwar in seiner Struktur einen individuellen Schlüssel mit dem die symmetrische Verschlüsselung realisiert wird, allerdings muss eben jener mittels Keyfile geöffnet werden.
# UUID generieren und in Variable UUID speichern
UUID=$(uuidgen)
# Anlegen der Datei mysecret.xml mit Nutzung der UUID Variablen
cat <<EOF > mysecret.xml
<secret ephemeral='no' private='yes'>
<description>my luks secret</description>
<uuid>${UUID}</uuid>
</secret>
virsh secret-define --file mysecret.xml
# 128 Zeichen langes Kennwort generieren und in Base64 speichern
# die Nutzung von -base64 statt -hex sorgt dafür, dass der Key binäre Daten enthält. Hier kann man selbst entscheiden ob der Schlüsel lesbar sein soll ;). Ich empfehle die Konstellation mit -hex | base64 zu nutzen.
PASSWORD=$(openssl rand -hex 128 | base64)
# Passphrase / Key setzen
virsh secret-set-value "${UUID}" "${PASSWORD}"
# Secrets auflisten, hier sollte das Secret angezeigt werden!
virsh secret-list
Volume anlegen
UUID=<UUID des Libvirt Secrets>
V_NAME=my_volume
# in GB, ohne Einheit (siehe <capacity>)
V_SIZE=100
V_PATH="/srv/images/${V_NAME}"
cat <<EOF > myvolume.xml
<volume>
<name>${V_NAME}</name>
<capacity unit='G'>${V_SIZE}</capacity>
<target>
<path>${V_PATH}</path>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='${UUID}'/>
<cipher name='aes' size='256' mode='xts' hash='sha512'/>
<ivgen name='plain64' hash='sha512'/>
</encryption>
</target>
</volume>
# Volume anlegen, bitte falls ein anderer Pool gewünscht ist, entsprechend anpassen
virsh vol-create --pool default --file myvolume.xml
Libvirt erzeugt danach mittels QEMU-IMG ein Image, welches außen mittels LUKS gesichert ist und im inneren mit RAW-Format verwendet wird, nicht dass man plötzlich wunderbare QCOW2 Funktionen erwartet ;)
Image in VM einbinden
In der XML Defintion der virtuellen Maschine müssen Parameter gesetzt sein, damit das Image angezogen werden kann. Deshalb hier ein Beispiel aus dem Kontext heraus gezogen, mit aufgelösten Variablen:
<domain type='kvm'>
<!-- INHALT AUF DISK CONFIG REDUZIERT! -->
<disk type='file' device='disk'>
<!-- cache deaktivieren und io=native bringen Geschwindigkeit -->
<driver name='qemu' type='raw' cache='none' io='native'/>
<!-- PFAD wie in der my_volume.xml! -->
<source file='/srv/images/my_volume'/>
<backingStore/>
<target dev='vda' bus='virtio'/>
<encryption format='luks'>
<!-- unbedingt die UUID mit der Secret-UUID beibehalten, darüber wird der Schlüssel zum öffnen des LUKS Containers gefunden -->
<secret type='passphrase' uuid='16cd518f-35ee-4a55-acc3-376bb0c9152e'/>
</encryption>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</disk>
</domain>
Mikrotik
Subsections of Mikrotik
Mikrotik Routeros CLI Cheatsheet
Loop
Entfernen von Kommentaren auf mehreren Objekten
:for i from=0 to=24 do={/interface/bridge/port set $i comment=""}
Server & Hardware
Subsections of Server & Hardware
Supermicro noVNC ohne Browser (CURL)
Nicht immer ist ein Browser in greifbarer Nähe, oder es soll kurz schnell gehen. Um auf die noVNC Schnittstelle von Supermicro Mainboards zugreifen zu können ist die Verbindung mittels IPMI Viewer, oder JNLP (Java Network Launch Protocol) möglich.
Ist der Host nicht im selben Netzwerk wie der lokale PC, funktioniert der IPMI Viewer nicht zwingend. Dies kann zum Beispiel beim SSHuttle der Fall sein. In diesem Fall erreicht man zwar das Webinterface der IPMI-Schnittstelle, muss sich dann mittels Browser einloggen und die JNLP Datei herunterladen. Im Anschluss kann diese dann ausgeführt werden…
Soll es schneller gehen bietet sich der Download der JNLP-Datei auch mittels curl an:
IPMIHOST=YOURHOST
USER=YOURUSER
PASS=YOURPASS
COOKIE=$(mktemp)
JNLP=$(mktemp)
curl -q -s -k -c "${COOKIE}" -X POST --data "name=${USER}&pwd=${PASS}" "https://${IPMIHOST}/cgi/login.cgi" >/dev/null
curl -q -s -k -b "${COOKIE}" -o "${JNLP}" -X GET "https://${IPMIHOST}/cgi/url_redirect.cgi?url_name=ikvm&url_type=jwsk"
javaws "${JNLP}"
Zur Erklärung der “Magie”:
- die Variablen werden gesetzt und zwei temporäre Dateien erzeugt ($COOKIE & $JWSK)
- mittels HTTP POST Request wird sich eingeloggt (Daten kommen aus den Variablen $USER & $PASS). Der Inhalt des Cookies wird in die Temp-Datei ($COOKIE) geschrieben
- mit dem Cookie wird die URL aufgerufen, die eine gewünschte JNLP-Datei zurückliefert. Der Inhalt wird in die Datei ($JNLP) gespeichert.
- die JNLP Datei wird mittels Java-Webstart (javaws) ausgeführt
Links
https://www.truenas.com/community/threads/script-to-launch-supermicro-ipmi-viewer-from-shell.45275/
Supermicro Serial over LAN (SOL)
Es gibt Fälle in denen gerade keine Desktop GUI bereit steht, oder einem die Java Anwendung zu unbequem ist um die Bildschirmausgabe (noVNC) zu öffnen.
Dennoch ist es möglich den Bootprozess zu begleiten, oder sogar das BIOS aufzurufen.
Hierfür stellt Supermicro eine serielle Schnittstelle bereit, die über das Netzwerk erreicht werden kann (Serial over LAN).
Am einfachsten geschieht der Zugriff über IPMItool. Die Parameter sollten wie folgt angepasst werden:
Parameter | Verwendung |
---|---|
-U | Username |
-P | Password |
-H | IP oder Hostname der IPMI Schnittstelle des Remote-Hosts |
-I | Interface, im Regelfall nicht notwendig, aber bei älteren IPMItool Versionen angeben |
Beispiel
ipmitool -I lanplus -H $IP_ODER_HOSTNAME -U ADMIN -P ADMIN sol activate
#verlassen der Konsole mit folgender Kombination:
<Enter>
~~
Die Tilde schreibt sich mit "ALT GR" + "+" (neben Enter)
Konfiguration Grub für Linux-Konsole
Um die Konsole von Linux verwenden zu lassen, ist es eventuell nötig dem Kernel entsprechende Parameter mitzuteilen.
Dies kann im Grub konfiguriert werden.
Ein Beispiel zu Ubuntu (ggf. auch auf andere Distributionen übertragbar):
# File: /etc/default/grub
# Ausgabe auf Bildschirm und serieller Schnittstelle
GRUB_TERMINAL="console serial"
# entweder ergänzen:
GRUB_CMDLINE_LINUX="... serial=ttyS0 console=ttyS0,115200n8
# oder neuen Bereich beginnen:
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX serial=ttyS0 console=ttyS0,115200n8"
Danach muss die GRUB-Konfiguration erstellt werden:
grub-mkconfig -o /boot/grub/grub.cfg
update-grub
Nach einem Reboot dürften Bootprozess, Grub-Menü und auch die Konsole des Betriebssystems mittels SOL anzusprechen sein.
Links
SSH
Subsections of SSH
Chrooted SFTP Server konfigurieren
Vorwort
Um Dateien auf und von einen Linux-Server zu laden stehen unzählbar viele Möglichkeiten zur Verfügung. In diesem Beispiel wird ein SFTP-Server konfiguriert, der:
- nur bestimmten Benutzern, oder Gruppen den Zugang erlaubt
- die Authentifizierung via Passwort, oder SSH-Schlüssel zulässt
- das Startverzeichnis (Wurzelverzeichnis) fest vorschreibt
Sollte noch kein Openssh-Server installiert sein, kann dies einfach nachgeholt werden:
sudo pacman -Syu openssh
sudo apt update && sudo apt install openssh-server
Allgemein Hinweise zur Konfiguration
Alle Einstellungen werden in der typischen Konfigurationsdatei /etc/ssh/sshd_config vorgenommen. Nach Änderungen muss der SSH-Dienst neugestartet werden um diese zu laden. Bereits hergestellt Verbindungen werden von den Anpassungen nicht beeinträchtigt, sodass man bei Fehlkonfigurationen diese wieder rückgängig machen kann!
Es ist daher immer ratsam eine neue Verbindung aufzubauen um die neuen Einstellungen zu testen. Die existierende Verbindung sollte dann für die Korrektur und nötige Neustarts verwendet werden.
Konfiguriert man SSHd falsch und schließt alle Verbindungen, hat man sich wohlmöglich ausgesperrt!
Konfiguration
Die unten stehenden Einstellungen sollen hier etwas genauer beleuchtet werden:
Parameter | Verwendung |
---|---|
ForceCommand | Hierdurch ist eine SSH-Konsolen-Verbindung (Shell) nicht mehr möglich, denn es wird eine SFTP-Verbindung erzwungen. Somit kann der Benutzer keine Konsolen-Verbindung mehr aufbauen. |
PasswordAuthentication | erlaubt die Anmeldung mittels Passwort |
ChrootDirectory | Einstiegspunkt für die SFTP-Verbindung. Dies entspricht dem höchsten Verzeichnis in welches man zurückgehen kann. Der Inhalt von z.B. /srv/sftp_group_dir entspricht bei der Verbindung dem root (/). |
# File: /etc/ssh/sshd_config
# Alle Einstellungen können bequem an das Ende der Datei gepackt werden!
# gilt nur für Benutzer der Linux-Gruppe sftpusers
# alle Benutzer teilen sich einen gemeinsamen Ordner
Match Group sftpusers
PasswordAuthentication yes
ChrootDirectory /srv/sftp_group_dir
ForceCommand internal-sftp
# gilt nur für Benutzer der Linux-Gruppe individuals
# jeder Benutzer hat einen eigenen Ordner (%u wird durch Usernamen ersetzt)
Match Group individuals
PasswordAuthentication yes
ChrootDirectory /srv/individuals/%u
ForceCommand internal-sftp
# gilt nur für den Benutzer myuser
Match User myuser
PasswordAuthentication no
ChrootDirectory /srv/sftp
ForceCommand internal-sftp
AllowTcpForwarding no
Die Reihenfolge der Konfiguration ist relevant! Ist ein Benutzer in z.B. beiden Gruppen (sftpusers und individuals), so gilt der erste Treffer und die weiteren Konfigurationen sind irrelevant!
Sollte die gruppen-basierte Konfiguration genutzt werden, achte darauf den Konsolen-Benutzer mit dem du Einstellungen tätigst nicht zur Gruppe hinzuzufügen. Andernfalls kannst du zukünftig keine Kommandozeile mehr via SSH öffnen, denn es wird SFTP erzwungen ;)! In diesem Fall wäre ein neuer Benutzer für SFTP Verbindungen ratsam.
Damit die Verbindung generell möglich ist, darf das gewählte Chroot-Directory für den verbindenen Benutzer nicht beschreibbar sein! Damit der Benutzer aber einen Ordner zum schreiben hat, sollte ein neuer Ordner angelegt werden. Hier ein Beispiel:
# Ordner rekursiv anlegen
mkdir -p /srv/sftp_group_dir/subdir
# Besitz auf root Benutzer und Gruppe anpassen
chown root:root /srv/sftp_group_dir
# nur Benutzer und Gruppe dürfen "alles"
chmod 755 /srv/sftp_group_dir
# der Besitz des Unterordner subdir wird auf den Benutzer myuser und die Gruppe sftpusers gesetzt
chown myuser:sftpusers /srv/sftp_group_dir/subdir
# Benutzer und Gruppe dürfen "alles"
chmod 770 /srv/sftp_group_dir/subdir
Um Problemen mit Dateiberechtigungen entgegen zu wirken, können Linux-Benutzer sich die gleiche ID teilen.
Dies ist bei SFTP besonders hilfreich, denn alle Benutzer können dann unterschiedliche Namen (und Passwörter), aber identische Schreibberechtigungen haben.
Bei Zugriffen auf Dateien teilen sie sich nämlich die selbe ID.
Hat jeder Benutzer eine individuelle ID, muss darauf geachtet werden, dass die Datei- und Ordnerberechtigung korrekt konfiguriert werden.
Geschieht dies nicht, können Benutzer Dateien eventuell nicht lesen und bearbeiten.
Deshalb ist es hilfreich die identische User-ID zu verwenden.
Port Forwarding
Remote Port per Tunnel lokal binden
Per SSH kann prinzipiell jeder TCP-Port getunnelt werden, den der Remote-Host erreicht.
Hierzu wird auf dem Client ein Port lokal gebunden und jeglicher Traffic der auf diesen eingeht, durch den Tunnel zum Remote-Host geleitet.
Dieser stellt dann stellvertredend die Verbindung zum Ziel her.
Syntax
ssh -L [local_bind_address:]port:host:hostport root@remote.host
Beispiel 1
MariaDB wird über diverse lokalen IP-Adressen und Ports verfügbar gemacht.
Auf dem Remote-Host host1 ist MariaDB nur lokal erreichbar (127.0.0.1:3306).
Die linke Seite entspricht der lokalen IP (oder Port) des Clients.
ssh user@host1 -L 127.0.0.1:3306:127.0.0.1:3306
ssh user@host1 -L 192.168.123.2:3306:127.0.0.1:3306
ssh user@host1 -L 192.168.123.2:13306:127.0.0.1:3306
ssh user@host1 -L 3306:127.0.0.1:3306
Beispiel 2
Ein Webserver (HTTP/S) läuft auf web1, welcher von host1 erreicht werden kann (ein typischer Jumphost):
- IP-Adresse web1: 192.168.55.2
- IP-Adresse host1: 192.168.55.1
ssh user@host1 -L 127.0.0.1:80:192.168.55.2:80
ssh user@host1 -L 127.0.0.1:443:192.168.55.2:443
Weil die Ports 80 und 443 zu den “well-known” Ports gehören, müssen diese ggf. mit root-Rechten gebunden werden (sudo vor dem ssh Befehl).
Deswegen kann es empfehlenswert sein, diese stattdessen auf Ports größer 1024 zu binden:
ssh user@host1 -L 127.0.0.1:8080:192.168.55.2:80
ssh user@host1 -L 127.0.0.1:8443:192.168.55.2:443
SSH SOCK5 Proxy
Anwendungen können (sofern unterstützt) über einen sogenannten Sock5-Proxy mit Servern kommunizieren.
Hierbei wird der Traffic an den Remote-Host gesendet und dieser schickt die Anfrage weiter zum Ziel.
Syntax
ssh user@host1 -D [lokale_bind_address:]port
Beispiel 1
Der Sock5-Proxy bindet sich lokal auf Port 5000.
ssh user@host1 -D 127.0.0.1:5000
Beispiel 2
Lokaler Proxy, der auch von anderen Clients genutzt werden kann, sofern Sie den Host und Port erreichen können.
ssh user@host1 -D 192.168.178.2:1337
SShuttle
Gerne als “poor man’s VPN” bezeichnet, kann SShuttle (eine Python Anwendung) bestimmte Ziel-Adressen (oder Netze) über SSH tunneln.
Hierzu bindet SShuttle einen lokalen Port und hinterlegt Firewall-Regeln (nftables / iptables). Hierdurch werden Pakete zum Ziel an den lokalen SShuttle Port umgeleitet (DNAT), und SShuttle leitet diese wiederum zum Remote-Host.
Dieser schickt die Pakete dann dann zum Ziel(netz).
Durch diese Technik können ganze IP-Netze hinter (Jump-)Hosts erreicht werden, solange es sich um TCP-Traffic handelt.
Syntax
sshuttle [-l [ip:]port] -r [user@]sshserver[:port] <subnets...>
Beispiel 1
Die Netze 10.20.30.0, 192.168.33.0/25
und die IP-Adresse 1.1.1.1 sollen über host1 verfügbar gemacht werden:
sshuttle -r user@host1 10.20.30.0/24 192.168.33.0/25 1.1.1.1
SSH Verbindung ohne Passwort (mit Key)
Für eine erhöhte Sicherheit beim SSH-Login bietet sich die Authentifizierung mittels SSH-Schlüssel an.
Zusätzlich wird der Login mittels Passwort deaktiviert.
In dieser Anleitung wird die Generierung auf Windows und Linux (auch WSL) beschrieben und abschließend, wie der öffentliche Schlüssel auf den Server zu legen und die SSH-Konfiguration vorzunehmen ist.
SSH Schlüssel auf Windows generieren
In neueren Windows 10 Versionen steht der OpenSSH-Client bereit. Falls dieser nicht installiert ist, kann dieser installiert werden.
Hierfür nutzt man unter Einstellungen “Apps & Features”, klickt auf “Optionale Features” und installiert mittels “Feature hinzufügen” den OpenSSH-Client.
Nach der Installation stehen die Kommandozeilen-Tools zur Verfügung und die Generierung kann durchgeführt werden.
Je nach Plattform die man unterstützten möchte, kann es notwendig sein den veralteten Standard (RSA) zu verwenden.
In diesem Fall sollte man einen möglichst großen Schlüssel verwenden (4096 Bit).
Gemäß der Doku empfiehlt sich das Schlüsselverfahren ecdsa zu verwenden.
ssh-keygen -t ecdsa -b 521
ssh-keygen -t rsa -b 4096
ssh-keygen -t ed25519
Hier ein komplettes Beispiel in dem der Pfad mittels Enter bestätigt und ein Passwort für den Schlüssel festgelegt wird. Das Passwort schützt den Schlüssel im Fall von Diebstahl durch Datei-Kopieren!
# .ssh Ordner im $HOME anlegen und betreten
cd
mkdir .ssh
cd .ssh
# Key generieren
C:\Users\User\.ssh>ssh-keygen -t ecdsa -b 521
Generating public/private ecdsa key pair.
Enter file in which to save the key (C:\Users\User/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\User/.ssh/id_ecdsa.
Your public key has been saved in C:\Users\User/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx User@PC
The key's randomart image is:
+---[ECDSA 521]---+
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
+----[SHA256]-----+
Nach der Generierung finden sich, je nach gewähltem Verfahren zwei Dateien im Verzeichnis .ssh:
- id_$verfahren (privater Schlüssel)
- id_$verfahren.pub (öffentlicher Schlüssel)
Die *.pub Datei ist nützlich, aber nicht zwingend notwendig, da diese immer wieder aus dem privaten Schlüssel generiert werden kann:
ssh-keygen -f $privater_schlüssel -y
# <Passwort eingeben>
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF1mthDNIv98jiT5qF85YCd9QmvgK+bTn/VLQVRmJyC12dOSjGpcam4c5Uu9t5dEXtr1bRSW9nCC7Ro6Exla0y86AALfgrTTAFysotLuqJD5bigQN5J50qpZJwUs8wlB12NehrNvAfCQiEYvmN6Bg0RugUyHSi21jlQ4kSj6RsDMAT9Xw==
SSH Schlüssel auf Linux (oder WSL) generieren
Im Regelfall sollte die Anwendung ssh-keygen bereits installiert sein. Ist dies nicht der Fall, müssen die Pakete dafür installiert werden. Wie immer für Ubuntu / Debian und Archlinux:
pacman -Syu openssh
apt update && apt install openssh-client
Im Anschluss wird wie unter Windows der Schlüssel generiert:
ssh-keygen -t ecdsa -b 521
ssh-keygen -t rsa -b 4096
ssh-keygen -t ed25519
Mehr Informationen dazu finden sich oben in der Windows-Anleitung.
Der Ausgabe-Pfad ist ebenfalls der $Benutzer-Ordner/.ssh.
ohne Passwort, aber per Key
Der öffentliche Schlüssel muss in das Home-Verzeichnis des Users gelegt werden, als der man sich einloggen möchte. In diesem Beispiel nennt er sich “user1”.
Den Inhalt der id_$verfahren.pub legt man nun in die authorized_keys Datei (/home/user1/.ssh/authorized_keys.
Diese Datei kann eine beliebige Menge von öffentlichen Schlüsseln enthalten.
Hinter dem Schlüssel können Kommentare hinzugefügt werden.
# Auflisten der Keys
cat /home/user1/.ssh/authorized_keys
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF1mthDNIv98jiT5qF85YCd9QmvgK+bTn/VLQVRmJyC12dOSjGpcam4c5Uu9t5dEXtr1bRSW9nCC7Ro6Exla0y86AALfgrTTAFysotLuqJD5bigQN5J50qpZJwUs8wlB12NehrNvAfCQiEYvmN6Bg0RugUyHSi21jlQ4kSj6RsDMAT9Xw== mein kommentar zum schlüssel
Funktionstest
Beim Verwenden des Schlüssels muss dieser mit dem gewählten Kennwort geöffnet werden:
ssh user1@server.host
Enter passphrase for key 'C:\Users\User/.ssh/id_ecdsa':
Last login: Sun Apr 25 22:34:34 2021 from x.x.x.x
user1@server ~
Möchte man nicht jedes mal das Kennwort eingeben, bietet sich ein SSH Agent an.
Dieser hält solange er läuft den SSH-Schlüssel bereit.
Deshalb muss man den privaten Schlüssel nur einmalig öffnen.
ssh-agent bash
ssh-add
# <Passwort eingeben>
``´
Unter Windows kann der Agent-Dienst deaktiviert sein, in diesem Fall muss man diesen vorab mittels Powershell (als Admin) aktivieren:
```powershell
Get-Service -Name ssh-agent | Set-Service -StartupType Manual
Passwort Authentifizierung deaktivieren
Unter bearbeitet man die OpenSSH-Server-Konfiguration und startet den Dienst neu. Falls etwas fehlschlägt, auf gar keinen Fall die Konsolenverbindung trennen.
Ein Neustart bricht eine existierende Verbindung nicht ab, sodass man die Fehlkonfiguration noch reparieren kann! In diesem Beispiel verwenden wir nano (auch wenn ich vim bevorzuge).
Nach Bearbeitung beendet man diesen mit “STRG + X”, “y”, “Enter”.
nano /etc/ssh/sshd_config
# verbietet root Login mittels Passwort
# (ohne SSH Key ist dann kein root Login mehr möglich)
PermitRootLogin prohibit-password
# verbiete generell Passwort-Authentifizierung
PasswordAuthentication no
Ausnahmen für bestimmte Benutzer
Es kann hilfreich sein, einzelnen Benutzern die Authentifizierung dennoch zu erlauben:
# erlaube für Benutzer "user2" Passwort-Authentifizierung
Match User user2
PasswordAuthentication yes
# erlaube allen Benutzern der Gruppe sshpass Passwort-Authentifizierung
Match Group sshpass
PasswordAuthentication yes
SSH-Daemon neustarten
systemctl restart sshd.service
# im Fehlerfall prüfen:
systemctl status sshd.service
Links
SSL
Subsections of SSL
Lets Encrypt Zertifikat via Certbot anfragen
Zertifikate können bequem mittels Certbot angefragt werden, wobei zwischen verschiedenen Verfahren gewählt werden kann. Eine Auflistung der Plugins findet man hier: https://certbot.eff.org/docs/using.html
Folgende Möglichkeiten werden hier erklärt:
- Webroot
- Standalone
- DNS
- Manual
In den Beispielen werden die Variablen genutzt, die entsprechend ersetzt werden müssen!
Variable | Inhalt |
---|---|
DOMAIN | der Domain Name für den das Zertifikat generiert werden soll |
E-Mailadresse zu der kritische E-Mails, oder Ablauferinnerungen gesendet werden |
Benötigt man ein Wildcard-Zertifikat (*.domain.de) ist die nur die Verifikation mittels DNS möglich!
Es können bis zu 100 Hostnamen auf ein gemeinsames Zertifikat gelegt werden, welche mittels mehreren “-d”-Parametern erfolgt:
certbot ... -d domain1.de -d my.host.com -d another.host.company.com
Installation
Für Ubuntu und Archlinux stehen Pakete bereit. Liefert das Betriebssystem diese nicht, ist eine Installation auch mittels PIP (Python Package Installer) möglich:
pacman -Syu certbot
apt update && apt install certbot
Webroot
Hierbei schreibt der Certbot eine ACME Challenge Datei in den gewünschten Pfad. Eine andere Anwendung (z.B. nginx) muss diese dann auf Anfrage der Let’s Encrypt Servern ausliefern können. Ist der Inhalt der Datei korrekt, erhält man sein Zertifikat.
certbot certonly -d ${DOMAIN} --non-interactive --agree-tos --email ${MAIL} --webroot /var/www/html/
Standalone (HTTP Port)
Der Certbot bindet sich hierbei an Port 80 und kann mittels HTTP angefragt werden. Der Port kann im Fall einer vorangehenden Belegung (z.B. durch einen Webserver) konfiguriert werden. Dadurch bedingt, dass Let’s Encrypt allerdings nur Port 80 zur Prüfung heranzieht, muss ein Proxy / Webserver dann auf den entsprechenden Port weiterleiten.
Läuft kein Webserver auf dem Host, kann die Standalone Methode mit Port 80 (Standard) genutzt werden.
# direkt, ohne Proxy (nur wenn Port 80 frei ist!)
certbot certonly --standalone -d ${DOMAIN} --non-interactive --agree-tos --email ${MAIL} --http-01-port=80
# Proxy lauscht auf :80, Certbot Port 9999
certbot certonly --standalone -d ${DOMAIN} --non-interactive --agree-tos --email ${MAIL} --http-01-port=9999
Manual
Alle Schritte der Zertifikatsgenerierung können durch individuelle Skripte durchgeführt werden. In diesem Beispiel legt das Skript le-dns-hook.sh den DNS Eintrag an und le-dns-hook-cleanup.sh räumt im Anschluss den Eintrag wieder ab.
Die zu verwendeten Daten (Hostname + ACME Challenge) werden an die Skripte beim Ausführen via Environment-Variablen übergeben, wie hier dokumentiert: https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks
letsencrypt certonly --manual --preferred-challenges dns \
--manual-auth-hook "/usr/local/bin/le-dns-hook.sh" \
--manual-cleanup-hook "/usr/local/bin/le-dns-hook-cleanup.sh" \
-d ${DOMAIN}