opendkim: kleine Scripte, dass das Leben leichter macht

kuerbis42

New Member
Moin zusammen. Ich bin zwar neu hier, aber habe schon die eine oder andere Hilfe "abgezogen". Zeit sich zu revanchieren...

Ich stelle Euch hier zwei Scripts zur Verfügung, durch die sich die Erstellung der Schlüssel und DNS-Einträge für opendkim vereinfachen.
Das erste Script ist dadurch enstanden, das opendkim-genkey die Schlüssel- und DNS.txt-Datei immer unter dem Namen des Selektors speichert. Ärgerlich, wenn man mehrere Domains hat, dann muss man ständig umbenennen, etc.
Das zweite Script ist entstanden, weil es beim Kopieren der DNS-Einträge (gerade in PuTTY und nano) immer schnell zu Fehlern kommt, weil nano bei zu langen Zeilen ein $ zeigt.
Und zu guter Letzt: macht man es nicht so oft, dann vergisst man alles wieder....

Also, hier die dokumentierten Scripte, ggf. müsst Ihr etwas anpassen, aber die standart Pfade sind /etc/opendkim und /etc/opendkim/keys
Und natürlich könnt Ihr den Selektor ändern (hier s1), dann muss aber das zweite Script ggf. auch angepasst werden

Code:
    #!/bin/bash

    # ueberpruefen, ob der erforderliche Parameter uebergeben wurde
    if [ -z "$1" ]; then
      echo "Bitte geben Sie den vollstaendigen Domainnamen (z.B. einetolledomain.com) als ersten Parameter an."
      echo "Bsp.: keygen.sh einetolledomain.de"
      echo "--------------------------"
      echo "Es werden durch opendkim-genkey eine Schluessel- und eine DNS-Datei erzeugt, ausserdem werden"
      echo "die Dateien in DOMAIN.private (Schluessel) und DOMAIN.txt (DNS) umbenannt."
      echo "Wird als 2. Parameter true angegeben, dann wird zum Namen auch die TLD Endung im Namen  uebernommen."
      echo "Bsp: keygen.sh international.de true   >> DOMAIN-TLD.private und DOMAIN-TLD.txt >> international-de.private,international-de.txt"
      echo ""
      echo "Anschliessend muessen noch die Dateien key.table, signing.table und trusted bearbeitet werden. openDKIM muss neu gestartet werden!"
      exit 1
    fi

    # ueberpruefen, ob der zweite Parameter gesetzt ist. Wenn nicht, die TLD nicht anhaengen.
    if [ -z "$2" ]; then
      append_tld=false
    else
      append_tld=true
    fi

    full_domain="$1"

    # Extrahieren der TLD
    tld=$(echo "$full_domain" | rev | cut -d '.' -f 1 | rev)

    # Extrahieren des Domaenennamens ohne die TLD
    domain=$(echo "$full_domain" | cut -d '.' -f 1)

    # Erstellen der DKIM-Schluessel
    opendkim-genkey -b 2048 -d "$full_domain" -D /etc/opendkim/keys -s s1 -v

    # Umbenennen der erzeugten Dateien
    cd /etc/opendkim/keys
    if [ "$append_tld" = true ]; then
      mv s1.private "$domain-$tld.private"
      mv s1.txt "$domain-$tld.txt"
    else
      mv s1.private "$domain.private"
      mv s1.txt "$domain.txt"
    fi

    # aendern der Dateiberechtigungen
    chown opendkim:opendkim -R "$domain"*
    cd /etc/opendkim

    echo "DKIM-Schluessel fuer die Domain $full_domain wurde erstellt."
    echo "gespeicher als:"

    if [ "$append_tld" = true ]; then
      echo "$domain-$tld.private"
      echo "$domain-$tld.txt"
    else
      echo  "$domain.private"
      echo "$domain.txt"
    fi

    #Ergaenzend dazu wird jetzt mit dem Script oneline.sh die Datei Copy+Paste faehig einzeilig erzeugt und in $domain.txt.oneline geschrieben. Danach angezeigt
    ./oneline.sh "/etc/opendkim/keys/$domain.txt"
