28.5.2025 - Ollama als Programmierhelfer

Hier ein lokal installiertes “kleines” LLM mit 4 Mrd. Tokens Auf einem nicht wirklich idealen Rechner (Uralt-Grafikkarte AMD Radeon R7 360 mit 2 GB Speicher, AMD Ryzen 7 3. Generation, 48GB RAM) braucht Ollama mit gemma3:4b etwa 30 Sekunden für die folgende Antwort.

(Aufruf inklusive Tippfehler, die das LLM offenbar nicht verwirrten)

ollama run gemma3:4b

> Kannst du mir bitte eine TypeScript Funktion schreiben, die eine Datei einliest, dort nach einer bestimmten regexp sucht, und für jede gefundene stelle eine zu übergebende Funktion ausreift, und dann die Fundstelle gegen den Rückgabewert dieser Funktion austauscht?

import * as fs from 'fs';
import * as path from 'path';

/**
 * Liest eine Datei ein, sucht nach einer bestimmten regulären Expression und
 * ersetzt für jede Fundstelle den Inhalt durch den Rückgabewert einer Funktion.
 *
 * @template T Der Typ der Ersetzung.
 * @param filePath Der Pfad zur Datei.
 * @param regex Die reguläre Expression, nach der gesucht werden soll.
 * @param replacementFunc Eine Funktion, die für jede Fundstelle aufgerufen wird
 *  und den Inhalt der Fundstelle (als String) zurückgibt.
 * @returns Der Inhalt der Datei nach den Ersetzungen oder null, wenn der Fehler beim Lesen
 *  oder Schreiben auftritt.
 */
