Datenhaufen zu IT und Elektronik.

Kategorie: Linux & BSD (Seite 1 von 3)

FreeBSD SSH-Server absichern: MFA mit Google Authenticator einrichten​

Dass man eigentlich keinen reinen Kennwort-Login für seine Anmeldung an einem SSH-Server haben möchte, ist sicherlich bei fast allen angekommen. Kennwörter lassen sich einfacher mittels eines Brute-Force-Angriffes herausfinden. Ebenso gehen diese auch mal verloren. SSH-Keys werden die meisten ebenfalls bereits aufseiten des Clients mit einem zweiten Faktor geschützt haben. Dies kann ein MFA-Token sein oder einfach eine Passphrase.

Hin und wieder lässt es sich aber nicht vermeiden, dass man seinen Login nur mit einer einfachen Kombination aus Benutzername und Kennwort sichert. Um dieses dennoch etwas aufzuwerten, lässt sich dieses ebenfalls mit MFA ausstatten. In diesem kurzen Beispiel geht es dabei um einen SSH-Server auf einem FreeBSD-System, welches nach der Authentifizierung mittels Benutzername/Kennwort noch nach einem Auth-Code vom Google Authenticator fragt.

Clientseitig ist eigentlich nichts weiter zu beachten. Auf Serverseite muss das Paket pam_google_authenticator installiert werden:

pkg install pam_google_authenticator

Ist die Installation abgeschlossen, müssen wir nun unsere PAM-Konfiguration für den SSHD-Password-Login erweitern. Oh, ja… Auf demselben Weg lässt sich dieses ebenfalls für den normalen Login an der Konsole, für su, ftp usw. einbinden. Selbstverständlich ebenfalls für den Login per SSH-Keys. Wir bleiben aber hier nun beim Login mit User/Pass. Meine /etc/pam.d/sshd sieht damit wie folgt aus:

#
#
# PAM configuration for the "sshd" service
#

# auth
#auth		sufficient	pam_krb5.so		no_warn try_first_pass
#auth		sufficient	pam_ssh.so		no_warn try_first_pass
auth		required	pam_unix.so		no_warn try_first_pass
auth            required        /usr/local/lib/pam_google_authenticator.so

# account
account		required	pam_nologin.so
#account	required	pam_krb5.so
account		required	pam_login_access.so
account		required	pam_unix.so

# session
#session	optional	pam_ssh.so		want_agent
session		required	pam_permit.so

# password
#password	sufficient	pam_krb5.so		no_warn try_first_pass
password	required	pam_unix.so		no_warn try_first_pass

Ebenfalls muss die folgende Option in der /etc/ssh/sshd_config aktiviert sein:

ChallengeResponseAuthentication yes

Das war es auch schon fast. Wenn man nun auf seinem Smartphone noch schnell den Google Authenticator installiert, können wir schon damit beginnen, den zweiten Faktor zu erstellen. Dafür einfach mit dem gewünschten Nutzer in dessen Home-Verzeichnis: „cd ~“ den google-authenticator aufrufen und den Anweisungen folgen:

Dieses nur noch mit der Authenticator-App am Smartphone scannen, den Code einmal eingeben und schon wird man bei jedem Kennwort-Login nach seinem aktuellen Code gefragt.

Oh, sehr ähnlich ist die Einrichtung unter Linux 🙂

DNSSEC unter Linux Mint & Ubuntu: SSH-Hostkey-Verifikation erklärt​

Heute habe ich versucht, mich von meiner neuen Linux Mint Installation aus mit einem meiner SSH-Server zu verbinden. Mein SSH-Client hat mich direkt mit der Frage begrüßt, ob ich dem neuen Hostkey vertrauen möchte oder nicht.

ssh username@hostname.kernel-error.org
The authenticity of host 'hostname.kernel-error.org (2a01:5a8:362:4416::32)' can't be established.
ED25519 key fingerprint is SHA256:kTRGVCMRLiHfvJunW2CbW5H3NZmn3Wkx2KnHJXl3iJu.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Für viele mag diese Meldung bekannt und vollkommen normal erscheinen. In der Regel antwortet man initial mit „yes“ und sieht sie nie wieder. Aber diese Meldung hat ihren Grund. Beim initialen Aufbau einer Verbindung zu einem SSH-Server wird einem der Fingerprint des HostKeys angezeigt. So hat man die Möglichkeit, den Fingerprint mit dem erwarteten Fingerprint abzugleichen, um sicherzustellen, dass man sich wirklich mit dem gewünschten SSH-Server verbindet und nicht etwa ein Angreifer Zugangsdaten abfischt. Wenn man eh immer nur „JA“ sagt, könnte man diesen Check auch direkt in seiner ~/.ssh/config mit folgendem Eintrag deaktivieren:

Host *
    StrictHostKeyChecking no

Warum erzähle ich das alles? Nun, weil es für mich eigentlich nicht normal ist, diese Meldung zu sehen. Denn es gibt die Möglichkeit, die Fingerprints der erwarteten HostKeys in seiner DNS-Zone zu hinterlegen und seinen SSH-Client mit der folgenden Konfiguration in seiner ~/.ssh/config anzuweisen, dies einfach selbst zu überprüfen, sofern der SSH-Client eine vertrauenswürdige Antwort vom DNS-Server erhält.

Host *
   VerifyHostKeyDNS yes

Vertrauenswürdige Antwort vom DNS-Server… Hier sind wir schon bei DNSSEC angekommen. Meine DNS-Server, einschließlich des lokalen Resolvers auf meinem Router, unterstützen alle DNSSEC. Meine SSH-Client-Konfiguration ist korrekt und dennoch erscheint die Meldung…. Also habe ich den Verbindungsaufbau mit etwas mehr Debugging-Output gestartet, was bei ssh einfach die zusätzliche Option -vvv bedeutet:

ssh usermane@hostname.kernel-error.org -vvv
[...]
debug1: SSH2_MSG_KEX_ECDH_REPLY received
debug1: Server host key: ssh-ed25519 SHA256:kTRGVCMRLiHfvJunW2CbW5H3NZmn3Wkx2KnHJXl3iJu
debug3: verify_host_key_dns
debug1: found 2 insecure fingerprints in DNS
debug3: verify_host_key_dns: checking SSHFP type 4 fptype 1
debug1: verify_host_key_dns: matched SSHFP type 4 fptype 1
debug3: verify_host_key_dns: checking SSHFP type 4 fptype 2
debug1: verify_host_key_dns: matched SSHFP type 4 fptype 2
debug1: matching host key fingerprint found in DNS
[...]

Zu meiner Überraschung sehe ich:

debug1: found 2 insecure fingerprints in DNS

Hm… „insecure“… Er hat also die passenden Einträge in der DNS-Zone gefunden, kann diesen aber nicht vertrauen, weil… ja, warum? Die Antwort des DNS-Servers ist nicht vertrauenswürdig? OK, das lässt sich einfach mit dig und der Option +dnssec testen. Wir suchen einfach im Header nach „ad„:

dig +dnssec hostname.kernel-error.org @8.8.8.8

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> +dnssec hostname.kernel-error.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48645
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
[...]

@8.8.8.8 gibt an, dass direkt der öffentliche DNS-Server von Google gefragt wird. Dieser wird natürlich meine Server fragen usw., einfach um sicherzugehen, dass meine eigentlichen DNS-Server, die für die Zone zuständig sind, sauber konfiguriert sind. Ich sehe ein „ad„, also ist dort schon mal alles gut. Im Anschluss habe ich den Test noch mit meinem lokalen DNS-Resolver auf dem Router durchgeführt. Also einfach @192.168.0.1 oder was auch immer euer lokaler Router ist. Gleiches Ergebnis…. Aber warum will dann mein Linux Mint nicht? Sollte Linux Mint etwa kein DNSSEC können?

dig +dnssec hostname.kernel-error.org

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> +dnssec hostname.kernel-error.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1789
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
[...]

Öhhh ähhh… Ja, öhm, geht nicht… Aber warum? Was steht denn in meiner /etc/resolv.conf? 127.0.0.53? Ohhhhhhhh, stimmt! systemd-resolv! OK, ok… Ich könnte also in meiner /etc/systemd/resolved.conf nun einfach DNSSEC=yes setzen und mit einem systemctl restart systemd-resolved sollte dann… Nope, leider nicht. Nun geht überhaupt keine DNS-Auflösung mehr. Es scheint am eingesetzten Stub-Resolver zu liegen, den man ebenfalls noch ändern kann usw… Nennt mich etwas oldschool, aber für meine Zwecke reicht der klassische Weg über die vom NetworkManager gepflegte resolv.conf. Um also systemd-resolved zu deaktivieren und auf den NetworkManager zu wechseln, sind die folgenden Schritte nötig:

sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved
sudo rm /etc/resolv.conf

