Inhaltsverzeichnis

DKIM - Domain Key Identified Mail unter CentOS 7.x

DKIM Logo Zur Sicherstellung der Authentizität von E-Mail-Absendern wurde in 2004 von Yahoo ein Identifikationsprotokoll entwickelt, mit welchem die Authentizität von E-Mail-Absendern sichergestellt werden kann. Dies wurde vor allem mit dem Wunsch zur Eindämmung unerwünschter eMail wie Phishing und/oder Spam konzipiert. Ursprünglich wurde DomainKeys unter dem Titel Domain-Based Email Authentication Using Public Keys Advertised in the DNS (DomainKeys) im RFC 4870 veröffentlicht. Im RFC 4871 wurde dies unter dem Titel DomainKeys Identified Mail (DKIM) Signatures über- und in der aktuellen Version RFC 6376 weitergeführt.

DKIM basiert auf asymmetrischer Verschlüsselung, bei der eMails mit zwei Signaturen versehen werden, die erste über ein paar Header-Zeilen der Nachricht und die zweite über den Mail-Body, also dem Inhalt einer eMail. Die zugehörigen Prüfsummen werden in standardisierten DKIM-Signature-Headern in der eMail eingetragen. Weitere Informationen hierzu findet man im RFC 4871 oder in der Dokumentation von DKIM.org.

Der empfangende Mail-Server ist nun in der Lage, an Hand des öffentlichen Schlüssels diese Daten, der im TXT-Record des Domain Name System (DNS) der Domäne abrufbar ist, die Daten zu verifizieren. Ist diese Signatur gültig, ist der Absendeserver der eMail zweifelsfrei festgestellt. Bei einem negativen Ergebnis hat nun der empfangende MTA1) die Möglichkeit, die Annahme der eMail zu verweigern bzw. die empfangene Nachricht auszusortieren. Wie bereits erwähnt ist dies möglich, da der sendende MTA jede versendete E-Mail im sogenannten „DomainKey-Signature-Header“ mit einer digitalen Signatur des Inhaltes der E-Mail versieht. Der Domaininhaber (Sender) kann mit Hilfe von ADSP2) festlegen, was der Empfänger beim Eingang einer eMail tun soll, sofern die DKIM-Signatur gebrochen wurde. Diese Policy wird, wie der öffentliche DKIM-Schlüssel auch, über den DNS publiziert. Weitere Informationen hierzu findet man im RFC 4871

Installation von AMaVIS

Zur Signierung und Überprüfung der empfangenen Daten nutzen wir bei unserem Mailserver-Postfix die Möglichkeiten von AMaViS. Die Grundinstallation von AMaViS ist im Kapitel Grundinstallation von AMaViS unter CentOS 7.x beschrieben. In unserer Postofficeumgebung nutzen wir den AMaVis-Daemon in der Version amavisd-new-2.9.x. Neben diesem Perl-Programm benötigen wir noch die beiden Pakete perl-Mail-DKIM und perl-Crypt-OpenSSL-RSA welche bei der Installation von amavisd-new automatisch mitinstalliert wurden.

Bei der nachfolgenden Konfigurationsbeschreibung gehen wir davon aus, dass bereits ein funktionierender Postfix-Mailserver wie auch der Viren- und SPAM-Schutz mit Hilfe von AMaViS zur Verfügung steht.

Wertvolle Hinweise zur Konfiguration und Nutzung von DKIM entnimmt man am besten der original AMaViS-Dokumentation Setting up DKIM mail signing and verification.

Überprüfung von DKIM-Signaturen

Damit unsere AMaViS-installation die Überprüfung von DKIM-Signaturen im Mailheader vornimmt bedarf es keiner großen Konfiguration. Wie in der Originaldoku von Marc Martinec zu entnehmen ist, müssen wir lediglich die Variable $enable_dkim_verification setzen, in dem wir ihr den Wert 1 zuweisen. Diese Variable findet sich in der Sektion DKIM - Domain Key Identified Mail wieder.

 # vim /etc/amavisd/amavisd.conf
################################################################################
## DKIM - Domain Key Identified Mail
#
 
# DKIM-Signaturen verifizieren
$enable_dkim_verification = 1;
 
...

Signieren von eMails

Generierung der Schlüssel

Wie Eingangs bereits erwähnt, wird bei den DKIM-Signaturen auf asymmetrischer Verschlüsselung zurück gegriffen. Wir benötigen also ein Schlüsselpaar aus public- und private-key. Bevor wir diese erzeugen, legen wir uns das Zielverzeichnis für unseren privaten Schlüssel an und passen die Berechtigung so an, dass dieses Verzeichnis unserem User amavis „gehört“.

 # mkdir /var/spool/amavisd/dkim
 # chown amavis:amavis /var/spool/amavisd/dkim/

Im nächsten Schritt erstellen wir uns nun unser Schlüsselpaar. Dazu benutzen wir die Option genrsa des Befehls amavisd # amavisd genrsa file_name [nbits].