zweites Script
Code:
    #!/bin/bash
    # Dateiname der Eingabedatei
    input_file="$1"
    # Ausgabedatei
    output_file="$1"
    # Eingabedatei komplett einlesen, Zeilenumbrueche entfernen und Teile zwischen ( und ) extrahieren
    input_content=$(cat "$input_file" | tr -d '\n' | grep -oE '\(.*\)')
 
    # Domainnamen extrahieren
    domain_name=$(awk '/DKIM key s1 for/ {print $NF}' "$input_file")

    # DKIM-Inhalt extrahieren
    dkim_info=$(sed 's/^[^(]*//' <<< "$input_content")

    # Leerzeichen, ( , )  und Anfuehrungszeichen aus DKIM-Inhalt entfernen
    dkim_info_cleaned=$(tr -d '[:space:]()"' <<< "$dkim_info")

    # Ausgabe in die Ausgabedatei schreiben
    echo "s1._domainkey.$domain_name" > "$output_file.oneline"
    echo "$dkim_info_cleaned" >> "$output_file.oneline"

    echo "Die Ausgabe wurde in $output_file gespeichert."
    echo ""

    # Darstellung zum direkten Copy+Paste
    cat "$output_file.oneline"

Ich habe die beiden Scripte direkt im Verzeichnis /etc/opendkim plaziert - nicht vergessen, die Dateien ausführbar machen, und die anderen Tabellen von DKIM zu pflegen.
Viel Spaß und Erfolg. Kuerbis42
 
Last edited:
Eine kleine Empfehlung:
überprüfe immer ob das "cd" funktioniert hat, könnte ja sein dass der Ordner nicht existert.
Die Kombi aus " cd /etc/opendkim/keys" und "chown opendkimpendkim -R "$domain"*" kann bei fehlendem Keys Unterordner dafür sorgen dass der Home des Users oder Im Zweifelsfall Das Rootverzeichnis rekursiv chownd wird. Resultat ist dann leider gerne mal ein DRP-Test des Backups.
Mit "cd /meinorder || exit 1" (oder besser, Aufruf einer "err" Funktion mit sinnvoller Ausgabe) verhindert man dieses Risiko.
 
Moin d4f,
ja, Du hast recht, da ist das Script verbessungsfähig.
Aber dann könnte man es noch besser so machen:
Code:
  # Umbenennen der erzeugten Dateien
 
    if [ "$append_tld" = true ]; then
      mv /etc/opendkim/keys/s1.private "/etc/opendkim/keys/$domain-$tld.private"
      mv /etc/opendkim/keys/s1.txt "/etc/opendkim/keys/$domain-$tld.txt"
    else
      mv /etc/opendkim/keys/s1.private "/etc/opendkim/keys/$domain.private"
      mv /etc/opendkim/keys/s1.txt "/etc/opendkim/keys/$domain.txt"
    fi

    # aendern der Dateiberechtigungen
    chown opendkim opendkim -R "/etc/opendkim/keys/$domain"*

Wenn das umbenennen nicht funktioniert hat, dann gibt es auch nichts für chown.

Oder? (ggf noch die Pfade als Variable parameterisieren, aber es soll ja nur ein kleiner Helfer sein, kein ausgewchsenes Program ;-)
 
Code:
    # aendern der Dateiberechtigungen
    chown opendkim opendkim -R "/etc/opendkim/keys/$domain"*
Bist du sicher, daß er das ohne den ":" zwischen Owner und Group frißt...?
Ich bin mir da jetzt nicht sicher, ob es mit Leerzeichen geht...
Ich würde es so schreiben:
Code:
    # aendern der Dateiberechtigungen
    chown opendkim:opendkim -R "/etc/opendkim/keys/$domain"*

Edit:
Habs gerade mal getestet. Bei mir ging es nicht mit Leerzeichen:
Code:
root@host:~# mkdir test
root@host:~# cd test
root@host:~/test# touch test.txt
root@host:~/test# ls -l
insgesamt 8
-rw-r--r-- 1 root root    0  5. Nov 21:26 test.txt
root@host:~/test# useradd test
root@host:~/test# chown test:test "test.txt"
root@host:~/test# ls -l
insgesamt 8
-rw-r--r-- 1 test test    0  5. Nov 21:26 test.txt
root@host:~/test# chown root root "test.txt"
chown: Zugriff auf 'root' nicht möglich: Datei oder Verzeichnis nicht gefunden
 