Dann in die Konfigurationsdatei vom NetworkManager /etc/NetworkManager/NetworkManager.conf in der [main]-Sektion die folgende Option setzen:

dns=default

Nun nur noch den NetworkManager neu starten und schon sollte die /etc/resolv.conf mit den DNS-Informationen gefüttert werden:

sudo systemctl restart NetworkManager
cat /etc/resolv.conf
# Generated by NetworkManager
search kernel-error.local
nameserver 10.10.88.1
nameserver fd00:424e:6eff:f525:454e:6eff:f525:4241

Perfekt! Also los, noch ein Versuch mit dem SSH-Client und… nichts… DNS-Auflösung funktioniert, aber es ist noch immer „insecure„. Stimmt! Es fehlt etwas in meiner resolv.conf. Wir brauchen bestimmt noch die folgende Option:

options edns0

Jetzt aber! HA, dig ist schon mal glücklich, ich sehe ein „ad“. Ähm, aber der SSH-Client noch immer nicht?! Was zum… OK, OK… Irgendwas um SSH muss ich vergessen haben. Aber was? Wie macht SSH das überhaupt? Vielleicht gibt mir das eine Idee. Also, mal kurz in den Code geschaut, C bekomme ich gerade noch hin:

        /* Check for authenticated data */
        if (ldns_pkt_ad(pkt)) {
                rrset->rri_flags |= RRSET_VALIDATED;
        } else { /* AD is not set, try autonomous validation */
                ldns_rr_list * trusted_keys = ldns_rr_list_new();

                debug2("ldns: trying to validate RRset");
                /* Get eventual sigs */
                rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG,
                    LDNS_SECTION_ANSWER);

                rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs);
                debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS",
                       rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG);

                if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs,
                     trusted_keys)) == LDNS_STATUS_OK) {
                        rrset->rri_flags |= RRSET_VALIDATED;
                        debug2("ldns: RRset is signed with a valid key");
                } else {
                        debug2("ldns: RRset validation failed: %s",
                            ldns_get_errorstr_by_id(err));
                }

                ldns_rr_list_deep_free(trusted_keys);
        }

Aaaaaaaaaaaaaaaaaaaaaaa… ldns… woher bekommt er wohl die Trust Keys? Genau… woher? Da fehlt also NOCH etwas in meiner resolv.conf:

options edns0 trust-ad

Und? genau… geht 😀

ssh usermane@hostname.kernel-error.org -vvv
[...]
debug1: SSH2_MSG_KEX_ECDH_REPLY received
debug1: Server host key: ssh-ed25519 SHA256:kTRGVCMRLiHfvJunW2CbW5H3NZmn3Wkx2KnHJXl3iJu
debug3: verify_host_key_dns
debug1: found 2 secure fingerprints in DNS
debug3: verify_host_key_dns: checking SSHFP type 4 fptype 1
debug1: verify_host_key_dns: matched SSHFP type 4 fptype 1
debug3: verify_host_key_dns: checking SSHFP type 4 fptype 2
debug1: verify_host_key_dns: matched SSHFP type 4 fptype 2
debug1: matching host key fingerprint found in DNS
[...]

Pfff… nun habe ich natürlich die Optionen von Hand in meine resolv.conf eingetragen, der NetworkManager wird diese Option also spätestens beim nächsten Boot rauswerfen. Also muss ich noch meinem NetworkManager beibringen, dass er bitte diese Option ebenfalls in meine resolv.conf schreibt, wenn das jeweilige Netzwerkprofil aktiviert ist. Dazu gibt es aber leider keinen Menüpunkt in der GUI vom NetworkManager, also muss das per CLI gemacht werden. Dieses für IPv4 und IPv6 gleichermaßen, sonst greift es leider nicht!

nmcli conn modify DEINE-PROFIL-UUID ipv4.dns-options edns0,trust-ad
nmcli conn modify DEINE-PROFIL-UUID ipv6.dns-options edns0,trust-ad

Oh, ein nmcli conn show listet die bestehenden und vor allem das aktive Profil inkl. der UUID auf. Davon abgesehen, klappt es nun so und ist rebootfest.

So und nun ihr! Ich bin mit meinem FreeBSD-Wissen an das Thema herangegangen. Wie macht man das als Hardcore-Linux-User und mit systemd-resolved richtig und funktionierend?

DNS over TLS mit BIND, Stunnel und Android 9: Eigener DoT-Server​

Über die Techniken DoT (DNS over TLS) habe ich bereits im Zusammenhang mit Bind 9.16 geschrieben. Ebenfalls DoH (DNS over HTTPS) gibt es einen kleinen Beitrag.

Bilder der Bind 9 TLS Konfiguration

Zu diesem Zeitpunkt bracht BIND 9 die Unterstützung für DoH und DoT noch nicht selbst mit. Daher waren zu diesem Zeitpunkt noch Umwege über stunnel oder nginx zusammen mit doh-proxy nötig.

Zum Glück kommt die letzte stable Version 9.18.0 (26. Januar 2022) mit dem nötigen Support.

named now supports securing DNS traffic using Transport Layer Security (TLS). TLS is used by both DNS over TLS (DoT) and DNS over HTTPS (DoH).

Warum möchte man noch gleich DoH oder DoT benutzen? Ganz einfach… Über diese Techniken werden DNS Abfragen verschlüsselt übertragen. Dieses ist ein weiterer Schutz davor manipulierte Antworten zu bekommen und selbstverständlich, damit die eigenen DNS Abfragen erst überhaupt nicht mitgelesen werden. Denn wenn von einem Gerät im Netzwerk die DNS Abfrage zu z.B.: www.tagesschau.de kommt, könnte man davon bereits Dinge ableiten.

Wie die meisten Bind Konfigurationen ist dieses ebenfalls straightforward. Ab Version 9.18 bringt Bind alles Nötige mit. Da wir nun TLS mit dem Bind sprechen möchten, benötigen wir natürlich ein gültiges Zertifikat, wie z.B. beim nginx für seine Webseite.

Ebenfalls sollte man ein paar frische Diffie-Hellmann Parameter generieren:

openssl dhparam -out dhparam.pem 4096

Die eigentliche bind Konfiguration kann in der named.conf.options geschehen:

options {
        [...]
        listen-on port 853 tls local-tls { 37.120.183.220; };
        listen-on-v6 port 853 tls local-tls { 2a03:4000:38:20e::853; };
        listen-on port 443 tls local-tls http default { 37.120.183.220;  };
        listen-on-v6 port 443 tls local-tls http default { 2a03:4000:38:20e::853; };
        [...]
        allow-recursion-on { 127.0.0.0/8; ::1/128; 2a03:4000:38:20e::853; 37.120.183.220; };
        [...]
};

Da der bind auf weiteren Ports lauschen soll erweitert man diese für IPv4 und IPv6. Der Default Port für DoH ist dabei 443 und der default Port für DoT ist 853, beides TCP.

listen-on sowie listen-on-v6 sind wohl selbsterklärend.
port ist der TCP Port und erklärt sich ebenfalls.
tls sagt dem Bind das wir tls sprechen möchten.
local-tls verweißt auf den gleichnamigen tls Block über welchen man seine TLS Konfiguration vornimmt.
http ist für DoH.
default gibt den eigentlichen endpoint für die DoH Abfragen an, im default ist es /dns-query

Da der Server unsere DNS Abfragen erledigen soll, müssen wir ihm dieses noch per allow-recursion-on auf den jeweiligen Adressen erlauben.

Als nächstes wird die eigentliche TLS Terminierung konfiguriert (das lässt sich ebenfalls auslagern, wenn gewünscht). Dafür wird der folgende Block, außerhalb der Options Blocks, ergänzt:

tls local-tls {
    cert-file "/usr/local/etc/ssl/wild.kernel-error.de/2022/ecp/chain.crt";
    key-file "/usr/local/etc/ssl/wild.kernel-error.de/2022/ecp/http.key";
    dhparam-file "/usr/local/etc/ssl/dhparam.pem";
    protocols { TLSv1.2; TLSv1.3; };
    ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256";
    prefer-server-ciphers yes;
    session-tickets no;
};

local-tls ist dabei der name des Blocks. Auf diesen verweisen wir oben.
cert-file ist der Pfad zum Zertifikat. Ich habe dort nicht nur das Zertifikat, sondern die gesamte Chain, also mit Intermediate und Root.
key-file ist der Pfad zum Key des Zertifikates.
dhparam-file ist der Pfad zu den Diffie-Hellman Parametern.
protocols definiert die zu verwendenden TLS Protokolle. In diesem Beispiel TLS1.2 sowie TLS1.3.
ciphers definiert die zu verwendenden cipher. Es soll ja „sicher“ bleiben.
prefer-server-ciphers übermittelt dem Client die Information, in welcher Reihenfolge protokoll/cipher Kombinationen probiert werden sollen um einen Match zu finden. Erst das vermeintlich sicherste und dann immer „schlechter“.
session-tickets regelt ob eine Wiederaufnahme von TLS Sessions erlaubt ist oder nicht. Da ich forward secrecy nutzen möchte, ist es deaktiviert.