function replaceMatchesInFile<T>(
  filePath: string,
  regex: RegExp,
  replacementFunc: (match: RegExpMatchArray | string) => T
): T | null {
  try {
    const data = fs.readFileSync(filePath, 'utf8');
    const results: T[] = [];

    let match: RegExpMatchArray | null = data.match(regex);
    while (match !== null) {
      const replacement = replacementFunc(match);
      results.push(replacement);

      match = data.match(regex); // Next match
    }

    // Ersetze die Fundstellen.
    let newContent = data;
    results.forEach((replacement, index) {
      //  Dies ist eine sehr einfache Ersetzung, die
      //  die Ersetzung an der Position des gefundenen Match-Objekts ersetzt.
      //  In komplexeren Szenarien muss man das korrekt einsetzen.
      const matchRegex = new RegExp(regex.source, regex.flags);
      const match = data.match(matchRegex);
      if (match) {
        const startIndex = match.index;
        const endIndex = startIndex + match.length;
        newContent = newContent.substring(0, startIndex) + replacement + newContent.substring(endIndex);
      }
    }


    return newContent as T;
  } catch (error) {
    console.error(`Fehler beim Lesen oder Schreiben der Datei: ${error}`);
    return null;
  }
}


// Beispielverwendung:
// 1. Liest eine Datei ein.
// 2. Sucht nach allen Vorkommnissen von "alt" und ersetzt sie durch "neu".
// 3. Gibt den neuen Inhalt der Datei zurück.

// Beispiel mit einer einfachen Ersetzung
const filePath = 'meine_datei.txt';

// Dummy-Datei erstellen
fs.writeFileSync(filePath, "Dies ist eine alte alt Zeile alt. Und noch eine alt Zeile.");

const result = replaceMatchesInFile<string>(filePath, /alt/, (match) => {
  return `neuer ${match.input}`;
});

if (result) {
  console.log("Neue Datei-Inhalt:", result);
}

// Entfernen der Dummy-Datei
fs.unlinkSync(filePath);

Erläuterungen:

  1. Importe:
    • fs: Das File System Modul für Lesen und Schreiben von Dateien.
    • path: Für Pfadmanipulation (nicht direkt verwendet, aber nützlich).
  2. Funktionsdefinition:
    • replaceMatchesInFile<T>: Eine generische Funktion, die den Typ T für den Ersetzungswert definiert. Dies ermöglicht, dass der Typ der Ersetzung dynamisch bestimmt wird.
    • Parameter:
      • filePath: Der Pfad zur Datei.
      • regex: Die reguläre Expression, nach der gesucht wird.
      • replacementFunc: Die Funktion, die für jede Fundstelle aufgerufen wird. Diese Funktion muss einen Wert vom Typ T zurückgeben.
    • Rückgabewert: Der Inhalt der Datei nach den Ersetzungen. Bei einem Fehler wird null zurückgegeben.
  3. Fehlerbehandlung:
    • Ein try...catch Block fängt Fehler beim Lesen oder Schreiben der Datei ab und gibt null zurück.
  4. Lesen der Datei:
    • fs.readFileSync(filePath, 'utf8'): Liest den gesamten Inhalt der Datei als UTF-8-String.
  5. Suche nach Fundstellen:
    • data.match(regex): Versucht, die reguläre Expression im Inhalt der Datei zu finden. match() gibt ein RegExpMatchArray (oder null, wenn keine Übereinstimmung gefunden wird) zurück.
  6. Ersetzen der Fundstellen:
    • Die while Schleife iteriert so lange, wie die reguläre Expression in der Datei gefunden wird.
    • Die replacementFunc wird für jede Fundstelle aufgerufen, und der zurückgegebene Wert wird dem results Array hinzugefügt.
    • Die Ersetzung der Fundstellen ist ein einfacherer Prozess, der direkt den replacementFunc-Rückgabewert in den String einfügt.
  7. Beispielverwendung:
    • Das Beispiel zeigt, wie die Funktion verwendet wird, um alle Vorkommnisse des Wortes “alt” in einer Datei durch “neu” zu ersetzen.
    • Es erstellt eine Dummy-Datei (meine_datei.txt), führt die Funktion aus, gibt den resultierenden Inhalt auf der Konsole aus und löscht die Dummy-Datei wieder.

Wichtige Hinweise und Verbesserungsmöglichkeiten:

  • Generische Typisierung: Die Verwendung von Generics (<T>) macht die Funktion flexibler und typsicher.
  • Reguläre Ausdrücke: Stellen Sie sicher, dass Ihre regulären Ausdrücke korrekt sind und das gewünschte Verhalten haben. Das Erstellen und Verwenden von regulären Ausdrücken kann komplex sein.
  • Performance: Bei sehr großen Dateien kann das Lesen der gesamten Datei in den Speicher problematisch sein. Für sehr große Dateien sollten Sie möglicherweise Techniken wie “streaming” verwenden, um die Datei zeilenweise oder in Blöcken zu verarbeiten.
  • Reguläre Ausdrucks-Flags: Sie können Flags wie g (global) an Ihre reguläre Expression übergeben, um sicherzustellen, dass alle Vorkommnisse gefunden und ersetzt werden, und nicht nur das erste.
  • Sicherheitsaspekte: Seien Sie vorsichtig bei der Verwendung von regulären Ausdrücken, insbesondere wenn Benutzereingaben in den regulären Ausdruck einbezogen werden. Dies kann zu Sicherheitslücken (z. B. Regex Denial of Service, ReDoS) führen.
  • Komplexere Ersetzungen: Die Ersetzung ist sehr einfach. In realen Szenarien benötigen Sie möglicherweise eine komplexere Logik, um die Ersetzung durchzuführen (z. B. basierend auf dem Inhalt der Fundstelle oder anderen Faktoren).
  • Testen: Testen Sie Ihre Funktion gründlich mit verschiedenen Eingaben, um sicherzustellen, dass sie wie erwartet funktioniert.

Dieses Beispiel bietet eine solide Grundlage. Sie können es an Ihre spezifischen Anforderungen anpassen.

> danke

Gern geschehen! Wenn du noch Fragen hast oder weitere Hilfe benötigst, melde dich einfach. Viel Erfolg bei deinem Projekt!

> /bye

28.5.2025 - LLM

Ich wollte hier einen Artikel über KI bzw. LLMs schreiben, insbesondere solche, die man ohne Datenschutzbedenken in der eigenen Umgebung laufen lassen kann. Dann habe ich mich gefragt, wieso ich das selber schreiben soll, wo ich doch einen Experten auf meinem PC installiert habe. Also soll er zeigen, was er kann:

ollama run gemma3:12b

> Schreibe bitte einen Artikel, ca. 1000 - 1500 Wörter, gerichtet an ein technikaffines Publikum, darüber, was ein LLM ist und was man damit machen kann.

Absolut! Hier ist ein Artikel, der LLMs (Large Language Models) für ein technikaffines Publikum erklärt und die vielfältigen Anwendungsmöglichkeiten aufzeigt:

Large Language Models (LLMs): Die Revolution der Künstlichen Intelligenz – Was Sie wissen müssen

Die Welt der Künstlichen Intelligenz (KI) erlebt derzeit eine rasante Entwicklung, und im Zentrum dieser Transformation stehen Large Language Models (LLMs). Von ChatGPT über Bard bis hin zu Open-Source-Alternativen wie Llama – diese Modelle haben nicht nur die Schlagzeilen erobert, sondern auch das Potenzial, die Art und Weise, wie wir mit Technologie interagieren, grundlegend zu verändern. Aber was sind LLMs eigentlich, wie funktionieren sie und was können sie leisten? Dieser Artikel taucht tief in die Materie ein und richtet sich an ein Publikum mit technischem Hintergrund.

Was sind Large Language Models (LLMs)?

Im Kern sind LLMs neuronale Netzwerke, die auf riesigen Mengen an Textdaten trainiert wurden. Diese Daten umfassen Bücher, Artikel, Websites, Code – im Wesentlichen alles, was in digitaler Form existiert. Das Ziel des Trainings ist es, die statistischen Beziehungen zwischen Wörtern und Phrasen zu erlernen, um die Wahrscheinlichkeit des nächsten Wortes in einer Sequenz vorherzusagen.

Die Architektur: Transformer und darüber hinaus

Die meisten modernen LLMs basieren auf der Transformer-Architektur, die 2017 von Google vorgestellt wurde. Transformer-Modelle zeichnen sich durch ihre Fähigkeit aus, die Beziehungen zwischen Wörtern in einem Satz unabhängig von ihrer Position zueinander zu erfassen. Dies wird durch den “Attention”-Mechanismus ermöglicht, der dem Modell hilft, sich auf die relevantesten Wörter zu konzentrieren, um den Kontext besser zu verstehen.

  • Attention Mechanismus: Stellt sicher, dass das Modell erkennt, welche Wörter im Satz am wichtigsten sind, um die Bedeutung zu verstehen.
  • Self-Attention: Erlaubt dem Modell, die Beziehungen zwischen den Wörtern innerhalb einer einzelnen Eingabesequenz zu gewichten.
  • Encoder-Decoder Struktur: Einige Modelle verwenden eine Encoder-Decoder-Struktur, bei der der Encoder die Eingabe verarbeitet und der Decoder die Ausgabe generiert.

Skalierung und Emergent Abilities

Ein Schlüsselfaktor für den Durchbruch von LLMs ist die Skalierung. Mit zunehmender Anzahl von Parametern (die Gewichte im neuronalen Netzwerk) und der Trainingsdatengröße zeigen LLMs überraschende “Emergent Abilities” – Fähigkeiten, die nicht explizit programmiert wurden, sondern spontan entstehen. Dazu gehören:

  • Few-Shot Learning: Die Fähigkeit, Aufgaben mit nur wenigen Beispielen zu lösen.
  • Zero-Shot Learning: Die Fähigkeit, Aufgaben zu lösen, für die keine spezifischen Trainingsbeispiele vorliegen.
  • Kontextuelles Verständnis: Die Fähigkeit, den Kontext einer Anfrage zu erfassen und entsprechende Antworten zu generieren.

Wie funktionieren LLMs im Detail?

  1. Tokenisierung: Der Eingabetext wird in “Tokens” zerlegt – das können einzelne Wörter, Wortteile oder sogar Satzzeichen sein.
  2. Embedding: Jedem Token wird ein numerischer Vektor zugeordnet, der seine semantische Bedeutung repräsentiert.
  3. Neuronale Verarbeitung: Die Token-Embeddings durchlaufen die neuronalen Schichten des Modells, wobei das Transformer-Netzwerk die Beziehungen zwischen den Token verarbeitet.
  4. Vorhersage: Das Modell prognostiziert die Wahrscheinlichkeit des nächsten Tokens in der Sequenz.
  5. Generierung: Das Modell wählt das wahrscheinlichste Token aus und fügt es zur generierten Sequenz hinzu. Dieser Prozess wird iterativ wiederholt, bis das Modell ein Stoppzeichen generiert oder eine maximale Länge erreicht ist.

Anwendungsbereiche von LLMs: Eine Übersicht

Die Anwendungsbereiche von LLMs sind vielfältig und erweitern sich ständig. Hier sind einige Beispiele:

  • Textgenerierung: Schreiben von Artikeln, Blogposts, E-Mails, Gedichten, Drehbüchern.
  • Chatbots und virtuelle Assistenten: Entwicklung intelligenterer und natürlichsprachlicherer Dialogsysteme.
  • Code-Generierung: Automatisierung der Softwareentwicklung durch Generierung von Code-Snippets oder sogar vollständiger Programme.
  • Sprachübersetzung: Verbesserung der Genauigkeit und Flüssigkeit von maschinellen Übersetzungen.
  • Sentimentanalyse: Erkennung von Meinungen und Emotionen in Texten.
  • Frage-Antwort-Systeme: Entwicklung von Systemen, die komplexe Fragen in natürlicher Sprache beantworten können.
  • Zusammenfassung: Automatisches Erstellen von Zusammenfassungen langer Dokumente.
  • Content Moderation: Identifizierung und Filterung von schädlichen oder unangemessenen Inhalten.
  • Personalisierung: Anpassung von Inhalten und Empfehlungen basierend auf den Vorlieben des Benutzers.
  • Forschung: Analyse großer Mengen an Textdaten zur Gewinnung neuer Erkenntnisse.

Herausforderungen und Limitationen

Trotz ihrer beeindruckenden Fähigkeiten haben LLMs auch einige Herausforderungen und Limitationen:

  • Bias: LLMs können Vorurteile aus den Trainingsdaten übernehmen und in ihren Ausgaben widerspiegeln.
  • Halluzinationen: LLMs können manchmal falsche oder erfundene Informationen generieren, die als “Halluzinationen” bezeichnet werden.
  • Mangelndes Weltwissen: LLMs haben kein echtes Verständnis der Welt und können daher manchmal unlogische oder unsinnige Antworten geben.
  • Rechenintensive Anforderungen: Das Training und der Betrieb von LLMs erfordern erhebliche Rechenressourcen.
  • Ethische Bedenken: Missbrauchspotenzial für die Verbreitung von Falschinformationen, Identitätsdiebstahl oder andere betrügerische Aktivitäten.
  • Sicherheit: Anfälligkeit für “Prompt Injection” – Angriffe, bei denen bösartiger Code in Eingabeaufforderungen versteckt wird, um das Modell zu manipulieren.

Die Zukunft der LLMs

Die Entwicklung von LLMs steht noch am Anfang. Zukünftige Trends könnten beinhalten:

  • Multimodale Modelle: Integration von Text mit anderen Modalitäten wie Bildern, Audio und Video.
  • Verbessertes Kontextverständnis: Fähigkeit, längere und komplexere Kontexte zu verarbeiten.
  • Kontrollierbarkeit: Entwicklung von Techniken, um die Ausgabe von LLMs besser zu steuern und zu lenken.
  • Effizientere Architekturen: Entwicklung von Modellen, die mit weniger Rechenressourcen trainiert und betrieben werden können.
  • Dezentrale LLMs: Ermöglichung von Training und Betrieb von LLMs auf verteilten Netzwerken.

Fazit

Large Language Models sind eine bahnbrechende Technologie, die das Potenzial hat, viele Bereiche unseres Lebens zu verändern. Obwohl es noch Herausforderungen zu bewältigen gibt, sind die Möglichkeiten, die diese Modelle bieten, enorm. Für ein technikaffines Publikum ist es entscheidend, die Funktionsweise, die Anwendungen und die Limitationen von LLMs zu verstehen, um die Chancen und Risiken, die mit dieser Technologie einhergehen, einschätzen zu können. Die Reise der LLMs hat gerade erst begonnen und verspricht eine spannende Zukunft.

20.5.2025 - Der eigene Mailserver

Ein eigener Mailserver ist meistens keine gute Idee: Man ist dann der Spamflut und permanenten Angriffen direkt ausgesetzt und wird ausserdem von professionellen Mailservern, mit denen man kommunizieren muss, um Mails auszutauschen, misstrauisch beäugt und oft abgelehnt. Fast immer ist es somit besser, man nutzt für Mails entweder den Internet-Provider, oder den Anbieter der Website, oder einen Maildienst wie gmail, gmx oder proton.

Wenn man allerdings seine Webseiten selbst gehostet hat und für Mailadressen den Namen einer eigenen Domain verwenden möchte, dann geht das nicht mehr mit jedem Provider. Und wenn man noch dazu etwa grossen Platzbedarf für seine Mails braucht, dann kann es auch schnell teuer werden.

Aber wir haben ja sowieso einen Server für unsere Websites aufgesetzt, dann kann der sich ja auch gleich um alle Mails der Domains kümmern, die er hostet.

Zuerst ein kleiner Exkurs: E-Mails sollen jederzeit versendet werden können, nicht nur, wenn der Empfänger online ist. Sie werden deshalb üblicherweise nicht direkt an den Empfänger gesendet, sondern an dessen Mail-Provider. Dieser ist es also, dem wir Mails senden müssen, und der kümmert sich dann darum, dass jede Mail vom richtigen Empfänger abgeholt werden kann.

Dazu einige Begriffe:

  • SMTP (Simple Mail Transfer Protocol): Das ist genau das. Ein Standard, fast so alt wie das Internet selbst, der es ermöglicht, Mails zu versenden. Die Schöpfer des Standards haben allerdings weder an Spammer noch an Spione noch an Malware noch an Betrüger gedacht, sondern an eine überschaubare Anzahl von Anwendern, die einander kennen. Daher hat SMTP keinerlei Sicherheitselemente. Jeder kann jedem jede beliebige Mail senden. Und das wurde von Spammern und Malware-Versendern weidlich ausgenützt. Es gab viele Ideen, SMTP sicherer zu machen, aber die meisten wurden nicht realisiert, da man rückwärtskompatibel bleiben wollte. Somit griffen die Provider zunehmend zur Selbsthilfe: Sie weisen jede Mail ab, die von einem Sender stammt, dem sie nicht vertrauen. Dieses Vertrauen kann man sich erwerben, indem man entweder zu einem grossen Provider gehört, oder indem man verschiedene Sicherheitsmechanismen umsetzt, die wir weiter unten zeigen. Dass all diese Massnahmen die Spam-Flut aber trotzdem nicht wirklich eindämmen können, merken wir jeden Tag.

  • POP3 (Post Office Protocol Version 3): Eine Methode, um Mails vom Provider auf den eigenen Computer herunterzuladen. Dies geschieht idR passwortgesichert und meist auch verschlüsselt. Die Mails werden dabei auf dem Server des Providers gelöäscht, sobald man sie heruntergeladen hat.

  • IMAP (Internet Message Access Protocol): Doent dazu, Mails zu lesen und zu bearbeiten, ohne sie zwingend herunterzuladen. Die Mails bleiben auf dem Server des Providers gespeichert, bis man sie explizit löscht.

  • Verbindungssicherheit: Wie die Verbindung vom Client (IMAP oder POP3) zum Server verschlüsselt wird. Gar nicht, SSL/TLS oder StartTLS. Letzteres ist eine Kombination aus den ersten beiden: Die Verbindung wird zuerst unverschlüsselt aufgebaut, und dann, wenn beide Seiten einverstanden sind, auf TLS verbessert. Achtung: Verschlüsselt heisst nur, dass der Dastenverkehr zwischen Provider und Empfänger verschlüsselt stattfindet. Zwischen dem Absender und dem Provider des Empfängers laufen Mails idR unverschlüsselt.

  • Authentisierung: Hat trotz des ähnlichen Zwecks nichts mit der Verbindungssicherheit zu tun, sondern beschreibt, wie der Client sich gegenüber dem Server ausweist. Normales Passwort, verschlüsseltes Passwort oder eine indirekrte Lösung (Kerberos, OAuth etc.). Wenn die Verbinsung verschlüsselt ist, genügt Normales Passwort. Wenn die Verbindung unverschlüsselt ist, sollte das Passwort verschlüsselt übertragen werden..

Komplettlösung

Die m.E. einfachste Lösung, ein eigenes Mailsystem aufzusetzen, ist mailcow:dockerized, eine Sammlung von Docker-Containern, die alle benötigte Software unter einer brauchbaren Oberfläche vereinigt.

Ein wesentlicher Teil der Konfiguration muss allerdings am Name-Server erfolgen. Das ist die Stelle, die Anfragen nach ihre-url.com auf Ihre IP-Adresse übersetzt. Häufig ist das Ihr Webspace-Provider, aber Sie können beim Domain-Registrar im Prinzip auch jeden anderen Server angeben, der die Aufgaben eines Nameservers übernehmen kann. Ich verwende gern die Dienste von ZoneEdit. Für die Mailzustellung muss man den MX-Record des Domain-Eintrags auf den zuständigen Mailserver legen.

Sicherheit

Wie eingangs bereits geschrieben, gibt es Bestrebungen, den Mailverkehr besser gegen Spam und Malware zu sichern. Diese Bestrebungen erschweren unglücklicherweise der Betrieb eines eigenen Postausgangsservers (der Posteingangsserver, egal ob POP3 oder IMAP, ist hingegen kein Problem).

Dazu nochmal ein Exkurs: Wie funktioniert das Senden einer Mail?

Wenn sie in Ihrem Mailprogramm auf “senden” klicken, dann nimmt das Mailprogramm mit dem in den Einstellungen festgelegten Postausgangsserver auf. Es identifiziert sich dafür meist mit einem Benutzernamen und Passwort (oder es hat sich, beim einige Zeit üblichen SMTP-after-POP-Konzept kurz zuvor mit einer POP-Session identifiziert). Dieser Postausgangsserver wird die Mail also üblicherweise problemlos entgegennehmen, sofern die “Personalien” stimmen. Knifflig wird der nächste Schritt: Der Postausgangsserver muss mit dem Posteingangsserver des Empfängers Kontakt aufnehmen, und diesem die Mail übergeben. Das kann möglicherweise über mehrere Zwischenstationen erfolgen, aber das änfert nichts am Konzept. Der Posteingangsserver wird die Mail oft nur dann entgegennehmen, wenn er den Sender für vertrauenswürdig hält, um seine User vor Spam und Malware zu schützen. Die Provider sind in der Umsetzung dieser Politik unterschiedlich streng. Wenn Sie einen eigenen Postausgangsserver betreiben, dann kann es durchaus sein, dass manche Epmfänger Ihre Mails akzeptieren, und andere genau dieselben Mails abweisen. Ein Beispiel für ein besonders strenges System ist Googles Gmail. Es ist recht schwierig, Gmail dazu zu bewegen, Mails von einem ihm unbekannten System entgegenzunehmen, insbesondere, wenn dieses System keine fixe IP hat.

Hier zwei häufig gebrauchte Sicherheitsmechanismen:

DKIM: Domain Keys Identified Mail

Hier wird im Nameserver-Eintrag der Domain ein öffentlicher Schlüssel im Feld DKIM abgelegt, der ungefähr so aussehen kann:

DKIM dkim._domainkey-mysite.ch v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQCAQEArpXtxxQCVMaR+X/htM0NyG5a83N7ay+Ru6B7MQmqtBX7GD6dUejkO4aasa+T8W19WRNk3zAcHciV3KnAbAL9ZkX/7BJctY2HE29kRTH+grUjU1RtMb3Ay10xaAYHEulN7TTrAmwtsI08sRituFaL4YVpCLSd+T71L57atrX9OisFJTG5TJuBbg92rThEgcFfr6pWxSVULfk3WVJILq+QQgRjvl8HhQXfcp/ynQc9Zcos7v0kKa7f87d0PcQYbnF7RbgPF8dDE4YQIDAQAB

Der Mailserver hat den dazu passenden privaten Schlüssel und signiert jede Mail damit. Auf diese Weise kann der Eingangsserver des Empfängers der Mail die Signatur mit dem öffentlichen Schlüssel prüfen, und so dafür garantieren, dass die Mail tatsächlich von der Domain kommt, von der sie zu kommen scheint. Allerdings hilft das nicht zuverlässig gegen gefälschte “von”-Felder in der Mail selber, sondern nur gegen gefälschte Absender im “envelope” der Mail. Darum prüfen manche Empfänger auch, ob “von” veld und “envelope-sender” identisch sind.

SPF: Sender Policy Framework

Auch das ist ein Eintrag im Nameserver der Domain, diesmal in einem TXT-Feld, das zum Beispiel so aussehen kann:

TXT @-mysite.ch v=spf1 a mx include:smtp.myhoster.mail ~all

Dieser Eintrag beschreibt, welche Mailserver überhaupt autorisiert sind, Mails für diese Domain zu senden. Damit kann man verhindern, dass ein Bösewicht einen eigenen Mailserver verwendet, um Fake-Accounts zu erstellen, die genauso aussehen, wie echte Mailadressen von echten Gegenübern. Leider ist dieser Eintrag meist der k.o. für Mailserver, die keine fixe IP haben. Viele Provider lehnen solche Mailserver nit einer IP aus dem Endkunden-bereich direkt ab.

Sie können beide Funktionen mit einem mailcow-basierten Server nutzen, aber wie gesagt wird Ihnen das möglicherweise nicht viel helfen, wenn Sie keine fixe IP haben.

Lösungen:

  • Sie mieten einen fertigen Mailserver bei einem entsprechenden Dienst.

  • Sie mieten einen Webspace mit fixer IP für Ihren Mailserver. Allerdings ist damit noch nicht sichergestellt, dass alle möglichen Empfänger-Server Ihren Nailer für vertrauenswürdig genug halten.

  • Sie verwenden Ihren eigenen Maiserver nur als Posteingangsserver und senden Mails z.B. über den SMPT-Server Ihres Internet-Providers. Das kann man ja im Mailprogramm beliebig konfigurieren.

18.5.2025 - SSH

Die Secure Shell (SSH) ist eine bewährte Möglichkeit, auf entfernte Computer zuzugreifen. Man kann konfigurieren, ob der Zugriff mit name/passwort, und/oder mit einem public/private Schlüsselpaar erfolgen darf.

Server Konfiguration

Auf Linux-Computern ist der SSH Server häufig bereits installiert (Überprüfen mit sudo systemctl status ssh) Wenn nicht, kann man ihn mit sudo apt install openssh-server installieren.

Die Konfiguration findet sich in /etc/ssh/sshd_config und allfälligen zusätzlichen Dateien in /etc/ssh/sshd_config.d/

Jede Zeile dort ist eine Einstellung. Zeilen, die mit # anfangen, sind inaktiv, respektive auf den Standardwert gesetzt, der hinter dem # steht.

Von den vielen Einstellungen dort, sind in der Praxis nur wenige relevant:

    port 22

Wenn Ihr Computer direkt übers Internet erreichbar ist (was normalerweise aber eh nicht der Fall sein sollte), empfiehlt es sich, da eine andere Nummer einzutragen, zum Beispiel 36542 (Sie können jede Zahl zwischen 1025 und 65534 nehmen, aber einige sind schon für bestimmte Sienste reserviert). Der Grund ist, dass sehr viele automatisierte Attacken auf Port 22 erfolgen, und wenn der Robot merkt, dass an Port 22 tatsächlich Anfragen entgegengenommen werden, wird er seine Bemühungen verstärken, dort durchzukommen. Wenn Sie den SSH server gut konfiguriert haben, wird ihm das zwar nicht gelingen, aber die Abwehr der Angriffe wird Ihren Computer Rechenzeit und Ihren Internet-Anschluss Bandbreite kosten.

    PermitRootLogin no

Es empfiehlt sich, keinen Fernzugriff als Systemadministrator zu erlauben. Wenn Sie soch etwas administrieren müssen, können Sie sich als ein User mit sudo-Rechten einloggen und dann via sudo Admin-Rechte erlangen. Das ist eine zusätzliche Hürde.

    PasswordAuthentication yes

Wir benötigen das, um den Zugriff per Schlüsselpaar einzurichten. Danach sollteman es auf “no” setzen, um nur noch die Identifikation über Schlüssel zuzulassen

Alles Andere können Sie auf standard lassen. Schauen Sie aber noch ins Verzeichnis /etc/ssh/sshd_config.d/ und prüfen Sie auch die Dateien dort, wenn vorhanden. Die können nämlich die Einstellungen in der Hauptkonfiguration überschreiben.

Falls Sie etwas geändert haben, geben Sie anschliessend ein: sudo systemctl restart ssh, um die neuen Einstellungen zu laden.

Client Konfiguration

Der client braucht normalerweise für einfache Verbindungen keine Konfiguration. Das Programm ssh ist auf Linux und Mac computern bereits installiert, auf Windows 11 ebenfalls. Bei älteren Windows-Versionen können Sie sich mit putty.exe behelfen.

Die Verbindung stellen Sie einfach mit ssh servernameher. Der SSH Client wird dann versuchen, Sie auf dem Server mit demselben Benutzernamen einzuloggen, denn Sie auf dem clienht-Computer haben. Wenn das nicht der Fall ist, können Sie mit ssh user@servernamefestlegen, als welcher Benutzer Sie sich einloggen wollen.

Nach eingabe des Passworts sind Sie auf einem Terminal des entfernten Computers eingeloggt, als wären Sie direkt vcor dem Bildschirm. Allerdings ohne grafische Oberfläche.

Schlüssel erstellen

Wenn die Verbindung auf diese Weise gekungen ist, sollten Sie als nächstes ein Schlüsselpaar erstellen. Dadurch wird die Verbindung sicherer und komfortabler.

    ssh-keygen -o -a 100 -t ed25519

Geben Sie am besten einen eindeutigen Dateinamen ein. Ich wähle hier ~/.ssh/serverkey als Bsispiel. Die Passphrase kann die Sicherheit erhöhen, aber Sie müssen sie dann jedesmal eingeben, Sie können auch einfach die Eingabetaste drücken, dann wird der Schlüssel ohne passphrase erstellt.

Sie erhalten zwei Dateien, in meinem Beispiel serverkey und serverkey.pub, beide im (versteckten) Verzeichnis .ssh in Ihrem Benutzerverzeichnis.

Nun müssen wir dem Server bekannt geben, dass dies der richtige Schlüssel ist. Dazu geben wir ihmd en öffentlichen Schöüssel (Der private Schlüssel sollte den Computer niemals verlassen, auf dem er erstellt wurde).

Auch diese Bekanntgabe kann man automatisieren:

    ssh-copy-id -i ~/.ssh/serverkey.pub user@servername

Sie werden noch einmal nach Ihrem Passwort gefragt, und dann wird mit diesem Befehl der öffentliche Schlüssel in der Datei .ssh/authorized_keys des genanten users gespeichert.

Testen Sie, ob es geklappt hat:

    ssh -i ~/.ssh/serverkey servername

Das Login sollte jetzt ohne Passwortabfrage erfolgen (Ausser, wenn Sie eine Passphrase für den Schlüssel angegeben haben, dann müssen Sie diese eingeben).

Wenn alles geklappt hat, können Sie auf dem Server die Datei /etc/ssh/sshd_config nochmal öffnen und die Zeile PasswordAuthenticationauf “no” stellen. Danach die neue Einstellung mit systemctl restart ssh aktivieren.

Von nun an können Sie nur moch mit dem eben erstellten Schlüssel auf den Server zugreifen. Falls es sich um einen Server handelt, auf den Sie keinen physischem Zugriff haben, weil es zum Beispiel ein gemieteter virtueller Server ist, dann tun Sie gut daran, einen zweiten Benutzer mit Adminrechten zu erstellen, und auch diesem ein SSH-Schlüsselpaar zuzuteolen, damit Sie nicht ausgesperrt bleiben, wenn Sie als Hauptbenutzer etwas falsch machen.

Konfigurationsdatei

Der ssh-Befehl hat voele mögliche Optionen, die sie zum Beispiel mit man ssh oder auf der entsprechenden Website nachlesen können. Da es schwierig ist, sich das zu merken, falls Sie mehrere Optionen benötigen oder merhere Server eibgerichtet haben, können Sie Ihre Einstellungen in einer Konfigurationsdatei eintragen. Erstellen Sie dazu die Datei ~/.ssh/config.

Dort können Sie für jeden Server einen eigenen Eintrag erstellen. Beispiel:

Host mycloud
        HostName cloud.myfamily.somewhere
        User snoopy
        Port 28652
        # Solr
        LocalForward 48983 127.0.0.1:8983
        # Couchdb 
        LocalForward 45984 127.0.0.1:5984
        # Syncthing
        LocalForward 48384 127.0.0.1:8384
        # Minio
        LocalForward 49000 127.0.0.1:9000
        IdentityFile /home/icke/.ssh/cloudkey

Host homeserver
        HostName 192.168.0.63
        User icke
        IdentityFile /home/icke/.ssh/homeserver

Dann können Sie fortan die Verbindung mit einem simplen ssh mycloud herstellen. Und das gilt auch für andere Dienste, die ssh indirekt nutzen. Beispielsweise können Sie mit rsync -av --delete mycloud:/home/pi /srv/backup/ ein Verzeichnis Ihres Heimservers via SSH sichern. Denken Sie aber daran, dass Sie auf dem entfernten Server immer mit den Rechten des Users unterwegs sind, als der Sie sich eingeloggt haben.Sie werden also z.B. so nicht aufs /root Verzeichnis zugreifen können.