Last edited:
Habs gerade mal getestet. Bei mir ging es nicht mit Leerzeichen:
Stimmt. Im ersten Script ist (war) aber ein ganz anderer Fehler (der jetzt nicht mehr zu sehen ist?!?!):
Code:
chown opendkimpendkim -R "$domain"*
Also die Zeichen : und o waren ganz weg. Und so geht es auf keinen Fall.
Useless use of cat
Useless use of echo
Domain ohne TLD macht im Zusammenhang mit DKIM absolut gar keinen Sinn, aka überflüssiger Code.
Das CAT habe ich erklärt, denn in nano wird, wenn die Anzeige nicht breit genug ist, am Ende der Zeile mittels $ angezeigt, dass noch etwas kommt (siehe auch unten).
Durch CAT ist das Copy&Paste einfacher und weniger fehleranfällig - aber jeder kann es ja machen wie er will.
Domain ohne TLD macht im Zusammenhang mit DKIM absolut gar keinen Sinn, aka überflüssiger Code.
Nein, stimmt nur indirekt. Natürlich kann man alles immer mit TLD machen, hat nur auf DKIM hier überhaupt keinen Einfluß.
An dieser Stelle geht es ja nur darum, für DKIM, bzw. opendkim die Schlüsseldateien und den DNS-Eintrag "bereit zu stellen" - opendkim-geygen ist ja nur so gesprächig, dass es die Datei mit dem Namen des Selektors speichert, nach Deiner Aussage würde das ja gar keinen Sinn machen, weil ja nicht einmal die Domain drin vorkommt.
Aber: jeder kann es ja machen wie er will.

Es ist ja auch nur eine Möglichkeit, sich das Leben einfacher zu machen, wahrscheinlich geht es sogar als Einzeiler, aber den Anspruch habe ich nicht.

Und zu
Wenn ich das/die Scripte richtig verstehe, dann muss ich dort eben alle example.com durch meine jew. domain.tld ersetzen.... nicht wirklich übersichtlich.
Und die letzte Ausgabe dort:
Code:
#
# The output should look similar to this one, which will be the DNS-Record to publish
#
# Note: The folding of the pubkey is necessary as most nameservers have a line-length limit
#       If you use a DNS-Provider to publish your records, then use their free-text fields
#       to insert the record into their form
#
20230520._domainkey.example.com.    IN  TXT    ( "v=DKIM1; h=sha256; k=rsa; s=email; p="
        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Up5Z0TkPpE0mNAc9lf7Uug7P/n28Kk6fXC1V8m93dE+NPgsTKp4k+"
        "t2S3EujANO7J8WyBppE+aTbyQjU5TtaIPC8TS3sBg/6JX/QAw73+Hv03lieutmZ0GO4uuvj+QbOuDqNwHR/DZih3BrV7Mtit4F"
        "bILcz+V1QbJ7YssRQRaZ/LTGZ0Q6QLGr6BG9h3Ro4g1bTirFIuvbaVUuzDK/KxHKRAuAhIB7mmrpPRDQlFjgva9vQYsQUcQtVh"
        "Y/z6YvcGNvEWhme3gaTWzdG20aLTxut4Il17OSWiCbF0wdnUn0bnKins14YeHjkDhOhMoEagd3lWWs0k2KNxnbYljPQwIDAQAB" )
ist nicht C&P kompatibel zu den meisten DNS-Servern.
Kannst ja mal ausprobieren, was passiert, wenn Du von ( bis ) alles markierst, kopierst und in den DNS mit Paste einfügst.

Meine Scripte kann man mit ein paar entsprechenden cat << "EOF" > /data/db/opendkim/keytable, etc. durchaus erweitern, so dass keytable, signingtable, und trustedhosts auch noch automatisch gefüllt werden. Und zum Schluß ein automatisiertes opendkim restart.
Aber ein bisschen will man vllt. auch noch selber machen, zumal ich es schlau finde, sich das immer wieder mal in den Kopf zu werfen, was da eigentlich passiert.
 
Wenn ich das/die Scripte richtig verstehe, dann muss ich dort eben alle example.com durch meine jew. domain.tld ersetzen.... nicht wirklich übersichtlich.
Das ist ja auch kein fertiges Script, sondern mehrere Shell-Zeilen, aus welchen man aber problemlos ein(!) Script basteln kann, welches das Gleiche macht wie Deine zwei Scripte oben, nur halt eleganter und jederzeit flexibel erweiterbar:
Code:
#!/bin/bash