Damit ist die Konfiguration schon abgeschlossen (Firewall ggf. nicht vergessen!). Also testen….

Ein einfaches Tool dafür ist dog, oder natürlich dig aus den bind-tools aber Version 9.18. Für bind gibt es dann die Optionen +https oder auch +tls

dig +https @dns.kernel-error.de www.kernel-error.de A
dig +tls @dns.kernel-error.de www.kernel-error.de A

Der gleiche Test mit dog, sieht wie folgt aus:

dog www.kernel-error.de --tls "@dns.kernel-error.de"
A www.kernel-error.de. 6h00m00s   148.251.40.23
dog www.kernel-error.de --https "@https://dns.kernel-error.de/dns-query"
A www.kernel-error.de. 6h00m00s   148.251.40.23

Das war es auch schon! Viele Spaß mit einem „besseren“ DNS und wenn es noch Fragen gibt, einfach fragen 🙂

FreeBSD 13: Unverschlüsseltes ZFS-Dataset in verschlüsseltes Dataset migrieren​

Bild der Bücher FreeBSD Mastery ZFS und FreeBSD Mastery Advanced ZFS

Mit FreeBSD 13 lässt sich die native ZFS Verschlüsselung direkt nutzen. Dabei muss man zwischen einem komplett verschlüsselten zpool und verschlüsselten Datasets unterscheiden. Hat man einen komplett verschlüsselten zpool, bedeutet es nicht, dass damit auch alle Datasets verschlüsselt sein müssen, so wie es auch nicht bedeutet, dass man Datasets nur verschlüsseln kann, wenn auch der komplette ZFS Pool verschlüsselt ist.

Wer nun also sein FreeBSD auf Version 13 gehoben hat, möchte ggf. einzelne ZFS Datasets verschlüsseln. In der Praxis trifft dieses sicher oft auf Jails zu. Diese liegen in der Regel in eigenen ZFS Datasets und mit dem folgenden Beispiel lassen sich diese und andere Datasets nachträglich verschlüsseln.

Im Beispiel haben wir den Pool zroot und in diesem das Dataset varta. Weder der zpool noch das Dataset sind aktuell verschlüsselt:

root@testtest:/ # zfs list zroot/varta
NAME          USED  AVAIL     REFER  MOUNTPOINT
zroot/varta   100M  12.0G      100M  /zroot/varta
root@testtest:/ # zfs get encryption zroot/varta
NAME         PROPERTY    VALUE        SOURCE
zroot/varta  encryption  off          default
root@testtest:/ #

Aktiviert man bei ZFS Dinge wie Komprimierung oder Deduplikation sind diese immer nur ab dem Moment der Aktivierung und bis genau zur Deaktivierung aktiv. Dieses hat viele Vorteile aber auch Nachteile. So greift dieses nur für Daten, welche neu geschrieben werden. Möchte man dieses nachträglich auf alle Daten anwenden, muss man die Daten komplett neu schreiben. Dieses lässt sich am einfachsten und schnellsten per zfs send und zfs receive erledigen. Wenn man also sein bestehendes Dataset verschlüsseln möchte, dann geht dieses faktisch nicht, sondern man erstellt im Grunde ein neues verschlüsseltes Dataset und schreibt seine Daten dort rein.

Bevor wir nun mit der Migration starten, müssen wir noch eine Kleinigkeit wissen…. Zum Verschlüsseln der Daten benötigen wir noch ein Geheimnis, einen Schlüssel/Key. Dieser kann bei ZFS in verschiedenster Form und an verschiedensten Orten liegen. So könnte man den Key zur Ver- und Entschlüsselung auf einen USB-Stick ablegen. Nur wenn dieser auch im System steckt usw. usw.. Der eingängigste Weg ist sicher ein Passphrase welches per prompt abgefragt wird. Will man sein verschlüsseltes Dataset öffnen, wird man nach einem Kennwort gefragt, welches sich das System bis zum nächsten Reboot oder dem manuellen „Schließen“ des Datasets merkt. Diesen Zustand wollen wir nach der Migration, in diesem Beispiel, erreichen.

Zur Verdeutlichung erstellen wir kurz ein neues verschlüsseltes Dataset:

root@testtest:/ # zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt zroot/enc-beispiel
Enter passphrase:
Re-enter passphrase:

Damit haben wir ein neues Dataset welches sofort benutzt werden kann, alles was wir in dieses legen, ist verschlüsselt.

root@testtest:/ # zfs list zroot/enc-beispiel
NAME                 USED  AVAIL     REFER  MOUNTPOINT
zroot/enc-beispiel   200K  12.0G      200K  /zroot/enc-beispiel

Schauen wir in die Optionen des Datasets ist die Verschlüsselung aktiviert und der Schlüssel wird per Prompt vom Benutzer abgefragt:

root@testtest:/ # zfs get encryption,keylocation,keyformat zroot/enc-beispiel
NAME                PROPERTY     VALUE        SOURCE
zroot/enc-beispiel  encryption   aes-256-gcm  -
zroot/enc-beispiel  keylocation  prompt       local
zroot/enc-beispiel  keyformat    passphrase   -

Wie immer wird das Dataset sofort eingehangen:

root@testtest:/ # mount |grep enc-beispiel
zroot/enc-beispiel on /zroot/enc-beispiel (zfs, local, noatime, nfsv4acls)

Nach einem reboot, wird das Dataset nicht automatisch eingehangen, da ZFS den Schlüssel nicht hat. Wenn wir es nun einhängen und ZFS anweisen, den Schlüssel zu laden (Option -l), dann werden wir zur Eingabe des Kennwortes aufgefordert und können das Dataset im Anschluss wieder nutzen:

root@testtest:~ # mount | grep enc-beispiel
root@testtest:~ # zfs get encryption,keylocation,keyformat zroot/enc-beispiel
NAME                PROPERTY     VALUE        SOURCE
zroot/enc-beispiel  encryption   aes-256-gcm  -
zroot/enc-beispiel  keylocation  prompt       local
zroot/enc-beispiel  keyformat    passphrase   -
root@testtest:~ # mount | grep enc-beispiel
root@testtest:~ # zfs mount -l zroot/enc-beispiel
Enter passphrase for 'zroot/enc-beispiel':
root@testtest:~ # mount | grep enc-beispiel
zroot/enc-beispiel on /zroot/enc-beispiel (zfs, local, noatime, nfsv4acls)

Gut gut… So viel zu den Basics. Damit ist nun auch klar, warum im nun folgenden zfs send / zfs reveive Beispiel, der Schlüssel einen Umweg nehmen wird. Denn durch das pipen kommen wir so schlecht an die stdin heran, um das Passphrase einzugeben 😉 Wir sind nun also wieder zurück bei unserem unverschlüsselten Dataset varta und dessen Migration in einen verschlüsselten Zustand. Als erstes legen wir nun das gewünschte Passphrase in einer Datei ab:

root@testtest:~ # echo 'Tolles-Kennwort' > /kennwort.txt
root@testtest:~ # cat /kennwort.txt 
Tolles-Kennwort

Ebenfalls erstellen wir einen snapshot vom Dataset varta, welchen wir zur Migration nutzen:

root@testtest:~ # zfs snapshot zroot/varta@migration
root@testtest:~ # zfs list -t snapshot
NAME                    USED  AVAIL     REFER  MOUNTPOINT
zroot/varta@migration     0B      -      100M  -

Jetzt kann die eigentliche Migration starten:

root@testtest:~ # zfs send zroot/varta@migration | zfs receive -F -o encryption=on -o keyformat=passphrase -o keylocation=file:///kennwort.txt zroot/en-varta
root@testtest:~ # zfs list zroot/varta zroot/en-varta
NAME             USED  AVAIL     REFER  MOUNTPOINT
zroot/en-varta   100M  11.8G      100M  /zroot/en-varta
zroot/varta      100M  11.8G      100M  /zroot/varta
root@testtest:~ # zfs list -t snapshot
NAME                       USED  AVAIL     REFER  MOUNTPOINT
zroot/en-varta@migration   112K      -      100M  -
zroot/varta@migration        0B      -      100M  -

Das ist schnell und einfach, oder? Natürlich liegt nun noch immer das Passphrase offen in einer Datei im root des Systems. Wir müssen nun also den Ort des Schlüssels auf prompt ändern:

root@testtest:~ # zfs get keylocation zroot/en-varta
NAME            PROPERTY     VALUE                 SOURCE
zroot/en-varta  keylocation  file:///kennwort.txt  local
root@testtest:~ # zfs set keylocation=prompt zroot/en-varta
root@testtest:~ # zfs get keylocation zroot/en-varta
NAME            PROPERTY     VALUE        SOURCE
zroot/en-varta  keylocation  prompt       local