Beim Dateinamen vermerken wir dabei am einfachsten das Erstellungsdatum YYMMDD (Jahr+Monat+Tag, z.B. 141126 für 26. November 2014). So haben wir es später einfacher, die einzelnen Schlüssel auseinander zu halten, wenn wir mehrere benötigen, oder einzelne Schlüssel für ungültig erklären (revoke'n). Diesen Datums-Stempel verwenden wir dann auch als selector bei der nachfolgenden AMaViS-Konfiguration.

 # amavisd genrsa /var/spool/amavisd/dkim/dkim-key-141126.pem 4096
 Private RSA key successfully written to file "/var/spool/amavisd/dkim/dkim-key-141126.pem" (4096 bits, PEM format)

Alternativ können wir auch openssl zum Erstellen des Schlüssel verwenden.

 # openssl genrsa -out /var/spool/amavisd/dkim/dkim-key-141126.pem 4096
Generating RSA private key, 4096 bit long modulus
........................++
............++
e is 65537 (0x10001)

Haben wir unseren Schlüssel mit Hilfe von openssl erzeugt, passen wir die Dateiberechtigungen und Rechte unseres erstellen Schlüssels an.

 # chmod 600 /var/spool/amavisd/dkim/*
 # chown amavis:amavis /var/spool/amavisd/dkim/*

In unserem zuvor Schlüssel-Verzeichnis befindet sich nun der erstellte private Schlüssel.

 # ll /var/spool/amavisd/dkim
-rw-------. 1 amavis amavis 3247 Nov 26 12:50 dkim-key-141126.pem

In dieser Datei befindet sich nun der private key.

 # cat /var/spool/amavisd/dkim/dkim-key-141126.pem
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAuJ3/CruOs3fCU0ujOStcNN85TJh+5HvMa9m99C5XuRBlxOr+
fp5BeIEtiPO0szKvvPojwrueCq0oOuEzjR/i2ObpRkzKRUXmAa0qVezUZwQIbKei
uKII0PnpQclDrmQrzSXcQWPT57tkPg17Q9WamFUUaHeN3+pVGtMyjYekRaAoRlV+
a1gD111kXMPhiaFTMIncoRBS/gYN8FjfekH+ezqbLHLB8DLJQBZEGUILvJjAHX07
22XyqYtkn1qfv63nPRGw/qqAW1072Gchq4ZS4ZPQ89SrK4KcHt/XptSlztXMWtmR
FQriHdvbjr1Fx7ZwXdTQ+ik2AUZLMdhMrQe6/1GujQiMD6po81NpYbrjnfd+QF4s
Ubus4wPQKVNzsctiuzGlWsFexSHP4dAZtKnImJhVDnzZODQy0nSafedlr5g4VR36
vgm0YPWjSyRNnC/APHyw0DtHIrzTqfKuDeGv80uMPbEdujrw9gLbK3H8ow42iTic
mgPgT3J5j70ZOo4o4FMtpZ/AEQw+VnWpSfw7bkMjufLc29XHbtp22wfgq2Lmarr3
+psaHokFaQrImkMbzdSL9CdabkLptanAilLScvq8UaKVC+G1+vHDgaweq3BhXD5+
YcJnJlp4msUqqxGYlnx4RSvv8PipMU2DsVFbNJSH5NJuS7GuzplNg+f20ysCAwEA
AQKCAgAY4qM4TSPlKSV2mOF9mUyqi9RrcLraDZ32g7lJKt4EQiOVsZ9wbeChX7hF
l6Qp65Eoxgb//s5E3iZoGWcbhMrNNgMHyN4TDGL+otrsDiprYG3KR6Z1gNHzaVx5
06ld3n7Q/mN8JPqxZ98RRjvxXt+h3QYNNuBW6H1kSkesMDaCdB45rNiHm6uY4ivf
HUBPjwFpr4uf4lVtjF9goHovPqoQ7ktwaF+gAxiBnP688NwoJebvkqv43Psiw3li
yZJzAfwDjVjwWwdGSYEBoJU3S7nsUkJ+O5J/IPHub3ngMRXQlZ0gOeeGkJr+L16f
FQBM9VicLU2mCtwOu+zy4Rck07/u4/Xkqnq5cNLbc0a1AYU6UDikB3yrG1QeupGg
/0M11D/4qDJ8hVK8Sl72SEWMnbkLh5YZEOoKE83C4uQ79yMnbSADXHJfUHmnO6O8
aDlCaMoRKw+Dj4n90/d3R-m4i153rV3R-gURu+p8UXtpz19zXK9nxsBsI1bl/63M
4y0VMba8UjgtSz2rzrjO2BkN4g/p3k1wmgyxAorJeyZRcNpG+HdBf4jMo5j8f+Jd
BlZgjFx0d69v3hToHfWd6Un4yc1+KDsyB1uNwuA1zs5lVX5QGba5LgYhNPUWmhQ/
3Vj2hG7Pp4FpK1UcnwoyX8YqK0/NJICqkwu+kDUDLHapgnVawQKCAQEA2YR/pVc4
CXEyxwwCfV5Q6qtHdgHGXwKfMikQl86YmDy2DLGTSojQW8BZmlCAxDqmaWit0DN8
TEGoM+hkVenz5ebG+SVFGGdQEh+urrRCHkrBIAGiNMHhh0ecKud2z7Pc+nxSDdKS
8QPko+wnAzG/WKNkl73Wvx06UqnbBqMSiG6SKjdtH2Kh2wXb5KT5PQYY112W4JIi
53PVQMbgwFdRaJyy1WmCro0OaIs/6bJPWIKuKdSw35fC6/lgQsC7elD5p0XrdcpN
MuYJJOg0L8GYvIqO5+AIR5tCkutbd5yAEmLoHN6/IwDrt69YV1yLg27N09a/RJbI
uTkQmtpaJBgzcQKCAQEA2UdrNeaoz9jaRxm6HJgGtIbO8RJM/9bGYMxgSP+KAGIY
nQIEF/rxySdzIrkBuewIiWgKdjFiP+1DCi7M6IDu3YNxYik6f1Pp2HlZ7MUmT3XF
3Tm2RjnR33eCknoicohzEj5tSKFzshCqDDlv1sm9e32+eO5xjgx59EpxvjqQnP/4
PR3gxSIOGfYwAaHJnV3n/YAKKhM52f09+IMouk0javOYDg96Se6acnZszcLOv8vQ
FiwtRTAWiV6wbY1H7SFwWb2fMINsmh9E4eOz17cmwVHDSjxOnCvwUpFsAAqqWRBa
jqFxumSApErGEW97E1ucAdeZemqtki0yY3mnu6wqWwKCAQEAwjVNCsDu5W9OWO3e
IzVcpcm7ih9XkGj03oJPsFrjX7mFCZxa2AeDkQgSeHc8IPgEsMSnu+bcKfHNTltF
infSLgh4yuZ95KYJlcT34EBNcGJqQDt1KgmZZYGIa74yFIyQ1oy9bl3+mHZTZBBr
XKzEHU31eI4k+IoOEtRZHHnpCCtBEbRfF9CmlrmKdYDej5+r+k4zcdrIk0KWurlW
3iSYKQEPowALj/GdVbZOoEd2FJ7JBcxDB7+mZ65GRhNy0GkQHkuNSaQQfUtqCqvQ
PHtr9Zr4sQsUGWsEa8z747W1m7T3bR9sJMKjs2M5Svb0EauS1ns8Vu8R1F6g9sHS
DbwV4QKCAQEAiMguFOOdOCNy3jmy8Rc/eVw4YIi90n05q2xd3PaJwM4AYq8HNrVy
ish78cr37DxL73yAwYE7MbVCc+Gce23XcbmyojIEMm34E5/pXWWLRZCFvEv9lF4H
4h8RIvcidB3qglse0N6IQ/9gUrCHywypsGOV5DRvZhYym/hVfITPzxZRBuCNRGy4
5d0WwaBBFQEt72cwfuZVkAadgZnIBOhUuJqbCZbyzCIaNp6Yxjux/gnneF3dLeYk
+duTQ5QiSIS5frUhxt+leazfpzi6Wb1h92dqgoxOjIAYrVIA5FHShXkHGS1HNCja
1xJ/eDBvEXOlVX+NjgQkOpabVwYZ8spiawKCAQAI30WzWHPLcFHOhaIIRr7VlUv5
IR96T95H+c0a5JzNFhSOwxnqCWOtTmUnlaJcFwbREYl2mrImjht44Tz3bNjQlGqr
04WUf1VExh1WRfRGlT8LWuSLgVDHrI6M5yl5sefzILqogHaiEAvKbaTlIowD8hbR
MJGE0QdJKZNU/+dPO5w/0Rnq2kY54OJhSWZE0Z6zWqMQa3komnqQAXnlvHaUshjy
0M8oJ2zG8LEvqJllsjIU3orVPPfkuenWkn3cGQhx1xZIEEaLo1YC8eyAGW2OkKMP
OMrxmovD66O4MuPCnnPfcftE1e80Gi/UgxiVrdGOqx8BZ/AmChdWFZx5ZrVF
-----END RSA PRIVATE KEY-----

Konfiguration (single domain)

Den ersten Teil unserer Konfiguration haben wir schon erledigt. Nun weisen wir unseren AMaViS-Daemon an unsere ausgehenden Nachrichten mit einer DKIM-Signatur zu versehen. Hierzu tragen wir in der Section DKIM - Domain Key Identified Mail folgende Zeilen ein.

 # vim /etc/amavisd/amavisd.conf
################################################################################
## DKIM - Domain Key Identified Mail
#
 
# DKIM-Signaturen verifizieren
$enable_dkim_verification = 1;
 
# DKIM-Signaturen erstellen
$enable_dkim_signing = 0;
 
# Private Keys und Selectors
#
# signing domain         selector   private key                       options
# -------------          --------   ----------------------            ----------
dkim_key('nausch.org', '141126', '/var/spool/amavisd/dkim/dkim-key-141126.pem', h=>'sha256');
 
# DKIM Signing Policies
@dkim_signature_options_bysender_maps = (
    { '.' =>
        {
                ttl => 21*24*3600,
                c => 'relaxed/simple'
        }
    }
);

Die Variable $enable_dkim_signing setzen wir erst noch auf den Wert 0, da wir unseren public-key erst noch auf dem für uns zuständigen Nameserver einen entsprechenden DNS-Eintrag hinterlegen müssen, sprich wie müssen den public-key veröffentlichen. Anderenfalls würde AMaViS- bereits jetzt schon Nachrichten Signieren, die dann aber vom Empfänger nicht geprüft werden können. Schlimmstenfalls würde das zu bounces oder rejects führen!

Die Angaben der Schlüsselparameter im obigen Beispiel haben folgende Bedeutungen:

Über das Array @dkim_signature_options_bysender_maps können ferner Standardwerte für Signatur-Tags überschrieben werden. Dies kann per Sender(Domäne) erfolgen, oder wie im obigen Beispielals „catch all“ für alle Absender. Über den Parameter ttl kann defniert werden, wie lange eine Signatur nach Erstellung als gültig erachtet werden soll - in unserem Beispiel also 3 Wochen. Der Parameter c definiert, wie Amavis die zur Signierung herangezogenen Daten ggf. umeschrieben werden sollen. Detailierte erklärungen hierzu entnimmt man dem Kapitel 3.5 The DKIM-Signature Header Field bzw. dem Kapitel 3.4. Canonicalization.

Konfiguration (multiple domain)

Haben wir noch weitere virtuelle Mailserver am laufen, können wir durch nachfolgende exeplarische Zeilen erreichen, dass auch diese Nachrichten mit unserem DKIM-Signatur versehen werden können.

 # vim /etc/amavisd/amavisd.conf
################################################################################
## DKIM - Domain Key Identified Mail
#
 
# DKIM-Signaturen verifizieren
$enable_dkim_verification = 1;
 
# DKIM-Signaturen erstellen
$enable_dkim_signing = 1;
 
# Private Keys und Selectors
#
# signing domain         selector   private key                       options
# -------------          --------   ----------------------            ----------
dkim_key('nausch.org', '141126', '/var/spool/amavisd/dkim/dkim-key-141126.pem');
dkim_key('omni128.de', '141126', '/var/spool/amavisd/dkim/dkim-key-141126.pem', h=>'sha256');
dkim_key('ebersberger-liedersammlung.de', '141126', '/var/spool/amavis/dkim/dkim-key-141126.pem', h=>'sha256');

Betreiben wir einen Mailserver für sehr viele virtuellen Domänen und hat auch noch mehrere Mail-Administratoren, die sich um die Neuanlage von Domänen und deren Nutzerkonten sowie deren Pflege kümmern, so kann selbst das händische Pflegen der Domänen in den verschiedenen Konfigurationsdateien zum nervigen und fehleranfälligem Zeitvertreib werden. Abhilfe schafft hier eine zentrale Datei, in der alle lokalen Maildomänen enthalten sind und hier machen wir uns es so einfach wie nur möglich.

Bei der Grundkonfiguration von AMaViS haben wir bereits in der Section DESTINATIONS alle localen Domains definiert.

 # vim /etc/amavisd/amavisd.conf
################################################################################
## DESTINATIONS
#
 
# Definition der Verkehrsrichtungen:
 
# Das ist nach intern. Alle anderen Destinationen sind im Umkehrschluss extern.
@local_domains_maps = (
    [".$mydomain"],
    read_hash("/etc/postfix/all_local_domains_map"),
    );
 
...

Hier haben wir ja bereits eine Aufstellung aller bekannten lokalen (virtuellen) Domains. Mit Hilfe dieser Tabelle generieren wir uns nun die Liste mit den DKIM-Schlüsseln. Anstatt jede Domain einzeln in der amavisd.conf aufzuführen, binden wir einfach die liste aller Domains /etc/postfix/all_local_domains_map in die /etc/amavisd/amavis.conf ein.

 # vim /etc/amavisd/amavisd.conf
################################################################################
## DKIM - Domain Key Identified Mail
#
 
# DKIM-Signaturen verifizieren
$enable_dkim_verification = 1;
 
# DKIM-Signaturen erstellen
$enable_dkim_signing = 0;
 
# Private Keys und Selectors
#
# signing domain         selector   private key                       options
# -------------          --------   ----------------------            ----------
# dkim_key('nausch.org', '201411', '/var/spool/amavis/dkim/201411_nausch.org');
 
# Django : 2014-02-19
# DKIM-Keys für automatisch generierte Domainliste definieren
  open(filehandle,'/etc/postfix/all_local_domains_map')
    or die "Can't open domain-list-file: $!";
       while (<filehandle>)
             {
              chomp; s/\s*#.*$//; next if $_ eq '';
              dkim_key($_, '140224', '/var/spool/amavisd/dkim/dkim-key-141126.pem', h=>'sha256');
             }
  close(filehandle) or die "Can't close domain-list-file: $!";
 
# DKIM Signing Policies
@dkim_signature_options_bysender_maps = (
    { '.' =>
        {
                ttl => 21*24*3600,
                c => 'relaxed/simple'
        }
    }
);
 
...

DKIM & DNS

public key

Wie Eingangs bereits erwähnt, kann der Empfänger eine DKIM-signierte eMail mit Hilfe des public keys auf Echtheit hin überprüfen. Damit der Empfänger den public key abfragen kann, müssen wir diesen im DNS hinterlegen. Hierzu lassen wir uns den public-key unseres DKIM-keys am besten mit Hilfe des Befehls amavisd ausgeben.

 # amavisd -c /etc/amavisd/amavisd.conf showkey nausch.org
; key#2, domain nausch.org, /var/spool/amavisd/dkim/dkim-key-141126.pem
140224._domainkey.nausch.org.   3600 TXT (
  "v=DKIM1; h=sha256; p="
  "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAojGXwA9zJFJ4wpa2PB51"
  "amh5s2amqyBpUJR07or9SeqZlGV0193VGGuVM72w7ry8AzTKGZKRf2oPtjgx2zAF"
  "FQDoewOQVDdkQG9g+VGLW/NWGc/fKhOe1i0Q+O4GMoPcJ6rNerw5mVpnPpejc8LZ"
  "0SE4EN6hcJ0lkgNK8wqzkWvrA5xwouuj1WfXTHm6Ov4I7HRsmHvPyOaK+jpMBBYj"
  "o9qRtZiU48x+DOp3ti3r/dxaS8kKCDI+ohXoruUyMUU7U5/RISCGxahO7c5fm2pC"
  "OdwxnmEMdb4QLgtPV1S3atyq4JFNt2Qc6C06fDzN3ylyH+orrCjBBSa75ZdVxOun"
  "my5Iv7GbFUqX8QAGH1l0KyZWBdlx3YRME2ZpThOjwhG9cl66cc8w7dxlIFM1XZb/"
  "Z8SlFHFelhaqSovYPAd30pbooU4gL+sGOqqvdc18yXB7jIjUmiBNsO7HTXiI/fly"
  "dl+wWylh202hlTdl1VG3Gskup8I2gpuRK7SAsbNRzr2KN05T0B/zgr0bNjiBCDNm"
  "CiPf+z9/22MlCVczjL0G8o11bB5E2/IBMEpBAfw48cmSzmEqGXZhluhRcfkr7oiy"
  "DQMObGLgidf2+pY7YoxUHigq5ptF8/Ny8hXv5FJb5DuoQTyB8atUrhYDrMcZldDD"
  "4sUZajSC04shzSmob+gimAMCAwEAAQ==")

Möchte man sich alle Schlüssel anzeigen lassen, nutzt man einfach die Option showkeys beim Aufruf von amavisd.

 # amavisd -c /etc/amavisd/amavisd.conf showkeys
; key#1, domain omni128.de, /var/spool/amavisd/dkim/dkim-key-141126.pem
140224._domainkey.omni128.de.   3600 TXT (                             
  "v=DKIM1; h=sha256; p="                                              
  "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAojGXwA9zJFJ4wpa2PB51"   
  "amh5s2amqyBpUJR07or9SeqZlGV0193VGGuVM72w7ry8AzTKGZKRf2oPtjgx2zAF"   
  "FQDoewOQVDdkQG9g+VGLW/NWGc/fKhOe1i0Q+O4GMoPcJ6rNerw5mVpnPpejc8LZ"   
  "0SE4EN6hcJ0lkgNK8wqzkWvrA5xwouuj1WfXTHm6Ov4I7HRsmHvPyOaK+jpMBBYj"   
  "o9qRtZiU48x+DOp3ti3r/dxaS8kKCDI+ohXoruUyMUU7U5/RISCGxahO7c5fm2pC"   
  "OdwxnmEMdb4QLgtPV1S3atyq4JFNt2Qc6C06fDzN3ylyH+orrCjBBSa75ZdVxOun"   
  "my5Iv7GbFUqX8QAGH1l0KyZWBdlx3YRME2ZpThOjwhG9cl66cc8w7dxlIFM1XZb/"   
  "Z8SlFHFelhaqSovYPAd30pbooU4gL+sGOqqvdc18yXB7jIjUmiBNsO7HTXiI/fly"   
  "dl+wWylh202hlTdl1VG3Gskup8I2gpuRK7SAsbNRzr2KN05T0B/zgr0bNjiBCDNm"   
  "CiPf+z9/22MlCVczjL0G8o11bB5E2/IBMEpBAfw48cmSzmEqGXZhluhRcfkr7oiy"   
  "DQMObGLgidf2+pY7YoxUHigq5ptF8/Ny8hXv5FJb5DuoQTyB8atUrhYDrMcZldDD"   
  "4sUZajSC04shzSmob+gimAMCAwEAAQ==")                                  

...

...

; key#16, domain c3n705.guru, /var/spool/amavisd/dkim/dkim-key-141126.pem
140224._domainkey.c3n705.guru.  3600 TXT (
  "v=DKIM1; h=sha256; p="
  "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAojGXwA9zJFJ4wpa2PB51"
  "amh5s2amqyBpUJR07or9SeqZlGV0193VGGuVM72w7ry8AzTKGZKRf2oPtjgx2zAF"
  "FQDoewOQVDdkQG9g+VGLW/NWGc/fKhOe1i0Q+O4GMoPcJ6rNerw5mVpnPpejc8LZ"
  "0SE4EN6hcJ0lkgNK8wqzkWvrA5xwouuj1WfXTHm6Ov4I7HRsmHvPyOaK+jpMBBYj"
  "o9qRtZiU48x+DOp3ti3r/dxaS8kKCDI+ohXoruUyMUU7U5/RISCGxahO7c5fm2pC"
  "OdwxnmEMdb4QLgtPV1S3atyq4JFNt2Qc6C06fDzN3ylyH+orrCjBBSa75ZdVxOun"
  "my5Iv7GbFUqX8QAGH1l0KyZWBdlx3YRME2ZpThOjwhG9cl66cc8w7dxlIFM1XZb/"
  "Z8SlFHFelhaqSovYPAd30pbooU4gL+sGOqqvdc18yXB7jIjUmiBNsO7HTXiI/fly"
  "dl+wWylh202hlTdl1VG3Gskup8I2gpuRK7SAsbNRzr2KN05T0B/zgr0bNjiBCDNm"
  "CiPf+z9/22MlCVczjL0G8o11bB5E2/IBMEpBAfw48cmSzmEqGXZhluhRcfkr7oiy"
  "DQMObGLgidf2+pY7YoxUHigq5ptF8/Ny8hXv5FJb5DuoQTyB8atUrhYDrMcZldDD"
  "4sUZajSC04shzSmob+gimAMCAwEAAQ==")

Natürlich kann man auch openssl dazu verwenden, sich den public-key ausgeben zu lassen.

 # openssl rsa -in /var/spool/amavisd/dkim/dkim-key-141126.pem -out /var/spool/amavisd/dkim/dkim-key_141126_public.pem -pubout -outform PEM
 writing RSA key

Die Dateiberechtigung passen wir entsprechend an.

 # chmod 600 /var/spool/amavisd/dkim/dkim-key_141126_public.pem

Die Schlüsseldatei enthält nun den public-key für unsere DKIM-Konfiguration.

 # less /var/spool/amavisd/dkim/dkim-key_141126_public.pem
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAojGXwA9zJFJ4wpa2PB51
amh5s2amqyBpUJR07or9SeqZlGV0193VGGuVM72w7ry8AzTKGZKRf2oPtjgx2zAF
FQDoewOQVDdkQG9g+VGLW/NWGc/fKhOe1i0Q+O4GMoPcJ6rNerw5mVpnPpejc8LZ
0SE4EN6hcJ0lkgNK8wqzkWvrA5xwouuj1WfXTHm6Ov4I7HRsmHvPyOaK+jpMBBYj
o9qRtZiU48x+DOp3ti3r/dxaS8kKCDI+ohXoruUyMUU7U5/RISCGxahO7c5fm2pC
OdwxnmEMdb4QLgtPV1S3atyq4JFNt2Qc6C06fDzN3ylyH+orrCjBBSa75ZdVxOun
my5Iv7GbFUqX8QAGH1l0KyZWBdlx3YRME2ZpThOjwhG9cl66cc8w7dxlIFM1XZb/
Z8SlFHFelhaqSovYPAd30pbooU4gL+sGOqqvdc18yXB7jIjUmiBNsO7HTXiI/fly
dl+wWylh202hlTdl1VG3Gskup8I2gpuRK7SAsbNRzr2KN05T0B/zgr0bNjiBCDNm
CiPf+z9/22MlCVczjL0G8o11bB5E2/IBMEpBAfw48cmSzmEqGXZhluhRcfkr7oiy
DQMObGLgidf2+pY7YoxUHigq5ptF8/Ny8hXv5FJb5DuoQTyB8atUrhYDrMcZldDD
4sUZajSC04shzSmob+gimAMCAwEAAQ==
-----END PUBLIC KEY-----

Den public-key lassen wir uns am besten mit Hilfe des Befehls amavisd ausgeben, denn so können wir einfach die Zeichenfolge direkt in die Zonendatei des Nameserver BIND ein. Somit können auch einfach größere Schlüssel, wie in unserem Beispiel 4096 bits hinterlegt werden, da der Schlüssel bereits in mehrere TXT-Häppchen aufgeteilt wurde!

Den, mit Hilfe von amavisd ausgegebenen, Public-key hinterlegen wir nun im zuständigen DNS-Server. Ist dies geschehen können wir den public key wie folgt abrufen.

 # host -t TXT 140224._domainkey.sec-mail.guru
;; Truncated, retrying in TCP mode.
140224._domainkey.sec-mail.guru descriptive text "v=DKIM1\; p=" "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuJ3/CruOs3fCU0ujOStc" "NN85TJh+5HvMa9m99C5XuRBlxOr+fp5BeIEtiPO0szKvvPojwrueCq0oOuEzjR/i" "2ObpRkzKRUXmAa0qVezUZwQIbKeiuKII0PnpQclDrmQrzSXcQWPT57tkPg17Q9Wa" "mFUUaHeN3+pVGtMyjYekRaAoRlV+a1gD111kXMPhiaFTMIncoRBS/gYN8FjfekH+" "ezqbLHLB8DLJQBZEGUILvJjAHX0722XyqYtkn1qfv63nPRGw/qqAW1072Gchq4ZS" "4ZPQ89SrK4KcHt/XptSlztXMWtmRFQriHdvbjr1Fx7ZwXdTQ+ik2AUZLMdhMrQe6" "/1GujQiMD6po81NpYbrjnfd+QF4sUbus4wPQKVNzsctiuzGlWsFexSHP4dAZtKnI" "mJhVDnzZODQy0nSafedlr5g4VR36vgm0YPWjSyRNnC/APHyw0DtHIrzTqfKuDeGv" "80uMPbEdujrw9gLbK3H8ow42iTicmgPgT3J5j70ZOo4o4FMtpZ/AEQw+VnWpSfw7" "bkMjufLc29XHbtp22wfgq2Lmarr3+psaHokFaQrImkMbzdSL9CdabkLptanAilLS" "cvq8UaKVC+G1+vHDgaweq3BhXD5+YcJnJlp4msUqqxGYlnx4RSvv8PipMU2DsVFb" "NJSH5NJuS7GuzplNg+f20ysCAwEAAQ=="

ADSP

Über ADSP3) kann ein (Mail)-Domaininhaber definieren, was ein Mailserver mit einer zu Annahme anstehenden eMail passieren soll, sofern dessen DKIM4)-Signatur nicht gültig ist. Für ADSP wird dazu ein eigener Qualifier _adsp benutzt. Am Beispiel der Domain sec-mail.guru ergibt sich der Name _adsp._domainkey.sec-mail.guru.