# ueberpruefen, ob die erforderlichen Parameter uebergeben wurden
if [ -z "$1" ]; then
  echo "Bitte geben Sie den vollstaendigen Domainnamen (z.B. einetolledomain.com) als ersten Parameter an."
  echo "Bsp.: keygen.sh einetolledomain.de"
  exit 1
fi
if [ -z "$2" ]; then
  echo "Bitte geben Sie den Selektornamen (z.B. foobar oder 20231105) als zweiten Parameter an."
  echo "Bsp.: keygen.sh einetolledomain.de foobar"
  echo "Bsp.: keygen.sh einetolledomain.de 20231105"
  exit 1
fi

domain="$1"
selektor="$2"

# Erzeugen des Speicherortes
mkdir -p /etc/opendkim/keys/$domain
chown -R opendkim:opendkim /etc/opendkim

# Erstellen der DKIM-Schluessel
opendkim-genkey -v -r -b 2048 -h sha256 -s $selektor -d $domain -D /etc/opendkim/keys/$domain
chmod 0600 /etc/opendkim/keys/*/*.private

# Erstellen der Keytable
cat << "EOF" >> /etc/opendkim/keytable
$selektor._domainkey.$domain    $domain:$selektor:/etc/opendkim/keys/$domain/$selektor.private
"EOF"

# Erstellen der Signingtable
cat << "EOF" >> /etc/opendkim/signingtable
*@$domain      $selektor._domainkey.$domain
*@*.$domain    $selektor._domainkey.$domain
"EOF"

echo ""
echo "DNS-Record zum Copy+Paste (Multiline Version):"
# Multiline
multiline="$(/usr/bin/openssl pkey -pubout -outform pem -in /etc/opendkim/keys/$domain/$selektor.private | \
    awk '\!/^-----/ {printf $0}' | awk 'BEGIN{n=1}\
        {printf "\n$selektor._domainkey.$domain.    IN  TXT    ( \"v=DKIM1; h=sha256; k=rsa; s=email; p=\"";\
            while(substr($0,n,98)){printf "\n        \"" substr($0,n,98) "\"";n+=98};printf " )\n"}')"
echo $multiline
echo $multiline > /etc/opendkim/keys/$domain/$selektor.multiline.txt
echo ""

echo "DNS-Record zum Copy+Paste (Oneline Version):"
# Oneline
oneline="$(/usr/bin/openssl pkey -pubout -outform pem -in /etc/opendkim/keys/$domain/$selektor.private | \
    awk '\!/^-----/ {printf "\n$selektor._domainkey.$domain.    IN  TXT    ( \"v=DKIM1; h=sha256; k=rsa; s=email; p=\"$0\" )\n"}')"
echo $oneline
echo $oneline > /etc/opendkim/keys/$domain/$selektor.oneline.txt
echo ""

# Korrigieren der Dateiberechtigungen
chown -R opendkim:opendkim /etc/opendkim

echo ""
echo "DKIM-Schluessel fuer die Domain $domain wurde erstellt und hier gespeichert:"
echo "/etc/opendkim/keys/$domain"
echo "Auch die Keytable und Signingtable wurden entsprechend angepasst."
echo ""
Disclaimer: Dem Script fehlen noch Inputvalidation und Sicherheitschecks, aber das sind Hausaufgaben für den geneigten Nutzer ;)
Disclaimer 2: Das Script ist nur kurz blind von FreeBSD (tcsh) auf Linux (bash) portiert und mit obigen Scripts gemixt worden und kann daher kleinere Bugs enthalten ;)
 
ist nicht C&P kompatibel zu den meisten DNS-Servern.
Doch ist es, denn es ist RFC-konform.
Nur weil die Weboberfläche Deines Anbieters zu dumm dafür ist, heisst es nicht, dass das auch auf "die meisten" Anderen zutrifft, denn 80% aller von mir getesteten Anbieter schlucken diese Form problemlos, eben aus dem im Kommentar genannten Grund.
 
double use of chown ;)
Code:
chown -R opendkim:opendkim /etc/opendkim

Ja, Dein Script ist sehr elegant, auch die Sache mit versch. Selektoren in den Domain-Ordnern ist gut.
Außerdem scheinst Du regex und awk im Schlaf zu beherrschen - ich leider nicht.

Fazit: solange jmd. daraus einen Nutzen ziehen kann, ist es doch gut - oder?
 
  • Like
Reactions: d4f
Back
Top