Damit kann die Datei mit dem Passphrase gelöscht werden:

root@testtest:~ # rm /kennwort.txt

Ebenfalls kann nun auch das unverschlüsselte Dataset weg:

root@testtest:~ # zfs destroy -r zroot/varta

Wenn man nun möchte, kann man das neue Dataset natürlich an die gleiche Stelle mounten oder direkt komplett gleich dem alten benennen:

root@testtest:~ # zfs rename zroot/en-varta zroot/varta

Damit ist die Migration fertig und das Dataset ist verschlüsselt:

root@testtest:~ # zfs list zroot/varta
NAME          USED  AVAIL     REFER  MOUNTPOINT
zroot/varta   100M  11.9G      100M  /zroot/varta
root@testtest:~ # zfs get encryption,keylocation,keyformat zroot/varta
NAME         PROPERTY     VALUE        SOURCE
zroot/varta  encryption   aes-256-gcm  -
zroot/varta  keylocation  prompt       local
zroot/varta  keyformat    passphrase   -

Es sieht nun nach sehr viel aus, ist es aber nicht und es lässt sich sogar automatisieren.

Fragen? Dann fragen!

Firmware- und BIOS-Updates unter Linux einfach mit fwupd durchführen​

Bild vom fwupdmgr update in Aktion.

Firmware und BIOS Updates müssen hin und wieder sein um Fehler zu beseitigen oder Unterstützung für neuere Komponenten zu erhalten. Dieses unter Linux zu tun, war nicht immer einfach. Oft bieten die Hersteller nur Software für DOS oder vielleicht sogar noch Windows an. Der Support für Linux war eher selten vorhanden und beschränkte sich dabei eher auf Serversysteme. Wenn ich früher an meinem Linux Arbeitsplatz oder Notebook Firmware oder BIOS Updates installieren wollte, musste ich oft eine Festplatte aus der Kiste nehmen, Windows installieren, die nötigen Treiber für die Hardware installieren und mir dann die Herstellertools besorgen, um der Firmware ein Update zu verpassen. So macht es keinen Spaß und ist viel zu aufwendig.

Vor knapp 5 Jahren haben ein paar Gnome Entwickler zusammen mit dem Hersteller Dell mit der Entwicklung an einem Update Tool fwupd gestartet. Über dieses Tool gibt es nun die Möglichkeit Firmwareupdates auf einem einheitlichen Weg und über eine einheitliche Basis zu verteilen und zu installieren. Klar steht und fällt es weiterhin mit den Hardware Herstellern. Diese müssen sich nun aber nicht mehr um das eigentliche Tooling und den Support am Betriebssystem Linux kümmern, sondern müssen nur ihre eigentlichen Firmwareupdates in einem Online-Repository zur Verfügung stellen.

Jetzt kann jeder Linux Benutzer über einen sehr einfachen Weg Firmware und BIOS Updates einspielen. Für Gnome und KDE gibt es dazu sogar eine GUI, über die CLI geht es genau so einfach.

fwupd kann dabei im Hintergrund als Daemon laufen, täglich nach neuen Firmwareupdates suchen und diese installieren oder zur Installation ankündigen.

Nun möchte ich es mir nicht nehmen lassen, mit euch einen kurzen Ablauf eines solchen Firmwareupdates auf der CLI durchzuführen. Also… Los geht es!

Testgerät dafür ist ein Lenovo ThinkPad, um zu sehen welche Hardware von fwupd erkannt und unterstützt wird, hilft folgender Aufruf:

root@errorlap:/home/kernel# fwupdmgr get-devices
20N588101
│
├─Thunderbolt Controller:
│     Device ID:           149dca4a469318aced513ec818b67eeac46753e9
│     Summary:             Unmatched performance for high-speed I/O
│     Current version:     20.00
│     Vendor:              Lenovo (TBT:0x0109)
│     GUIDs:               52265728-359a-574c-9a6a-a23d3b1f952d ← TBT-01091804-native
│                          f117e89e-a75f-5f33-9e8e-c4aded9cbadf ← TBT-01091804-native-controller0-0
│     Device Flags:        • Internal device
│                          • Updatable
│                          • Requires AC power
│                          • Device stages updates
│   
├─SAMSUNG MZVLB256HB88-000L7:
│     Device ID:           f2759da7fe8e0388c5f3601cb072f837b1070b03
│     Summary:             NVM Express Solid State Drive
│     Current version:     4M2QEXH7
│     Vendor:              Samsung Electronics Co Ltd (NVME:0x144D)
│     Serial Number:       S4ELN88N881038
│     GUIDs:               6e54c992-d302-59ab-b454-2d26ddd63e6d ← NVME\VEN_144D&DEV_A808&REV_00
│                          47335265-a509-51f7-841e-1c94911af66b ← NVME\VEN_144D&DEV_A808
│                          1b3b43f9-e0b0-5978-a89b-6f0866124233 ← SAMSUNG MZVLB256HBHQ-000L7
│     Device Flags:        • Internal device
│                          • Updatable
│                          • Requires AC power
│                          • Needs a reboot after installation
│                          • Device is usable for the duration of the update
│   
├─System Firmware:
│     Device ID:           6150dd1f7291b0709289ab8a53cc85a17e117ef2
│     Current version:     0.1.65
│     Minimum Version:     0.0.1
│     Vendor:              LENOVO (DMI:LENOVO)
│     GUID:                603baf73-b997-45b5-86b4-2f981a008e18
│     Device Flags:        • Internal device
│                          • Updatable
│                          • Requires AC power
│                          • Needs a reboot after installation
│                          • Cryptographic hash verification is available
│                          • Device is usable for the duration of the update
│   
├─UEFI Device Firmware:
│     Device ID:           c0649684d1e6688e8147fac95eccb4fdd18d05aa
│     Current version:     192.64.1551
│     Minimum Version:     0.0.1
│     Vendor:              DMI:LENOVO
│     GUID:                2c0665e2-fdbd-495e-b8e4-69d92b9c119a
│     Device Flags:        • Internal device
│                          • Updatable
│                          • Requires AC power
│                          • Needs a reboot after installation
│                          • Device is usable for the duration of the update
│   
├─UEFI Device Firmware:
│     Device ID:           489f23b2ba9c1adf3e9f9f10598c98ba5c6bba39
│     Current version:     0.1.19
│     Minimum Version:     0.1.19
│     Vendor:              DMI:LENOVO
│     GUID:                38ea6335-29ca-417b-8cd4-6b4e5e866f92
│     Device Flags:        • Internal device
│                          • Updatable
│                          • Requires AC power
│                          • Needs a reboot after installation
│                          • Device is usable for the duration of the update
│   
└─UEFI Device Firmware:
      Device ID:           88cf266a57697921241cc5f4b412c3f1b5a07780
      Current version:     1.1.8
      Minimum Version:     0.0.1
      Vendor:              DMI:LENOVO
      GUID:                a6634b3a-f446-42f0-a0b2-62c7d4dcb694
      Device Flags:        • Internal device
                           • Updatable
                           • Requires AC power
                           • Needs a reboot after installation
                           • Device is usable for the duration of the update

Wie man sehen kann, ist bei diesem Gerät der Support recht weitreichend. Damit fwupd in seinem „Katalog“ überprüfen kann, ob es für eine bestimmte Hardware ein Update gibt, muss man diese kurz aktualisieren. Dieses geht direkt mit einem: fwupdmgr refresh –force

Natürlich merkt fwupd auch selbst, wenn sein Datenstand alt ist und bietet ein Update vor der Überprüfung an.

root@errorlap:/home/kernel# fwupdmgr get-updates
Firmware metadata has not been updated for 30 days and may not be up to date.

Update now? (Requires internet connection) [y|N]: y
Fetching metadata https://cdn.fwupd.org/downloads/firmware.xml.gz
Downloading…             [***************************************]
Fetching signature https://cdn.fwupd.org/downloads/firmware.xml.gz.asc