Der (TXT)-Datensatz hat dabei folgende Struktur „dkim=<WERT>“. Über den <WERT> kann der Domaininhaber folgendes festlegen:

Wurde nichts definiert oder ein anderer Wert als die oben angegeben wurde, wird der Default-Wert unknown gesetzt. Somit ergibt sich in unserem Anwendungsbeispiel, bei dem der Domaininhaber von sec-mail.guru selbst alle Nachrichten signiert und dem Empfänger bittet, Nachrichten mit schadhafter DKIM-Signatur zu rejecten, folgender TXT-Record:

_adsp._domainkey.sec-mail.guru.          IN TXT  "dkim=discardable;"

Diesen Record veröffentlichen wir nun über unseren DNS. Somit kann ein Empfänger nicht nur den DKIM-Schlüssel zum Verifizieren der DKIM-Signatur abfragen, sondern auch den ADSP-TXT-Record und weiß damit, was er ggf. machen sollte, sofern die DKIM-Signatur gebrochen wurde.

Tests

DNS + private key

Nachdem der TXT zur Verfügung steht, können wir mit Hilfe von amavisd diesen Überprüfen.

 # amavisd -c /etc/amavisd/amavisd.conf testkeys
TESTING#1: 141126._domainkey.omni128.de         => pass
...