Successfully downloaded new metadata: 5 local devices supported
• Thunderbolt Controller has the latest available firmware version
• SAMSUNG MZVLB256HBHQ-000L7 has the latest available firmware version
• UEFI Device Firmware has the latest available firmware version
• UEFI Device Firmware has no available firmware updates
20N588101
│
├─System Firmware:
│ │   Device ID:           6150dd1f7291b0709289ab8a53cc85a17e117ef2
│ │   Current version:     0.1.65
│ │   Minimum Version:     0.0.1
│ │   Vendor:              LENOVO (DMI:LENOVO)
│ │   GUID:                603baf73-b997-45b5-86b4-2f981a008e18
│ │   Device Flags:        • Internal device
│ │                        • Updatable
│ │                        • Requires AC power
│ │                        • Supported on remote server
│ │                        • Needs a reboot after installation
│ │                        • Cryptographic hash verification is available
│ │                        • Device is usable for the duration of the update
│ │ 
│ ├─ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS for Machine types: 20N2, 20N3, 20N4, 20N5, 20N6, 20N7, 20Q9, 20QH, 20RH, 20RJ) System Update:
│ │     New version:       0.1.70
│ │     Remote ID:         lvfs
│ │     Summary:           Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC System Firmware
│ │     License:           Proprietary
│ │     Size:              25,1 MB
│ │     Vendor:            Lenovo Ltd.
│ │     Flags:             is-upgrade
│ │     Description:       Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS) System Firmware Version 1.70
│ │     
│ │     The computer will be restarted automatically after updating BIOS completely. Do NOT turn off your computer or remove the AC adaptor while update is in progress.
│ │     
│ │     This stable release fixes the following issues:
│ │     
│ │      • Fixed an issue where Setup Settings Capture/Playback Utility (SRSETUP) causes 191 error if Secure Boot Mode is reset to Setup Mode and
│ │     
│ │     Supervisor Password is changed at the same time.
│ │     
│ │      • Fixed an issue where system might hang at POST when Thunderbolt3 Dock Gen2 is attached.
│ │   
│ ├─ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS for Machine types: 20N2, 20N3, 20N4, 20N5, 20N6, 20N7, 20Q9, 20QH, 20RH, 20RJ) System Update:
│ │     New version:       0.1.69
│ │     Remote ID:         lvfs
│ │     Summary:           Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC System Firmware
│ │     License:           Proprietary
│ │     Size:              25,1 MB
│ │     Vendor:            Lenovo Ltd.
│ │     Flags:             is-upgrade
│ │     Description:       Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS) System Firmware 1.69
│ │     
│ │     The computer will be restarted automatically after updating BIOS completely. Do NOT turn off your computer or remove the AC adaptor while update is in progress.
│ │     
│ │     This stable release fixes the following issues:
│ │     
│ │      • This time BIOS release has no impact for Linux users.
│ │   
│ ├─ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS for Machine types: 20N2, 20N3, 20N4, 20N5, 20N6, 20N7, 20Q9, 20QH, 20RH, 20RJ) System Update:
│ │     New version:       0.1.68
│ │     Remote ID:         lvfs
│ │     Summary:           Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC System Firmware
│ │     License:           Proprietary
│ │     Size:              25,1 MB
│ │     Vendor:            Lenovo Ltd.
│ │     Flags:             is-upgrade
│ │     Description:       Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS) System Firmware 1.68
│ │     
│ │     The computer will be restarted automatically after updating BIOS completely. Do NOT turn off your computer or remove the AC adaptor while update is in progress.
│ │     
│ │     This stable release fixes the following issues:
│ │     
│ │      • Fixed an issue where keyboard language settings could not be applied by Setup Settings Capture/Playback Utility (SRSETUP).
│ │      • Fixed an issue where WWAN device firmware update process might fail when Thunderbolt BIOS Assist Mode is set to Enabled.
│ │      • Fixed an issue where BIOS might generate 0288 beep error.
│ │      • Support for TCO Certified Logo shown on POST screen.
│ │   
│ ├─ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS for Machine types: 20N2, 20N3, 20N4, 20N5, 20N6, 20N7, 20Q9, 20QH, 20RH, 20RJ) System Update:
│ │     New version:       0.1.67
│ │     Remote ID:         lvfs
│ │     Summary:           Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC System Firmware
│ │     License:           Proprietary
│ │     Size:              25,1 MB
│ │     Vendor:            Lenovo Ltd.
│ │     Flags:             is-upgrade
│ │     Description:       Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS) System Firmware 1.67
│ │     
│ │      • Fixed an issue where Intel TXT Feature cannot be Enabled in ThinkPad Setup
│ │     
│ │     when Device Guard is Enabled.
│ │     
│ │      • Fixed an issue where system might hang at POST when attach USB C to DisplayPort
│ │     
│ │     Adapter cable.
│ │     
│ │      • Support Lid Sensor Enable/Disable in ThinkPad Setup - Config - Power.
│ │      • Updated the CPU microcode.
│ │     
│ │     Note: Above update will show "Self-Healing BIOS  backup progressing ... xx %"
│ │     
│ │     massage on screen during BIOS update process.
│ │     
│ │      • Updated the Arrow key behavior in ThinkPad Setup with Graphical Setup UI.
│ │     
│ │     Security issues fixed:
│ │     
│ │      • CVE-2020-0548
│ │      • CVE-2020-0549
│ │      • CVE-2020-0543
│ │   
│ └─ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS for Machine types: 20N2, 20N3, 20N4, 20N5, 20N6, 20N7, 20Q9, 20QH, 20RH, 20RJ) System Update:
│       New version:       0.1.66
│       Remote ID:         lvfs
│       Summary:           Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC System Firmware
│       License:           Proprietary
│       Size:              25,1 MB
│       Vendor:            Lenovo Ltd.
│       Flags:             is-upgrade
│       Description:       Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC (W-BIOS) System Firmware 1.66
│       
│       The computer will be restarted automatically after updating BIOS completely. Do NOT turn off your computer or remove the AC adaptor while update is in progress.
│       
│       This stable release fixes the following issues:
│       
│        • Fixed an issue where system performance may not set correctly.
│       
│       Some new functionality has also been added:
│       
│        • Updated Network Boot Device and Boot conditions.
│       
│       Note: Above update will show "Self-Healing BIOS  backup progressing ... xx %" massage on screen during BIOS update process.
│     
└─UEFI Device Firmware:
  │   Device ID:           c0649684d1e6688e8147fac95eccb4fdd18d05aa
  │   Current version:     192.64.1551
  │   Minimum Version:     0.0.1
  │   Vendor:              DMI:LENOVO
  │   GUID:                2c0665e2-fdbd-495e-b8e4-69d92b9c119a
  │   Device Flags:        • Internal device
  │                        • Updatable
  │                        • Requires AC power
  │                        • Supported on remote server
  │                        • Needs a reboot after installation
  │                        • Device is usable for the duration of the update
  │ 
  └─ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s Corporate ME Update:
        New version:       192.71.1681
        Remote ID:         lvfs
        Summary:           Lenovo ThinkPad T490/P43s/T590/P53s Corporate ME Firmware
        License:           Proprietary
        Size:              12,2 MB
        Details:           https://pcsupport.lenovo.com/de/en/search?query=N2IRM29W
        Vendor:            Lenovo Ltd.
        Flags:             is-upgrade
        Description:       Lenovo ThinkPad T490/ThinkPad P43s/ThinkPad T590/ThinkPad P53s/ThinkPad T490 HC ME Corporate Firmware Version:  (12.0.71.1681)
        
        This stable release fixes the following issues:
        
         • Fixed an issue wherein BIOS returned wrong vaue following an Intel CSME update to 12.0.64.1551.
         • Fixed an issue wherein IntelR AMT SUT couldn't change from CCMP to TKIP through WebUI
         • Fixed an issue wherein there was Failure to update IntelR CSME software from version 1910.12.0.1239 to 1932.12.0.1298 after OS recovery reset complete.
         • Fixed an issue wherein System stayed on S3 state and IntelR AMT PowerState shows 乬on乭.
        
        Security issues fixed:
        
         • CVE-2020-12356
         • CVE-2020-12303
         • CVE-2020-12297
         • CVE-2020-8752
         • CVE-2020-8749
         • CVE-2020-8746
         • CVE-2020-8747
         • CVE-2020-8754
         • CVE-2020-8751
         • CVE-2020-8760
         • CVE-2020-8756
         • CVE-2020-8757
         • CVE-2020-8705
         • CVE-2020-8745
         • CVE-2020-8744
         • CVE-2020-8753

Wie man sehen kann, gibt es ein Update für UEFI Device Firmware von Version 192.64.1551 auf Version 192.71.1681. Zusätzlich werden vom Hersteller der Hardware über die Device Flags Vorbedinungen angegeben, die erfüllt sein müssen, um das Update einspielen zu können. Als Beispiel sollte der Notebook am Netzteil angeschlossen sein und nach dem Update ist ein Reboot nötig um die neue Firmware zu nutzen….. Ebenfalls wird mir direkt aufgelistet, welche Änderungen dieses Firmwarupdate mit sich bringt.

Um das Firmwareupdate nun zu installieren ist folgendes nötig:

root@errorlap:/home/kernel# fwupdmgr update
• SAMSUNG MZVLB256HB88-000L7 has the latest available firmware version
• System Firmware has the latest available firmware version
Upgrade available for UEFI Device Firmware from 192.64.1551 to 192.71.1681
20N588101 must remain plugged into a power source for the duration of the update to avoid damage. Continue with update? [Y|n]: y
Downloading 192.71.1681 for UEFI Device Firmware...
Decompressing…           [***************************************]
Authenticating…          [***************************************]
Updating UEFI Device Firmware…                                   ]
Scheduling…              [***************************************]
Successfully installed firmware
• UEFI Device Firmware has the latest available firmware version
• UEFI Device Firmware has no available firmware updates
• UEFI Device Firmware has no available firmware updates

An update requires a reboot to complete. Restart now? [y|N]: 

Beim Reboot begegnet mir in meinem Fall das UEFI BIOS des Notebooks mit den Informationen, dass es nun die nötigen Firmwareupdates durchführt (ich habe dazu ein paar Bilder gemacht). Ist alles durchgelaufen und das System wieder hochgefahren, kann ich alles mit folgendem Befehl prüfen:

root@errorlap:/home/kernel# fwupdmgr get-updates
• SAMSUNG MZVLB256HB88-000L7 has the latest available firmware version
• System Firmware has the latest available firmware version
• UEFI Device Firmware has the latest available firmware version
• UEFI Device Firmware has the latest available firmware version
• UEFI Device Firmware has no available firmware updates
• UEFI Device Firmware has no available firmware updates
________________________________________________

Devices that have been updated successfully:

 • System Firmware (0.1.65 → 0.1.70)
 • UEFI Device Firmware (192.64.1551 → 192.71.1681)

Uploading firmware reports helps hardware vendors to quickly identify failing and successful updates on real devices.
Upload report now? (Requires internet connection):
0.	Do not upload reports at this time, but prompt again for future updates
1.	Do not upload reports, and never ask to upload reports for future updates
2.	Upload reports just this one time, but prompt again for future updates
3.	Upload reports this time and automatically upload reports after completing future updates
3
Successfully uploaded 1 report

Das Update ist gut gelaufen und ich habe die letzte Version installiert!

Wie beschrieben, steht und fällt es mit den Herstellern der Hardware. Was helfen könnte diese zur Mitarbeit zu bewegen ist, wie so oft, nachfragen. Sollte eure Hardware also nicht „mitspielen“, einfach mal eine kurze Nachricht an den Support schicken und fragen, warum die denn nicht zusammen mit fwupd arbeiten. FreeBSD oder generell BSD Benutzer wird die Information freuen, dass es recht aktuell Bemühungen gibt, fwupd ebenfalls auf BSD zu portieren: https://fosdem.org/2021/schedule/event/porting_fwupd_to_the_bsd/

Wer nun noch Fragen hat, bitte fragen 🙂

TRIM für SSDs im ZFS-Pool unter Linux aktivieren: So funktioniert’s​

Speicherzellen eine SSD sind nicht unendlich beschreibbar. Irgendwann sind sie „kaputt“. Damit dieses möglichst spät passiert, hat jede SSD eine interne Logik, um Schreibzugriffe möglichst gut auf Speicherbereiche zu verteilen. Im optimalen Fall wird jeder Speicherbereich gleich oft zum Schreiben benutzt. Damit dieses möglichst gut funktioniert, muss die SSD wissen, welche Speicherbereiche wirklich frei sind. Diese Information kann die SSD fast nur vom Filesystem selbst bekommen. Damit die Info weitergeleitet wird, gibt es TRIM https://de.wikipedia.org/wiki/TRIM.

ZFS bietet diese Möglichkeit natürlich auch und dieses ebenfalls unter Linux. Im zpool nennt sich diese Option autotrim und um zu prüfen ob es aktiviert ist, hilft folgender Befehl:

$ zpool get autotrim bpool rpool
NAME   PROPERTY  VALUE     SOURCE
bpool  autotrim  off        local
rpool  autotrim  off        local

Wie man sehen kann, gibt es die beiden ZFS Pools mit den Namen bpool und rpool. Auf beiden ist autotrim deaktiviert. Zum Aktivieren ist folgender Befehl nötig:

$ zpool set autotrim=on bpool
$ zpool set autotrim=on rpool

Wenn man nun prüft, ob es aktiviert ist:

$ zpool get autotrim bpool rpool
NAME   PROPERTY  VALUE     SOURCE
bpool  autotrim  on        local
rpool  autotrim  on        local

Sollte man dieses bestätigt bekommen.

Einen kleinen Tipp habe ich darüber hinaus zusätzlich noch. Wenn eine SSD an den Strom angeschlossen wird, ohne dass ein „Computer“ angeschlossen ist, fallen viele SSD in eine Art Wartungs- / Reparaturmodus. Dann sortieren SSDs selbstständig ihre Speicherzellen um. Wenn also einmal etwas in den ersten Speicherbereich geschrieben wurde, ist dieses nicht gleichbedeutend, dass es für immer in nur diesem Bereich liegen bleibt. Im laufenden Betrieb wird dieses verschoben, wenn die SSD (wie beschrieben) nur am Strom angeschlossen ist forciert man dieses zusätzlich bei vielen SSDs. Einfach 2 / 3 Stunden „laufen“ lassen… Hin und wieder lassen sich über diesen Weg „tote“ SSDs wiederbeleben. Alles funktioniert natürlich mit TRIM viel besser 😀

Frage? Dann fragen..

FreeBSD und Netcup: Probleme mit IPv6 lösen

Als Kunden der bei netcup FreeBSD „rootserver“ auf KVM qemu Basis einsetzt, habe ich schnell gemerkt, dass meine IPv6 Verbindung nicht stabil ist.

Bild wie ein Dinosaurier ein Patchkabel durchbeißt, im Hintergrund ist das Buch IPv6 Workshop zu erkennen.

Dieses zeigt sich wie folgt:

– Direkt nach dem Boot scheinen IPv6 Verbindungen zu funktionieren, wie gewünscht.

– Nach einiger Zeit brechen die Verbindungen zusammen, sowohl Verbindungen vom System in die Welt als auch Verbindungen von der Welt ins System.

– Verbindungen scheinen „Startprobleme“ zu haben. Ein ping läuft erst ein paar Mal ins Leere und dann funktionieren alle Verbindungen plötzlich wieder für einen Moment.

Ein möglicher Workaround ist es, vom System aus einen ping auf die IPv6 Adresse des Gateways von netcup zu starten. Dieses sorgt in der Regel kurzzeitig für funktionsfähige IPv6 Verbindungen. Aber was ist das genaue Problem und wie könnte eine brauchbare Lösung aussehen?

Als Leser mit IPv6 Wissen, denkt man natürlich sofort a NDP das Neighbor Discovery Protocol und ja ich denke genau hier liegt das Problem. Dieses unterscheidet sich zur Implementation bei Linux etwas, daher funktioniert IPv6 im netcup Testsystem problemfrei unter FreeBSD, NetBSD usw. aber nicht. Die Probleme im NDP lassen sich auf dem System schnell wie folgt erkennen:

root@netcup-vps:~ # netstat -s -picmp6
icmp6:
    0 calls to icmp6_error
    0 errors not generated in response to an icmp6 message
    0 errors not generated because of rate limitation
    Output histogram:
        neighbor solicitation: 29
        neighbor advertisement: 10
        MLDv2 listener report: 8
    0 messages with bad code fields
    0 messages < minimum length
    0 bad checksums
    0 messages with bad length
    Input histogram:
        router advertisement: 17
        neighbor solicitation: 633
        neighbor advertisement: 25
    Histogram of error messages to be generated:
        0 no route
        0 administratively prohibited
        0 beyond scope
        0 address unreachable
        0 port unreachable
        0 packet too big
        0 time exceed transit
        0 time exceed reassembly
        0 erroneous header field
        0 unrecognized next header
        0 unrecognized option
        0 redirect
        0 unknown
    0 message responses generated
    0 messages with too many ND options
    0 messages with bad ND options
    423 bad neighbor solicitation messages
    0 bad neighbor advertisement messages
    0 bad router solicitation messages
    0 bad router advertisement messages
    0 bad redirect messages
    0 path MTU changes

Ich habe einige Zeit damit verbracht, mich mit dem Support darüber auszutauschen. Wie immer landet man zuerst in der human firewall, im Anschluss erreichte ich oft Supportmitarbeiter in Ausbildung eines IT Berufes. Zwischenzeitlich wurde mir das Problem von netcup dann auch bestätigt und mit dem Hinweis versehen, dass es an ihren Core-Routern liege, welche irgendwann ein Update bekommen sollen. Wann genau dieses Updates gemacht wird, konnte/wollte mir niemand bestätigen. Ebenfalls wurde versucht mein System auf verschiedene Hosts zu verschieben, von welchen andere Kunden wohl positives berichtet hatten. Dann sollte das Problem irgendwann behoben sein und netcup war erstaunt, dass es dieses noch nicht ist. Was auch immer… Aus meiner Sicht liegt das Problem an netcup.