...
TESTING#16: 141126._domainkey.c3n705.guru       => pass

Wollen wir nur den Schlüssel einer bestimmten Domain testen, so verwenden wir folgenden Aufruf.

 # amavisd -c /etc/amavisd/amavisd.conf testkey domain omni128.de
TESTING#1: 141126._domainkey.omni128.de         => pass

Das folgende Beispiel zeigt eine Abfrage, die die Fehlermeldung invalid (public key: OpenSSL error: bad base64 decode) nach sich zieht.

 # amavisd -c /etc/amavisd/amavisd.conf testkey domain ebersberger-liedersammlung.de
TESTING#6: 141126._domainkey.ebersberger-liedersammlung.de      => invalid (public key: OpenSSL error: bad base64 decode)

Die Fehlermeldung bad base64 decode weißt direkt auf einem Typo-Fehler im Schlüsseldaten hin!

Das nächste Beispiel zeigt eine Abfrage, die eine weitere Fehlermeldung nach sich zieht:

 # amavisd -c /etc/amavisd/amavisd.conf testkey domain ebersberger-liedersammlung.de
TESTING#6: 141126._domainkey.ebersberger-liedersammlung.de => fail (OpenSSL error: data too large for key size)

Erhalten wir die Fehlermeldung fail (OpenSSL error: data too large for key size), so liegt es meist nicht an einem vermeintlich zu großen DKIM-Schlüssel, den wir verwenden, sondern schlichtweg an einem Typo-Fehler beim DNS-Eintrag unseres DKIM-Schlüssels!

Wurde der public DKIM-Schlüssel revoked, also zurückgezogen, zeigt dies nachfolgende Fehlermeldung.

TESTING#6: 140224._domainkey.piraten-it.guru   => invalid (public key: revoked)

Möchte man einen DKIM-Schlüssel zurückziehen (revoke), dann löscht man im DNS-Eintrag einfach den Teil hinter dem p=:

main._domainkey.piraten-it.guru           IN      TXT     "v=DKIM1; p="

Wir können natürlich auch direkt den TXT-Record eines Hosts abfragen eim DNS-Server abrufen:

 # host -t TXT 141126._domainkey.nausch.org
;; Truncated, retrying in TCP mode.
141126._domainkey.nausch.org descriptive text "v=DKIM1\; p=" "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuJ3/CruOs3fCU0ujOStc" "NN85TJh+5HvMa9m99C5XuRBlxOr+fp5BeIEtiPO0szKvvPojwrueCq0oOuEzjR/i" "2ObpRkzKRUXmAa0qVezUZwQIbKeiuKII0PnpQclDrmQrzSXcQWPT57tkPg17Q9Wa" "mFUUaHeN3+pVGtMyjYekRaAoRlV+a1gD111kXMPhiaFTMIncoRBS/gYN8FjfekH+" "ezqbLHLB8DLJQBZEGUILvJjAHX0722XyqYtkn1qfv63nPRGw/qqAW1072Gchq4ZS" "4ZPQ89SrK4KcHt/XptSlztXMWtmRFQriHdvbjr1Fx7ZwXdTQ+ik2AUZLMdhMrQe6" "/1GujQiMD6po81NpYbrjnfd+QF4sUbus4wPQKVNzsctiuzGlWsFexSHP4dAZtKnI" "mJhVDnzZODQy0nSafedlr5g4VR36vgm0YPWjSyRNnC/APHyw0DtHIrzTqfKuDeGv" "80uMPbEdujrw9gLbK3H8ow42iTicmgPgT3J5j70ZOo4o4FMtpZ/AEQw+VnWpSfw7" "bkMjufLc29XHbtp22wfgq2Lmarr3+psaHokFaQrImkMbzdSL9CdabkLptanAilLS" "cvq8UaKVC+G1+vHDgaweq3BhXD5+YcJnJlp4msUqqxGYlnx4RSvv8PipMU2DsVFb" "NJSH5NJuS7GuzplNg+f20ysCAwEAAQ=="