Gelöst werden kann dadurch, dass man seinem BSD mitteilt, es soll bitte ND nach RFC4861 machen. Dieses ähnelt zumindest im Punkt der Bindung des jeweiligen ND ans Interface. Dafür kann man dieses als kurzen Test wie folgt aktivieren:

sysctl net.inet6.icmp6.nd6_onlink_ns_rfc4861=1

Stellt sich der gewünschte Erfolg ein, wird es mit dem passenden Eintrag in der /etc/sysctl.conf permanent aktiviert:

net.inet6.icmp6.nd6_onlink_ns_rfc4861=1

Dabei aber bitte beachten, dass FreeBSD dieses vor ca. 10 Jahren aus Sicherheitsgründen deaktiviert hat. https://www.freebsd.org/security/advisories/FreeBSD-SA-08:10.nd6.asc

Ich bin mit meinen Bemühungen aber leider nicht zu einer, für mich funktionierenden, Lösung von Seiten netcups gekommen. Daher blieb mir nur RFC4861.

Ich denke das Problem ist sicher schon lange beim Support bekannt, einfache google Suchen oder im netcup Forum zeigen dieses schnell auf. Dennoch vermittelte der Support mir erst das Gefühl, selbst etwas falsch konfiguriert zu haben, nur um mir dann den Eindruck zu vermitteln, dass sie noch nie von einem solchen Problem gehört haben. Ich vermute daher, dass ihr Setup aktuell einfach keine „einfache“ Lösung dieses Problems zulässt und sie daher so agieren. Was aber natürlich reine Spekulation ist, ich kann auch nur „vor“ das Setup schauen.

Fragen? Dann fragen…

Linux Mint 20.1: Verschlüsselten ZFS-Root-Pool während der Installation einrichten​

Zu ZFS und warum man es haben will, muss ich hier sicher nicht mehr viel schreiben. Ebenfalls wird sich niemand mehr die Frage stellen, warum man seine Festplatte verschlüsseln möchte.

ABER wenn man nun Linux, ZFS und Verschlüsselung kombinieren möchte, dann gibt es etwas, worüber es sich zu schreiben lohnt. Wie man nun also sehr einfach unter sein Linux Mint >= 20.x einen native encryptet zfs root pool bekommt, darum geht es hier.

Linux ZFS Encryption enter password.

Linux Mint bringt seit Version 20 bereits alles mit um dieses ohne besonderen Aufwand zu erledigen. Natürlich ging es bereits schon früher, nur war es dann fast nur über den Weg möglich, die Festplatte inkl. Grub vollständig von Hand vor und während der Installation selbst fertig zu machen. Dieses ist… Sagen wir mal… „Für den erweiterten Anwender schon fast nicht zu machen“.

Zurück zu Linux Mint 20.x!

Wie erwähnt bringt diese Version alles Nötige mit, nur der Installer ist noch nicht ganz so weit und man muss ihm mit zwei Kleinigkeiten unter die Arme greifen. Einmal muss man die nötigen Pakete im Live-System nachinstallieren. Also einfach die gewünschte Version von Linux mit downloaden und davon booten. Ist man im Live-System angekommen, öffnen man ein Terminal und wirft die Installation der Pakete mit folgendem Befehl an:

sudo aptitude -y install libzfs2linux zfs-initramfs zfsutils-linux zfs-zed

Möchte man nun einfach nur sein Linux Mint auf einem ZFS Pool installieren, ist man schon fertig. Einfach den Installer starten und beim Punkt, auf welche Festplatte man sein neues System installieren möchte auf Advanced features… klicken und unten auf EXPERIMENTAL: Erase disk and use ZFS. Fertig ist!

Möchte man noch seinen zroot Pool verschlüsseln fehlt noch die zweite Kleinigkeit. Da der Installer den Wunsch und somit ebenfalls das Kennwort zur Verschlüsselung des ZFS Pools nicht abfragt, muss man es dem Installer mitgeben, bevor er mit seiner Arbeit startet. Dazu bleibt man im Terminal und editiert das Installerscript wie folgt:

sudo vi /usr/share/ubiquity/zsys-setup

Hier sucht man nun die Sektion, in welcher es ums Anlegen der ZFS Pools geht ?zpool create wäre eine gute Suche 😉

Hat man dieses gefunden (derzeit sollte es genau zwei Mal im Installerscript auftauchen) setzt man einfach vor das zpool create des rpools ein:

echo 'SUPER-SECURE' | 

Die Hochkomma bleiben dabei stehen und ihr ersetzt SUPER-SECURE durch euer gewünschtes Kennwort, was sich natürlich schon jeder gedacht hat. Damit wird dem zpool create rpool später im Installationsprozess euer Kennwort übergeben.

Fehlen nur noch die Optionen beim Erstellen des Pools, damit er ihn auch verschlüsselt. Dafür bitte folgendes vor die Zeile -O mountpoint=/ -R „${target}“ rpool „${partrpool}“ eintragen:

-O encryption=aes-256-gcm \
-O keylocation=prompt \
-O keyformat=passphrase \

Am Ende sieht der Ausschnitt also beispielhaft wie folgt aus:

echo 'Kennwort!' | zpool create -f \
        -o ashift=12 \
        -O compression=lz4 \
        -O acltype=posixacl \
        -O xattr=sa \
        -O relatime=on \
        -O normalization=formD \
        -O mountpoint=/ \
        -O canmount=off \
        -O dnodesize=auto \
        -O sync=disabled \
        -O encryption=aes-256-gcm \
        -O keylocation=prompt \
        -O keyformat=passphrase \
        -O mountpoint=/ -R "${target}" rpool "${partrpool}"

Das war es auch schon. Jetzt, wie gewohnt den Installer starten und schon wird man nach dem Reboot aufgefordert seinen ZFS Pool mit einem Kennwort zu entschlüsseln. Oh, geht natürlich so mit EFi und lagacy und überhaupt….

Ob alles so funktioniert hat, wie man es sich vorstellt, lässt sich direkt nach dem ersten Boot ins neue System prüfen. Einfach Terminal öffnen und mittels folgender Befehle prüfen, ob die Verschlüsselung aktiviert ist und sich auch sauber durch den Pool bis zu den Benutzerdaten weiter vererbt hat:

test@test-VirtualBox:~$ sudo zpool list
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
bpool  1,38G  97,3M  1,28G        -         -     0%     6%  1.00x    ONLINE  -
rpool  26,5G  4,46G  22,0G        -         -     3%    16%  1.00x    ONLINE  -
test@test-VirtualBox:~$ sudo zpool get feature@encryption
NAME   PROPERTY            VALUE               SOURCE
bpool  feature@encryption  disabled            local
rpool  feature@encryption  active              local
test@test-VirtualBox:~$ sudo zfs get encryption rpool/USERDATA/test_9d9i92
NAME                        PROPERTY    VALUE        SOURCE
rpool/USERDATA/test_9d9i92  encryption  aes-256-gcm  -
test@test-VirtualBox:~$

Hier noch Bilder zum Klicken, das mögen ja viele.

Fragen? Dann fragen…

SSH-Brute-Force mit veralteter Implementierung: Angriffsmuster erkennen​

Wenn man mit einem System im Internet steht fummelt immer irgendein script kiddie oder bot an den Diensten herum. Oft ist hier eine IP Adresse aus China dabei. Dann probieren sie ein paar default logins und wandern weiter zur nächsten IP Adresse. Die Bots geben dem Ganzen in der Regel schon nicht mehr als drei Versuche, weil sie dann eh von irgendeinem Sicherheitssystem geblockt werden. Da es noch viele andere bots hinter anderen IP Adressen gibt, übermittelt der bot nur seinen Stand der Versuche an das Hirn des Botnetzes und der nächste, nicht geblockte bot, kommt und probiert es weiter…

Alles „kalter Kaffee“… In den letzten Wochen fallen mir zwei kleine Veränderungen auf.

old SSH Bot

Einmal kommen diese IP Adressen noch immer stark aus China… ABER sehr oft ebenfalls von DigitalOcean (USA). Zudem fallen mir die anderen Cloudprovider auf (Google, Microsoft, AWS…). Das verschiebt sich aktuell wohl etwas. Normalerweise kommt ganz viel aus China, dann ganz viel von verschiedenen dynamischen Endkundenanschlüssen auf der Erde. Jetzt kommt ganz viel aus China, dann unglaublich nahe daran Digitalocean, direkt gefolgt von der google-cloud und microsoft-cloud. Erst jetzt kommen die Endkundenanschlüsse und mischen sich mit Adressen aus der AWS-Cloud. Scheinbar haben die Amazonjungs irgendetwas „besser“ gemacht, um ihre Kunden davor zu schützen sich etwas „einzufangen“?!?