signing und verifying

Nachdem die Überprüfung der AMaViS/DNS-Konfiguration positiv ausgefallen war, können wir uns jetzt daran machen, das Signieren der ausgehenden Nachrichten zu aktivieren. Dazu ändern wir den vorbereiteten Eintrag in der Section DKIM - Domain Key Identified Mail.

 # vim /etc/amavisd/amavisd.conf
################################################################################
## DKIM - Domain Key Identified Mail
#
 
# DKIM-Signaturen verifizieren
$enable_dkim_verification = 1;
 
# DKIM-Signaturen erstellen
$enable_dkim_signing = 1;
 
...

Anschließend führen wir einen Reload des AMaViS-Daemon durch.

 # systemctl reload amavisd

Schicken wir nun eine Test-eMail so findet der Empfänger im Mailheader die entsprechende DKIM-Signatur.

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=nausch.org; h=
	content-transfer-encoding:content-type:content-type:mime-version
	:user-agent:from:from:date:date:message-id:received:received; s=
	140224; t=1394130616; x=1395945017; bh=frcCV1k9oG9oKj3dpUqdJg1Px
	RT2RSN/XKdLCPjaYaY=; b=JTAoETI+ZtTJ0xFDk4DcZqDxPAq+fOuQ+BbjyYmMx
	izj2W0G8zJe+a5RVAKj9nFlPgPB1KtQ3rCPXmYsn59zJ/DyS30gZjkt43KQUcydr
	Hf3z8QmFmPWvvBx/bLKWrs9+RwsckDsJ7OSh1u3pOvqaTzdMjOcxt3CFNFXhSBj0
	ipOZa2FrXNeHJpAhMpAFZ9ynhxV8ekg9v000f6ZLKlzTj5MNuXzohhfdH7I1hy/R
	b9r+/zTY0NjEtCvLn2k/HBmoDxzUwx5A/XuQGTcEfBZelFgKdJuaDTNVCdlPgmSv
	o+LB2i8zLWNe56hrKDzEoOS872xQQvErezZ4+X7UPpMeswspcaLdnSkbeWMNGElw
	pTpL/h/WN3lJiVYB7+ZrC0k/V79KZWsui7og3KZ9PwyO9wB6HJOM80O8zIs8jH6o
	S4Gnk0yXgrx6B9wVwytAhEguDe3dhm6stQgkzvSi0sl1I9WV85OS3+5sFfOpuvju
	icOrI2DGNZnuFWFmbiaTLmMlw4y2QENxP/EonCuVKCGit5CGdkuJU+Q6HVfkseGU
	mqH8mwZRdaTcQD2M3mtGNqDYIlnCsir/whLhkFqP/zeqCAm9sRbJXAuYIfxrONDm
	XkEEoELtW7aIWIKM2xWagUtmVVW/FBbYOonMNuyLuC7Gf9q5gN5WqMwapJRjdtNQ
	dk=

Der empfangende Mailserver ist mit Hilfe des Headers: Authentication-Results: in der Lage festzustellen, ob die eMail unverändert angekommen und somit nicht manipuliert wurde:

Authentication-Results: mx1.tachtler.net (amavisd-new);
	dkim=pass (4096-bit key) header.d=nausch.org

Wurde die Nachricht jedoch hingegen verändert, so schlägt die Überprüfung fehl und wird entsprechend quittiert:

Authentication-Results: amavis.dmz.nausch.org (amavisd-new);
	dkim=fail (1024-bit key) reason="fail (message has been altered)"
	header.d=controlc.de

Die Veränderung der Nachricht passierte in dem obigen Beispiel dadurch, dass die Nachricht aus einer Mailingliste vom Mailinglisten-Server verändert wurde, da am Ende der nachricht ein listenspezifischer Mailfooter angefügt wurde.


Wie man das Brechen der DKIM-Signaturen durch den Mailinglisten-Manager mailman unterbindet, also den Mailinglistenserver DKIM-konform konfiguriert, wird in diesem Abschnitt erklärt.

signing (WEB-online)

Eine sehr gute und einfache Möglichkeit die DKIM-Konfiguration zu testen, stellt die DomainKeys, DKIM, SPF, SpamAssassin Email Validator von Brandon Checketts dar. Die angegebene temporäre eMailadresse kopieren wir uns und schicken an diese eine Testnachricht.

eMail Testseite