Zweitens scheint da ein Botnetz mit recht alter ssh Implementierung unterwegs zu sein. Oder es sucht halt speziell alte SSH-Server? Auf IoT Geräte mit alter Firmware tippe ich weniger, denn von diesen kommt ebenfalls etwas von Cloudanbietern. Bei denen unterstelle ich einfach mal, keine alten IoT Geräte im Einsatz zu haben, die infiziert sind. Naja… Oder es wird halt nach genau solchen Geräten gesucht. Warum alt? Weil ich so etwas in den Logs finde:

Apr  8 10:35:58 YOURMOM sshd[43201]: reverse mapping checking getaddrinfo for 4.3.2.1.serverdedicati.mum.your [1.2.3.4] failed.
Apr  8 10:35:58 YOURMOM sshd[43201]: Did not receive identification string from 1.2.3.4 port 34244
Apr  8 10:36:22 YOURMOM sshd[43202]: reverse mapping checking getaddrinfo for 4.3.2.1.serverdedicati.mum.your [1.2.3.4] failed.
Apr  8 10:36:22 YOURMOM sshd[43202]: Unable to negotiate with 1.2.3.4 port 36160: no matching key exchange method found. Their offer: diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1 [preauth]
Apr  8 10:36:42 YOURMOM sshd[43204]: reverse mapping checking getaddrinfo for 4.3.2.1.serverdedicati.mum.your [1.2.3.4] failed.
Apr  8 10:36:42 YOURMOM sshd[43204]: Unable to negotiate with 1.2.3.4 port 39556: no matching key exchange method found. Their offer: diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1 [preauth]

Wie ist das bei euch?

Von RSA zu ECDSA: Sichere Zertifikate für Web- und Mailserver​

….. naja, fast :-/

Wir sind alle in 2020 angekommen und so laaaannngggsssaaammmm könnte man von 4096 bit RSA Zertifikaten mal auf >= 256 bit EC Zertifikate wechseln, oder? Bringt mehr Sicherheit, die Schlüssel sind kleiner und so schneller gerechnet und alle gängigen Browser machen es ebenfalls schon ein paar Jahre.

Vor knapp 6 Monaten habe ich daher einen Satz neuer Schlüssel erstellt und diese schon mal in mein HPKP Header eingebunden, damit der Key-Rollover gut funktioniert. Heute habe ich zu den Schlüsseln Zertifikate gebaut, diese von einer CA signieren lassen und alles eingebunden.

Bei meinem nginx vollkommen schmerzfrei. Einfach die neuen Schlüssel hinterlegt und die Cipherliste von allem RSA-Zeug befreit:

ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256;

Restart vom nginx und zack, schon läuft alles!

Bei den Webseiten also überhaupt kein Problem. Etwas anders ist es bei E-Mail! Postfix macht es natürlich schon, ach LANGE.. Aber ein Microsoft Exchange 2016 in der (weiter weiter fertigstellen) Installation natürlich nicht. Wenn ich also von so einem System weiterhin E-Mails erhalten möchte (ja will ich und per RSA kann so ein System es auch in ~sicher~), muss ich weiterhin etwas auf RSA Basis anbieten.

Jetzt haben sich die Entwickler(innen) bei Postfix schon so etwas gedacht und bieten dieses in der Konfiguration an. Also RSA Keys/Zertifikate? Richtig… OK, das ist nichts besonders aber das es in Kombination mit ECD Keys/Zertifikaten möglich ist. Ach schaut einfach mal die Konfiguration:

smtpd_tls_eckey_file = /usr/local/etc/postfix/ec-postfix.key
smtpd_tls_eccert_file = /usr/local/etc/postfix/ec-postfix.pem
smtpd_tls_key_file = /usr/local/etc/postfix/postfix.key
smtpd_tls_cert_file = /usr/local/etc/postfix/postfix.pem

Ha, ist das nicht schön? smtpd_tls_eckey_ und smtpd_tls_key_?!? Der Server wirft jedem Client nun also zwei Serverzertifikate entgegen. Einmal EC und einmal RSA (ok man braucht also nun ebenfalls zwei Zertifikate).

Schaut mal:

➜  ~ testssl.sh -t smtp smtp.kernel-error.de:25
[....]
  Server Certificate #1
   Signature Algorithm          SHA256 with RSA
   Server key size              RSA 4096 bits
   Server key usage             Digital Signature, Key Encipherment
   Server extended key usage    TLS Web Server Authentication, TLS Web Client Authentication
   Serial / Fingerprints        4F7A9159AEED9414B7D542ED / SHA1 908FD237EF13A6048077082023C4CDE092F55F33
                                SHA256 74E3984BD5F9FAC26375DAEA6F0326229A0F42AC2EE53088A73DFD5F65107FA9
   Common Name (CN)             *.kernel-error.de 
   subjectAltName (SAN)         *.kernel-error.de kernel-error.de 
   Issuer                       AlphaSSL CA - SHA256 - G2 (GlobalSign nv-sa from BE)
   Trust (hostname)             Ok via SAN wildcard (same w/o SNI)
   Chain of trust               Ok   
   EV cert (experimental)       no 
   ETS/"eTLS", visibility info  not present
   Certificate Validity (UTC)   403 >= 60 days (2020-02-26 14:19 --> 2021-04-05 13:58)
   # of certificates provided   2
   Certificate Revocation List  http://crl2.alphassl.com/gs/gsalphasha2g2.crl
   OCSP URI                     http://ocsp2.globalsign.com/gsalphasha2g2
   OCSP stapling                not offered
   OCSP must staple extension   --
   DNS CAA RR (experimental)    available - please check for match with "Issuer" above
                                iodef=mailto:kernel-erro@kernel-error.de, issue=comodoca.com, issue=geotrust.com, issue=globalsign.com, issue=letsencrypt.org, issue=thawte.com
   Certificate Transparency     yes (certificate extension)

  Server Certificate #2
   Signature Algorithm          SHA256 with RSA
   Server key size              EC 256 bits
   Server key usage             Digital Signature, Key Agreement
   Server extended key usage    TLS Web Server Authentication, TLS Web Client Authentication
   Serial / Fingerprints        24E25E2F3D57B41671392F25 / SHA1 763EE6D52D3CF0237D9858F27EDF42EF4696B1E2
                                SHA256 9C4C0FCE32BA7E8AEAF17210B509D871D6B2EF237E0E887D7190F28F28011143
   Common Name (CN)             *.kernel-error.de 
   subjectAltName (SAN)         *.kernel-error.de kernel-error.de 
   Issuer                       AlphaSSL CA - SHA256 - G2 (GlobalSign nv-sa from BE)
   Trust (hostname)             Ok via SAN wildcard (same w/o SNI)
   Chain of trust               Ok   
   EV cert (experimental)       no 
   ETS/"eTLS", visibility info  not present
   Certificate Validity (UTC)   365 >= 60 days (2020-02-26 13:37 --> 2021-02-26 13:37)
   # of certificates provided   2
   Certificate Revocation List  http://crl2.alphassl.com/gs/gsalphasha2g2.crl
   OCSP URI                     http://ocsp2.globalsign.com/gsalphasha2g2
   OCSP stapling                not offered
   OCSP must staple extension   --
   DNS CAA RR (experimental)    available - please check for match with "Issuer" above
                                iodef=mailto:kernel-erro@kernel-error.de, issue=comodoca.com, issue=geotrust.com, issue=globalsign.com, issue=letsencrypt.org, issue=thawte.com
   Certificate Transparency     yes (certificate extension)
[....]

Jetzt kann noch ein 2016 Microsoft Exchangeserver einliefern und auch die „coolen Kinder“. Was mache ich wohl 2021? Exchange 2016 ignorieren?!?!


Kleines Update, da es Fragen gab..

Natürlich sollte man seine ciphers in einer sinnigen Reihenfolge für seinen Postifx konfigurieren. Kommen sie in der Reihe erst nach den RSA ciphern wird es natürlich fast nie benutzt *kopfschüttel*. Leute bitte kein copy & paste, mitdenken!

Ein Beispiel für die cipherliste wäre:

tls_high_cipherlist = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256

TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 sind dabei für TLS1.3

ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256 sind für den gewünschten ECD-Key

ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256 sind dann für TLS 1.2 RSA Verbindungen.

Kommt nun ein Client/einliefernder Mailserver, dann wird dieser dank:

tls_preempt_cipherlist = yes

Die vom Server übermittelte cipherliste durchgehen und die erste für beide funktionierende Kombination benutzen.

RSA Verbindungen sehen dann so aus:

Mar  3 08:24:13 smtp postfix/smtpd[49650]: Anonymous TLS connection established from RSA-mailserver[1.2.3.4]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

ECD Verbindungen so:

Mar  3 08:23:53 smtp postfix/smtpd[49650]: Anonymous TLS connection established from EDC-mailserver[5.6.7.8]: TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)

Einfach, oder?

« Ältere Beiträge

© 2025 -=Kernel-Error=-

Theme von Anders NorénHoch ↑