Wir schicken also nun eine Testnachricht an die angegebene Addresse, im einfachsten FAll nutzen wir dazu einfach das Schweizer Taschenmesser für SMTP, kurz [http://www.jetmore.org/john/code/swaks/|swaks]

 # swaks --to Dj4n90-i5-a-G33k@www.brandonchecketts.com --from n3rd@sec-mail.guru --header-X-Test "test eMail" --server 10.0.0.87 --port 587 --tls --header "Subject: DKIM-Signing-Test" --auth NTLM --auth-user n3rd@sec-mail.guru --auth-password BuAGEAd!QBzAGMAaAA

Über die Schaltfläche [View Results] erhalten wir dann die Prüfungsergebnisse unserer Testnachricht präsentiert.

Original Message:

Return-Path: <n3rd@sec-mail.guru>
X-Original-To: Dj4n90-i5-a-G33k@www.brandonchecketts.com
Delivered-To: spamapp@yen.roundsphere.com
Received: from mx01.nausch.org (mx01.nausch.org [217.91.103.190])
	by yen.roundsphere.com (Postfix) with ESMTP id 292D1533009D
	for <Dj4n90-i5-a-G33k@www.brandonchecketts.com>; Thu, 27 Nov 2014 06:58:44 -0500 (EST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=sec-mail.guru; h=
	message-id:x-mailer:subject:subject:from:from:date:date; s=
	140224; t=1417089522; x=1418903923; bh=ecGWgWCJeWxJFeM0urOVWP+KO
	lqqvsQYKOpYUP8nk7I=; b=dT0+XLEMpY7/Mhj4ha59okpgszY8v1Kku/LLD0x2o
	V9eh4YN2lzh5vdsQrh3fB0wqcQwc46ypNiHrYAXdI/r5WOJqOiOIdIpFlkHmmCpU
	8c808dQGgh5iEy01nkKAoJY3641CZrxp1gshtVyQUrM8x5cRhdk9KvdmHCPMkkCn
	vVSC/xCtLaYjNUPEad5SXnHeSjRWCkeI/raLYKzTaIAei5zNxuFQc1aOX0B33R0f
	z5pZZYSmw1CBYE644jTtiHcEpy6qonjwh53NL5FrI/qMbScOImtCC7r76xUu7mSf
	mJJw+ayVBDuzIxJEta38QySxkdcvS4YejEMTFT7ACcJoZeu0ct3Z9gXYJo301ESr
	ZTPoxhqNSRTs105dE26DDVlAUZjeTAtRgJlEge4zhSO4wem2qsRpFjXh7vbjKz7i
	Jy/6FHm8/0OpONowmUhfau9OMysQOEBwDibQWpJmM4v6nr+D+mYZvD6J76vb3f6M
	LJ440FpkY2EA0zQ1y9O2S62IDDS1ON+fyufJJ0W9oaelTYr45/ILfYzHKOc2xZsW
	+Irem5j0//HLdERT/hQqIPDp3yObGVn30fF/OX56i5h+tGTNkYpX4ykvKR7AwsiU
	KpPuliFssSxCR4QHC08rVoQda+AtRvGWlNEBgN3RDR65iSm7Q1fJJt3Z6LTakv7/
	38=
X-Virus-Scanned: amavisd-new at nausch.org
Received: from vml000087.dmz.nausch.org (vml000087.dmz.nausch.org [10.0.0.87])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by mx01.nausch.org (Postfix) with ESMTPSA id E9A98C00088
	for <Dj4n90-i5-a-G33k@www.brandonchecketts.com>; Thu, 27 Nov 2014 12:58:41 +0100 (CET)
Date: Thu, 27 Nov 2014 12:58:41 +0100
To: Dj4n90-i5-a-G33k@www.brandonchecketts.com
From: n3rd@sec-mail.guru
Subject: DKIM-Signing-Test
X-Mailer: swaks v20130209.0 jetmore.org/john/code/swaks/
X-Test: test eMail
Message-Id: <20141127115841.E9A98C00088@mx01.nausch.org>

This is a test mailing

DKIM Information:

DKIM Signature

Message contains this DKIM Signature:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=sec-mail.guru; h=
	message-id:x-mailer:subject:subject:from:from:date:date; s=
	140224; t=1417089522; x=1418903923; bh=ecGWgWCJeWxJFeM0urOVWP+KO
	lqqvsQYKOpYUP8nk7I=; b=dT0+XLEMpY7/Mhj4ha59okpgszY8v1Kku/LLD0x2o
	V9eh4YN2lzh5vdsQrh3fB0wqcQwc46ypNiHrYAXdI/r5WOJqOiOIdIpFlkHmmCpU
	8c808dQGgh5iEy01nkKAoJY3641CZrxp1gshtVyQUrM8x5cRhdk9KvdmHCPMkkCn
	vVSC/xCtLaYjNUPEad5SXnHeSjRWCkeI/raLYKzTaIAei5zNxuFQc1aOX0B33R0f
	z5pZZYSmw1CBYE644jTtiHcEpy6qonjwh53NL5FrI/qMbScOImtCC7r76xUu7mSf
	mJJw+ayVBDuzIxJEta38QySxkdcvS4YejEMTFT7ACcJoZeu0ct3Z9gXYJo301ESr
	ZTPoxhqNSRTs105dE26DDVlAUZjeTAtRgJlEge4zhSO4wem2qsRpFjXh7vbjKz7i
	Jy/6FHm8/0OpONowmUhfau9OMysQOEBwDibQWpJmM4v6nr+D+mYZvD6J76vb3f6M
	LJ440FpkY2EA0zQ1y9O2S62IDDS1ON+fyufJJ0W9oaelTYr45/ILfYzHKOc2xZsW
	+Irem5j0//HLdERT/hQqIPDp3yObGVn30fF/OX56i5h+tGTNkYpX4ykvKR7AwsiU
	KpPuliFssSxCR4QHC08rVoQda+AtRvGWlNEBgN3RDR65iSm7Q1fJJt3Z6LTakv7/
	38=


Signature Information:
v= Version:         1
a= Algorithm:       rsa-sha256
c= Method:          relaxed/simple
d= Domain:          sec-mail.guru
s= Selector:        140224
q= Protocol:        
bh=                 ecGWgWCJeWxJFeM0urOVWP+KO
	lqqvsQYKOpYUP8nk7I=
h= Signed Headers:  message-id:x-mailer:subject:subject:from:from:date:date
b= Data:            dT0+XLEMpY7/Mhj4ha59okpgszY8v1Kku/LLD0x2o
	V9eh4YN2lzh5vdsQrh3fB0wqcQwc46ypNiHrYAXdI/r5WOJqOiOIdIpFlkHmmCpU
	8c808dQGgh5iEy01nkKAoJY3641CZrxp1gshtVyQUrM8x5cRhdk9KvdmHCPMkkCn
	vVSC/xCtLaYjNUPEad5SXnHeSjRWCkeI/raLYKzTaIAei5zNxuFQc1aOX0B33R0f
	z5pZZYSmw1CBYE644jTtiHcEpy6qonjwh53NL5FrI/qMbScOImtCC7r76xUu7mSf
	mJJw+ayVBDuzIxJEta38QySxkdcvS4YejEMTFT7ACcJoZeu0ct3Z9gXYJo301ESr
	ZTPoxhqNSRTs105dE26DDVlAUZjeTAtRgJlEge4zhSO4wem2qsRpFjXh7vbjKz7i
	Jy/6FHm8/0OpONowmUhfau9OMysQOEBwDibQWpJmM4v6nr+D+mYZvD6J76vb3f6M
	LJ440FpkY2EA0zQ1y9O2S62IDDS1ON+fyufJJ0W9oaelTYr45/ILfYzHKOc2xZsW
	+Irem5j0//HLdERT/hQqIPDp3yObGVn30fF/OX56i5h+tGTNkYpX4ykvKR7AwsiU
	KpPuliFssSxCR4QHC08rVoQda+AtRvGWlNEBgN3RDR65iSm7Q1fJJt3Z6LTakv7/
	38=
Public Key DNS Lookup

Building DNS Query for 140224._domainkey.sec-mail.guru
Retrieved this publickey from DNS: v=DKIM1; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuJ3/CruOs3fCU0ujOStcNN85TJh+5HvMa9m99C5XuRBlxOr+fp5BeIEtiPO0szKvvPojwrueCq0oOuEzjR/i2ObpRkzKRUXmAa0qVezUZwQIbKeiuKII0PnpQclDrmQrzSXcQWPT57tkPg17Q9WamFUUaHeN3+pVGtMyjYekRaAoRlV+a1gD111kXMPhiaFTMIncoRBS/gYN8FjfekH+ezqbLHLB8DLJQBZEGUILvJjAHX0722XyqYtkn1qfv63nPRGw/qqAW1072Gchq4ZS4ZPQ89SrK4KcHt/XptSlztXMWtmRFQriHdvbjr1Fx7ZwXdTQ+ik2AUZLMdhMrQe6/1GujQiMD6po81NpYbrjnfd+QF4sUbus4wPQKVNzsctiuzGlWsFexSHP4dAZtKnImJhVDnzZODQy0nSafedlr5g4VR36vgm0YPWjSyRNnC/APHyw0DtHIrzTqfKuDeGv80uMPbEdujrw9gLbK3H8ow42iTicmgPgT3J5j70ZOo4o4FMtpZ/AEQw+VnWpSfw7bkMjufLc29XHbtp22wfgq2Lmarr3+psaHokFaQrImkMbzdSL9CdabkLptanAilLScvq8UaKVC+G1+vHDgaweq3BhXD5+YcJnJlp4msUqqxGYlnx4RSvv8PipMU2DsVFbNJSH5NJuS7GuzplNg+f20ysCAwEAAQ==
Validating Signature

result = pass
Details: 

SPF Information:

SPF Information:

Using this information that I obtained from the headers

Helo Address = mx01.nausch.org
From Address = n3rd@sec-mail.guru
From IP      = 217.91.103.190
SPF Record Lookup

Looking up TXT SPF record for sec-mail.guru
Found the following namesevers for sec-mail.guru: ns.udagdns.net ns.udagdns.de
Retrieved this SPF Record: v=spf1 mx ?all (TTL = 3600)
using authoritative server {ns.udagdns.net} directly for SPF Check
Result: pass (Mechanism 'mx' matched)

Result code: pass
Local Explanation: sec-mail.guru: 217.91.103.190 is authorized to use 'n3rd@sec-mail.guru' in 'mfrom' identity (mechanism 'mx' matched)
spf_header = Received-SPF: pass (sec-mail.guru: 217.91.103.190 is authorized to use 'n3rd@sec-mail.guru' in 'mfrom' identity (mechanism 'mx' matched)) receiver=yen; identity=mailfrom; envelope-from="n3rd@sec-mail.guru"; helo=mx01.nausch.org; client-ip=217.91.103.190

SPAM-Scoring:

SpamAssassin Score: -2.001
Message is NOT marked as spam
Points breakdown: 
-0.0 SPF_PASS               SPF: sender matches SPF record
-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%
                            [score: 0.0000]
-0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from author's
                            domain
 0.1 DKIM_SIGNED            Message has a DKIM or DK signature, not necessarily valid
-0.1 DKIM_VALID             Message has at least one valid DKIM or DK signature

Besonderheit - Mailinglisten

Wie am Anfang dieses Artikels beschrieben, basiert DKIM auf asymmetrischer Verschlüsselung. Die eMails werden mit zwei Signaturen versehen, die erste über ein paar Header-Zeilen der Nachricht und die zweite über den Mail-Body, also dem Inhalt einer eMail.

Der empfangende Mail-Server ist nun in der Lage, an Hand des öffentlichen Schlüssels, der im TXT-Record des Domain Name System (DNS) der Domäne abrufbar ist, die beiden übermittelten DKIM-Signaturen zu zu verifizieren. Ist die Signatur ungültig, hat der empfangende MTA1) die Möglichkeit, die Annahme der eMail zu verweigern bzw. die empfangene Nachricht auszusortieren.

Und genau bei diesem Punkt haben wir nun bei unserem Mailinglistenserver unter Umständen ein Problem, da sehr oft das Headerfeld „Subject“ mit dem Namen der Mailingliste ergänzt. So wird aus der SubjectDKIM-Headertest“ auf der Postfixmailingliste ein „[Postfixbuch-users] DKIM-Headertest“. Ebenso wird am Ende der verteilten eMail ein Footer angefügt, mit Hinweisen zur Mailingliste. Bei unserem Beispiel mit der Postfixmailingliste wird folgendes eingefügt:

-- 
_______________________________________________
Postfixbuch-users -- http://www.postfixbuch.de
Heinlein Professional Linux Support GmbH

Postfixbuch-users@listen.jpberlin.de
https://listi.jpberlin.de/mailman/listinfo/postfixbuch-users 

Haben wir uns die Rahmenbedingungen zum DKIM verinnerlicht, werden wir so schnell zu dem Schluß kommen, dass die Überprüfung der DKIM-Signaturen fehlschlagen muß! Damit also die eMails unserer Kunden bei den Mailservern unserer Empfänger nicht mit einem Malus belegt werden, haben wir zwei Möglichkeiten:

  1. eMail nicht verändern: Der Mailheader Subject darf eben so wenig verändert werden, wie der Mailbody nicht durch Anfügen eines Listenspezifischen Footers verändert werden.
  2. DKIM Header entfernen: Soll der Mailheader mit dem [LISTENNAMEN] erweitert und ein listenzpezifischer Footer angefügt werden, dann soll unser AMaViS etwaige DKIM-Signaturen entfernen.


Nachfolgend finden sich daher Hinweise, wie man (s)einen Mailinglistenserver Mailman DKIM-konform konfigurieren und betreiben kann.

eMail nicht verändern

Eine ungültige DKIM-Signatur bekommen wir immer dann, wenn der Mailheader und/oder der Mailbody, also der Nachrichtentext, nach dem Signieren von jemanden manipuliert wurde. Also werden wir nun dafür Sorge tragen, dass der Mailinglistenserver weder den Mail-Header noch den Nachrichtentext manipuliert.

Mit diesen Änderungen bleiben nunmehr die DKIM-Signaturen der eingehenden Nachrichten intakt und somit valide.

DKIM-Signaturen entfernen

Möchte man auf die Listenspezifischen Detailangaben im Subject wie auch am Ende des Nachrichtentextes nicht verzichten, haben wir nur noch die Option, eine etwaige DKIM-Signatur vom Mailinglistenserver entfernen zu lassen. Wir tragen hierzu in die Konfigurationsdatei unseres Mailman-Mailinglistenservers nachfolgende Zeilen ein.

 #  vim /etc/mailman/mm_cfg.py
vim /etc/mailman/mm_cfg.py
...
 
# Django : 2013-02-21
# Vorhandene DKIM-Header entfernen
REMOVE_DKIM_HEADERS = Yes
 
...

Anschließend starten wir unseren Mailinglistenserver einmal durch.

 # service mailman condrestart
Shutting down mailman:                                     [  OK  ]
Starting mailman:                                          [  OK  ]

Besonderheit - DMARC

Möchten wir DMARC bei der Bewertung der anzunehmenden Nachrichten mit berücksichtigen, setzen wir auf das Paket opendkim aus den Repository EPEL ein. Dies hat gegenüber der Signaturprüfung den entscheidenden Vorteil, dass die einzelnen Milter (SPF, DKIM und DMARC) nahtlos ineinander greifen, und so die neu hinzugefügten Haeder bei der Berwertung mit Betrachtet werden können.

Die Installation und Konfiguration von OpenDMARC ist im Kapitel DMARC - Domain-based Message Authentication, Reporting & Conformance beschrieben.

Installation von OpenDKIM

Die Installation gestaltet sich sehr einfach, da wir das EPEL-Paket direkt mit yum installieren können.

 # yum install opendkim

Was bei der Installation alles an Dateien und Verzeichnisse neu im System hinzugefügt worden sind, überprüfen wir mit Hilfe von rpm -qil <paketname>.

 # rpm -qil opendkim
Name        : opendkim
Version     : 2.9.2
Release     : 2.el7
Architecture: x86_64
Install Date: Wed 17 Dec 2014 03:22:40 PM CET
Group       : System Environment/Daemons
Size        : 591007
License     : BSD and Sendmail
Signature   : RSA/SHA256, Fri 08 Aug 2014 01:05:56 AM CEST, Key ID 6a2faea2352c64e5
Source RPM  : opendkim-2.9.2-2.el7.src.rpm
Build Date  : Mon 04 Aug 2014 10:55:31 PM CEST
Build Host  : buildvm-14.phx2.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://opendkim.org/
Summary     : A DomainKeys Identified Mail (DKIM) milter to sign and/or verify mail
Description :
OpenDKIM allows signing and/or verification of email through an open source
library that implements the DKIM service, plus a milter-based filter
application that can plug in to any milter-aware MTA, including sendmail,
Postfix, or any other MTA that supports the milter protocol.
/etc/opendkim
/etc/opendkim.conf
/etc/opendkim/KeyTable
/etc/opendkim/SigningTable
/etc/opendkim/TrustedHosts
/etc/opendkim/keys
/etc/sysconfig/opendkim
/etc/tmpfiles.d/opendkim.conf
/usr/lib/systemd/system/opendkim.service
/usr/sbin/opendkim
/usr/sbin/opendkim-default-keygen
/usr/sbin/opendkim-genkey
/usr/sbin/opendkim-genzone
/usr/sbin/opendkim-reportstats
/usr/sbin/opendkim-testadsp
/usr/sbin/opendkim-testkey
/usr/sbin/opendkim-testmsg
/usr/share/doc/opendkim-2.9.2
/usr/share/doc/opendkim-2.9.2/FEATURES
/usr/share/doc/opendkim-2.9.2/INSTALL
/usr/share/doc/opendkim-2.9.2/KNOWNBUGS
/usr/share/doc/opendkim-2.9.2/LICENSE
/usr/share/doc/opendkim-2.9.2/LICENSE.Sendmail
/usr/share/doc/opendkim-2.9.2/README
/usr/share/doc/opendkim-2.9.2/README.opendkim-reportstats
/usr/share/doc/opendkim-2.9.2/RELEASE_NOTES
/usr/share/doc/opendkim-2.9.2/RELEASE_NOTES.Sendmail
/usr/share/doc/opendkim-2.9.2/authheaders-check-setup-hook.lua
/usr/share/doc/opendkim-2.9.2/convert_keylist.sh
/usr/share/doc/opendkim-2.9.2/final.lua.sample
/usr/share/doc/opendkim-2.9.2/opendkim.conf.sample
/usr/share/doc/opendkim-2.9.2/opendkim.conf.simple
/usr/share/doc/opendkim-2.9.2/opendkim.conf.simple-verify
/usr/share/doc/opendkim-2.9.2/screen.lua.sample
/usr/share/doc/opendkim-2.9.2/setup.lua.sample
/usr/share/man/man5/opendkim.conf.5.gz
/usr/share/man/man8/opendkim-genkey.8.gz
/usr/share/man/man8/opendkim-genzone.8.gz
/usr/share/man/man8/opendkim-testadsp.8.gz
/usr/share/man/man8/opendkim-testkey.8.gz
/usr/share/man/man8/opendkim-testmsg.8.gz
/usr/share/man/man8/opendkim.8.gz
/var/run/opendkim
/var/spool/opendkim

Konfiguration

Die Konfiguration von OpenDKIM ist nicht sehr aufwändig, da wir lediglich das Modul verify benötigen. Das Signieren der eMails überlassen wir AMaViS. Die Konfiguration hierzu findet sich im Abschnitt Generierung von DKIM-Signaturen.

 # vim /etc/opendkim.conf
/etc/opendkim.conf
## BASIC OPENDKIM CONFIGURATION FILE
## See opendkim.conf(5) or /usr/share/doc/opendkim-2.9.2/opendkim.conf.sample for more
 
## BEFORE running OpenDKIM you must:
 
## - make your MTA (Postfix, Sendmail, etc.) aware of OpenDKIM
## - generate keys for your domain (if signing)
## - edit your DNS records to publish your public keys (if signing)
 
## See /usr/share/doc/opendkim-2.9.2/INSTALL for detailed instructions.
 
## CONFIGURATION OPTIONS
 
# Specifies the path to the process ID file.
PidFile /var/run/opendkim/opendkim.pid
 
# Selects operating modes. Valid modes are s (sign) and v (verify). Default is v.
# Must be changed to s (sign only) or sv (sign and verify) in order to sign outgoing
# messages.
Mode    v
 
# Log activity to the system log.
Syslog  yes
 
# Log additional entries indicating successful signing or verification of messages.
SyslogSuccess   yes
 
# If logging is enabled, include detailed logging about why or why not a message was
# signed or verified. This causes an increase in the amount of log data generated
# for each message, so set this to No (or comment it out) if it gets too noisy.
LogWhy  yes
 
# Attempt to become the specified user before starting operations.
UserID  opendkim:opendkim
 
# Create a socket through which your MTA can communicate.
Socket  inet:8891@localhost
 
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
Umask   002
 
# This specifies a text file in which to store DKIM transaction statistics.
# OpenDKIM must be manually compiled with --enable-stats to enable this feature.
#Statistics     /var/spool/opendkim/stats.dat
 
## SIGNING OPTIONS
 
# Selects the canonicalization method(s) to be used when signing messages.
# Django : 2014-12-17
# default: Canonicalization        relaxed/relaxed
Canonicalization        relaxed/simple
 
# Domain(s) whose mail should be signed by this filter. Mail from other domains will
# be verified rather than being signed. Uncomment and use your domain name.
# This parameter is not required if a SigningTable is in use.
#Domain example.com
 
# Defines the name of the selector to be used when signing messages.
# Django : 2014-12-17
# default: Selector        default
# Selector      default
 
# Specifies the minimum number of key bits for acceptable keys and signatures.
# Django : 2014-12-17
# default: MinimumKeyBits 1024
# MinimumKeyBits 1024
 
# Gives the location of a private key to be used for signing ALL messages. This
# directive is ignored if KeyTable is enabled.
# Django : 2014-12-17
# default: KeyFile /etc/opendkim/keys/default.private
#KeyFile        /etc/opendkim/keys/default.private
 
# Gives the location of a file mapping key names to signing keys. In simple terms,
# this tells OpenDKIM where to find your keys. If present, overrides any KeyFile
# directive in the configuration file. Requires SigningTable be enabled.
#KeyTable       /etc/opendkim/KeyTable
 
# Defines a table used to select one or more signatures to apply to a message based
# on the address found in the From: header field. In simple terms, this tells
# OpenDKIM how to use your keys. Requires KeyTable be enabled.
#SigningTable   refile:/etc/opendkim/SigningTable
 
# Identifies a set of "external" hosts that may send mail through the server as one
# of the signing domains without credentials as such.
#ExternalIgnoreList     refile:/etc/opendkim/TrustedHosts
 
# Identifies a set "internal" hosts whose mail should be signed rather than verified.
#InternalHosts  refile:/etc/opendkim/TrustedHosts
# Django : 2014-12-17
# default: unset
InternalHosts  refile:/etc/opendkim/TrustedHosts

Unsere eigenen internen Hosts tragen wir in der Konfigurationsdatei /etc/opendkim/TrustedHosts ein.

 # vim /etc/opendkim/TrustedHosts
/etc/opendkim/TustedHosts
# OPENDKIM TRUSTED HOSTS
# To use this file, uncomment the #ExternalIgnoreList and/or the #InternalHosts
# option in /etc/opendkim.conf then restart OpenDKIM. Additional hosts
# may be added on separate lines (IP addresses, hostnames, or CIDR ranges).
# The localhost IP (127.0.0.1) should always be the first entry in this file.
127.0.0.1
#host.example.com
#192.168.1.0/24
 
# Django : 2014-12-17 - internes Netz eingetragen
# default: unset
10.0.0.0/24

Wie schon auch bei der Konfiguration vom SPF-Milter definieren wir hier einen Port, an dem der Postfix-Daemon später den DKIM-Milter erreichen wird.

In der Konfigurationsdatei main.cf unseres Postfix-Mailserver tragen wir dazu in der Section MILTER nachfolgende Zeilen ein.

 # vim /etc/postfix/main.cf
/etc/postfix/main.cf
...
 
################################################################################
## MILTER
# Django : 2014-11-18
# DMARC Test
#spf_milter       = inet:127.0.0.1:8890
opendkim_milter  = inet:127.0.0.1:8891
#opendmarc_milter = inet:127.0.0.1:8892
amavisd_milter   = inet:10.0.0.67:8899
...

In der Konfigurationsdatei /etc/postfix/master.cf legen wir nun fest, dass bei der Annahme auf Port 25 unser gerade definierte smf-spf-milter verwendet werden soll.

 # vim /etc/postfix/master.cf
...

smtp      inet  n       -       n       -       1       postscreen
smtpd     pass  -       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=no
  -o smtpd_milters=${opendkim_milter},${amavisd_milter}
dnsblog   unix  -       -       n       -       0       dnsblog
tlsproxy  unix  -       -       n       -       0       tlspr

Bei unserem AMaViS-Host passen wir nun noch die Konfiguration an. Da wir die DKIM-Verifizierung mit Hilfe des opendkim-Milters vornehmen, können wir diese Funktion beim AMaViS-Daemon abschalten. Hierzu ändern wir die Option enable_dkim_verification.

 # vim /etc/amavisd/amavisd.conf
...
 
################################################################################
## DKIM - Domain Key Identified Mail
#
 
# DKIM-Signaturen verifizieren
# Django : 2014-12-17
# DKIM-Verifizierung mit Hilfe des opendkim-Milters vornehmen
# old    : $enable_dkim_verification = 1;
$enable_dkim_verification = 0;
 
# DKIM-Signaturen erstellen
$enable_dkim_signing = 0;
 
...

Anschließend aktivieren wir diese Änderung am AMaViS-Daemon.

 # systemctl restart amavisd

Programmstart

Das Starten des Daemon erfolgt über folgenden Aufruf.

 # systemctl start opendkim

Den erfolgreichen Start bzw. den Status des smf-spf-Daemon können wir bei Bedarf mit folgendem Aufruf abfragen.

 # systemctl status opendkim
opendkim.service - DomainKeys Identified Mail (DKIM) Milter
   Loaded: loaded (/usr/lib/systemd/system/opendkim.service; enabled)
   Active: active (running) since Wed 2014-12-17 16:00:28 CET; 5s ago
     Docs: man:opendkim(8)
           man:opendkim.conf(5)
           man:opendkim-genkey(8)
           man:opendkim-genzone(8)
           man:opendkim-testadsp(8)
           man:opendkim-testkey
           http://www.opendkim.org/docs.html
  Process: 19548 ExecStart=/usr/sbin/opendkim $OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 19549 (opendkim)
   CGroup: /system.slice/opendkim.service
           └─19549 /usr/sbin/opendkim -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid

Dec 17 16:00:28 vml000087.dmz.nausch.org opendkim[19549]: OpenDKIM Filter v2.9.2 starting (args: -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid)
Dec 17 16:00:28 vml000087.dmz.nausch.org systemd[1]: Started DomainKeys Identified Mail (DKIM) Milter.

Im Syslog wird der Start des Daemon entsprechend dokumentiert

 # less /var/log/messages
Dec 17 16:00:28 vml000087 systemd: Starting DomainKeys Identified Mail (DKIM) Milter...
Dec 17 16:00:28 vml000087 systemd: Started DomainKeys Identified Mail (DKIM) Milter.
Dec 17 16:01:01 vml000087 systemd: Created slice user-0.slice.
Dec 17 16:01:01 vml000087 systemd: Starting Session 151 of user root.
Dec 17 16:01:01 vml000087 systemd: Started Session 151 of user root.

Mit Hilfe von netstat können wir überprüfen, ob der Port 8891 geöffnet wurde.

 # netstat -tulpen
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode      PID/Program name    
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      0          114172     19358/master        
tcp        0      0 127.0.0.1:8890          0.0.0.0:*               LISTEN      993        112487     19141/smf-spf       
tcp        0      0 127.0.0.1:8891          0.0.0.0:*               LISTEN      991        117881     19642/opendkim

Gleiches können wir natürlich auch mit dem Befehl lsof erreichen

 # lsof -i:8891
 COMMAND    PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
 opendkim 19642 opendkim    3u  IPv4 117881      0t0  TCP localhost:ddi-tcp-4 (LISTEN)

Damit der Daemon automatisch beim Hochfahren des Servers gestartet wird, nutzen wir folgenden Aufruf.

 # systemctl enable opendkim.service
 ln -s '/usr/lib/systemd/system/opendkim.service' '/etc/systemd/system/multi-user.target.wants/opendkim.service'

Wollen wir überprüfen ob der Dienst automatisch startet, verwenden wir folgenden Aufruf.

 # systemctl is-enabled opendkim.service
 enabled

Die Rückmeldung enabled zeigt an, dass der Dienst automatisch startet; ein disabled zeigt entsprechend an, dass der Dienst nicht automatisch startet.

Nachdem wir nun unseren opendkim-Milter erfolgreich installiert und konfiguriert haben, können wir auch unseren Postfix Mailserver durchstarten, damit die Konfigurationsänderungen auf Seiten des MTA auch aktiv werden und Postfix den opendkim-Milter auch ansprechen kann.

Tests und Logging

Wurde die Nachricht unterwegs verändert,so fällt dies bei der Überprüfung der DKIM-Signatur auf und wird entsprechend im maillog vermerkt.

Mar 26 12:52:15 vml000080 opendkim[10943]: D2B6281: s=20120113 d=gmail.com SSL error:04091068:rsa routines:INT_RSA_VERIFY:bad signature

Hingegen wird bei positivem Ergebnis der DKIM-Validierung im maillog vermerkt.

Mar 26 18:02:48 vml000080 opendkim[7535]: CECDB81: message has signatures from googlegroups.com, gmail.com
Mar 26 18:02:48 vml000080 opendkim[7535]: CECDB81: DKIM verification successful

Im Mailheader einer angenommenen eMail finden sich dann entsprechend auch Hinweise zur DKIM-Signaturüberprüfung.

Authentication-Results: mx01.nausch.org; dkim=pass reason="1024-bit key"
header.d=piratenpartei-bayern.de header.i=@piratenpartei-bayern.de
header.b=WFipEQPn; dkim-adsp=pass

Bei negativem Ergebnis wird entsprechend vermerkt.

Authentication-Results: mx01.nausch.org; dkim=fail
reason="verification failed"
header.d=kitterman.com header.i=@kitterman.com header.b=g01pGD3l;
dkim-adsp=none

Links

1)
Mail Transfer Agent
2) , 3)
Author Domain Signing Practices
4)
DomainKeys Identified Mail