Configurazione di DKIM per qmail

Questa pagina riguarda la patch DKIM inclusa nella mia patch combinata (maggiori informazioni qui). Questo argomento è avanzato ed è consigliabile tornare qui alla fine del tutto.

DKIM fornisce un metodo per validare l'identità di un nome a dominio associato a un messaggio con una autenticazione crittografata. La tecnica di validazione è basata sulla crittografia di una chiave pubblica: Il server che invia l'email aggiunge il nome a dominio al messaggio e vi affigge una firma digitale. Questa chiave è posta nell'intestazione DKIM-Signature: del messaggio. Colui che riceve il messaggio può controllare la validità della chiave pubblica leggendo un record TXT del DNS del dominio associato al messaggio.

Sei invitato a dare un'occhiata alle pagine man a partire da qmail-dkim(8) e spawn-filter(8).

Changelog

  • 2017-05-14
    -DKIM patch updated to v. 1.20
    It now manages long TXT records, avoiding the rejection of some hotmail.com messages.
  • 2016-10-09
    Upgraded to v. 1.19: verification will not fail when a dkim signature does not include the subject provided that the   UNSIGNED_SUBJECT environment variable is declared. More info here

Ringraziamenti

Vorrei rivolgere un ringraziamento speciale a Manvendra Bhangui, l'autore della DKIM patch, per avermi assistito con grande cortesia durante tutta la configurazione.

 


I will show how to configure qmail-remote to sign your outgoing messages and qmail-smtpd to verify your incoming messages. Eventually, as an alternative, you can decide to set qmail-smtpd to do both things; this configuration is presented towards the bottom of this page.

In any case you have to create the domainkey signature.

Creazione della firma domainkey per le email in uscita

Le firme vengono create usando una chiave privata presente in un file protetto, e verificate da una chiave pubblica salvata in un record TXT nel DNS per il domino associato all'email.

Prima di poter firmare la posta, è necessario creare almeno una coppia di chiavi pubblica/privata. Si può decidere di creare una coppia di chiavi che valga per tutti i domini presenti nel mail server, oppure di usare una coppia di chiavi per ognuno dei domini.

Prima di tutto scaricare lo script (grazie a Joerg Backschues) che useremo per creare le chiavi e stampare a video il record DNS.

cd /usr/local/bin
wget http://notes.sagredo.eu/sites/notes.sagredo.eu/files/qmail/domainkey
chmod +x domainkey

Creare ora la cartella dove saranno salvate tutte le domainkeys.

mkdir /usr/local/etc/domainkeys

Modalità di utilizzo

Usage: /usr/local/bin/domainkey [-p] domain [selector]
       Create domainkey
       Print domainkey with -p

Lo script può essere usato per creare la chiave o anche per stampare a video la chiave esistente usando l'opzione -p.

Quando si crea una chiave per un dominio.net essa verrà salvata nella cartella /usr/local/etc/domainkeys/dominio.net. La cartella dovrà appartenere all'utente qmailr (l'utente sotto cui viene eseguito qmail-remote), se si opta per firmare i messaggi in uscita a livello qmail-remote, oppure a vpopmail, che è l'utente sotto cui gira qmail-smtpd, se si opta per firmare i messaggi a livello qmail-smtpd. Come opzione predefinita il mio script attribuisce i privilegi a qmailr.

# domainkey dominio.net

Generating RSA private key, 1024 bit long modulus
......................++++++
........++++++
e is 65537 (0x10001)
writing RSA key

TXT record for BIND:
default._domainkey.dominio.net. IN TXT "v=DKIM1\; k=rsa\; t=y\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyzJujXz9EiMat2eDzzLjWuSJ6g4i20FXGluNOmruuCFnVJP1OxurKdt57JZm+6QP2h9IOP0owBMmecXI9qx3CkFrlGSMbJsOEGqXwiTSSttgGmSTPZeNAureyo79spwPc44Ol2ZK2U9gBoDpSQEQdLdtXUreRvs/HyTkzalue2wIDAQAB"

Questo è il record TXT da inserire in un server DNS. Se il tuo Name Server non è bind, google può sicuramente essere d'aiuto.

Configurazione di qmail-remote per la firma e di qmail-smtpd per la verifica dei messaggi

Riferimenti:

rc script

Ecco come modificare il proprio script  /var/qmail/rc affichè qmail-remote firmi in uscita i messaggi:

#!/bin/sh

# Using stdout for logging
# Using control/defaultdelivery from qmail-local to deliver messages by default

exec env - PATH="/var/qmail/bin:$PATH" \
QMAILREMOTE=/var/qmail/bin/spawn-filter  \
FILTERARGS=/var/qmail/bin/dk-filter \
qmail-start "`cat /var/qmail/control/defaultdelivery`"

La variabile QMAILREMOTE fa sì che qmail chiami spawn-filter prima che il messaggio sia collocato in coda, il quale a sua volta eseguirà un filtro a scelta dichiarato attraverso la variabile FILTERARGS. Per un controllo più preciso a livello di singoli domini si può usare il control file filterargs (man spawn-filter). Inoltre si può usare QMAILLOCAL per firmare anche le email spedite agli utenti del vostro server stesso.

dk-filter utilizzerà come come locazione della domainkey il file /var/qmail/control/domainkeys/%/default. Il simbolo '%' verrà automaticamente sostituito con il dominio del mittente. Naturalmente si potrà decidere di firmare tutti domini con un singola firma collocata in /var/qmail/control/domainkeys/default 

Se si ha necessità di salvare la propria chiave altrove, oppure con un nome diverso da default si può definire la variabile DKIMSIGN come segue, ponendo questa riga prima del comando qmail-start

DKIMSIGN=/usr/local/etc/domainkeys/example.net/your_keyname

qmail-smtpd/run script

Inserire le seguenti variabili di ambiente nel vostro script /var/qmail/supervise/qmail-smtpd/run:

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMVERIFY="FGHKLMNOQRTVWjpu"
# This is to avoid verification of outgoing messages
export RELAYCLIENT_NODKIMVERIFY=1

Dichiarando RELAYCLIENT_NODKIMVERIFY si evita che qmail-dkim verifichi i propri messaggi in uscita.

Per scegliere al meglio le opzioni per la verifica dei messaggi leggere la pagina man di qmail-dkim.

Test

Creare un messaggio di test da usare nei test qui sotto (è importante uscire con ctrl+d e che la prima linea non sia vuota):

# cat > /tmp/testmail.txt
To: someone@somewhere.xy
From: postmaster@yourdomain.xy
Subject: DKIM Test Message

Test message FOLLOWING A BLANK LINE

cntrl-D

Test della firma

Faremo il test come qmailr, l'utente che esegue qmail-remote e che ha i privilegi di lettura della domainkey.

# su qmailr                                         
# declare -x QMAILREMOTE=/var/qmail/bin/spawn-filter
# declare -x _SENDER=postmaster@yourdomain.xy
# /var/qmail/bin/dk-filter < /tmp/testmail.txt
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=yourdomain.xy;
        s=default; h=To:From:Subject; bh=lrIChgTwMnmPKfGEgElIyJgL9jk=;
        b=LQPayl6VbbITdGjVC6vx2+bYF27jAjAkR6qm967GMd1L+0hb7szwP9cDfvy738
        Y05llEnOqMrc1QbGGE9uLxqGQrkOAPhl0q+Hxt8yQz1B4BsVk8vED812K/178pIe
        f+4oGrnodNCCJwg97TLXJmVdecGbrmOVPiBfm51kl4nSI=
To: someone@somewhere.xy
From: postmaster@yourdomain.xy
Subject: DKIM Test Tessage

Test message FOLLOWING A BLANK LINE

Mandare un messaggio a sè stessi a guardare la firma DKIM nell'header:

DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
    d=domain.net; s=private; x=1298156019; h=to:from:subject;
    bh=tVrwKZaEzYO4qmI9mPfR04ZvZik=; b=r2VH/6rQdY6xcPjyg55ULnf7U+DEs
    +apecicwvygIZVvQwxU4NqiqAQGTF3Qkft2eBDu42TBzX4nV7FTs8wzn40iGkfhB
    mMZhQdcyOseg7DyOFKUK5D8Ji3ueF/xgYFUnffrxPdZUMpGN9+dA9fY0wkonp5ML
    dDSaNje9mmd34I=

Test della verifica

Assumerò qui che vpopmail sia l'utente che esegue qmail-smtpd.

# su vpopmail
# declare -x DKIMQUEUE=/bin/cat
# unset RELAYCLIENT
# /var/qmail/bin/qmail-dkim < /tmp/testmail.txt
DKIM-Status: no signatures
To: someone@somewhere.net
From: postmaster@yourdomain.xy
Subject: DKIM Test Message

Test message FOLLOWING A BLANK LINE

 

Mandare un messaggio a sè stessi ad esempio da un account gmail.com (che ha la firma DKIM) e controllare l'header. Il messaggio è stato verificato se si ha questa linea nell'header:

DKIM-Status: good

Testare il record DNS

Infine, inviare una mail a check-auth@verifier.port25.com con "test" come oggetto. Vi risponderanno con un messaggio che conterrà i risultati del test e così saprete se la configurazione del vostro  DNS è corretta.

Come far sì che qmail-dkim e simscan vivano insieme felici

[Se simscan non è ancora stato installato si può saltare questo passaggio. qmail non funzionerà con le direttive seguenti senza simscan]

Come certamente saprai, anche simscan ha bisogno di chiamare qmail-queue e deve essere anche lui incluso nella variabile di ambiente QMAILQUEUE, proprio come qmail-dkim. Lo stesso dovrebbe succedere con altri scanner per l'email..

Si può risolvere il problema assegnando qmail-dkim a QMAILQUEUE e simscan alla variabile DKIMQUEUE. In questo caso qmail-dkim chiamerà simscan quando avrà finito il suo lavoro.

Per far ciò è necessario modificare come seguee lo script di avvio di qmail-smtpd /var/qmail/supervise/qmail-smtpd/run (ed eventualmente anche /var/qmail/supervise/qmail-submission/run)

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMQUEUE=/var/qmail/bin/simscan

Configuring qmail-smtpd for signing outgoing messages

You can skip this paragraph if you have already decided to sign ar qmail-remote level.

qmail-smtpd run script

Insert the two following environment variables in your /var/qmail/supervise/qmail-smtpd/run script:

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMKEY=/usr/local/etc/domainkeys/%/default

qmail-dkim will sign your messages if the variable RELAYCLIENT is set (take a look at your tcp.smtp) and will verify all messages from IPs where RELAYCLIENT is not set.

DKIMKEY is the location of the key. The '%' symbol is automatically replaced with the sender's domain. Of course you can decide to sign all your domains with one single signature located in /usr/local/etc/domainkeys/default

Testing

# cat > /tmp/testmail.txt
To: someone@somewhere.xyz
From: postmaster@yourdomain.xyz
Subject: Test Message

Test message FOLLOWING A BLANK LINE THAT YOU DON'T HAVE TO FORGET

cntrl-D

In this test qmail-dkim assumes that the domainkey is stored in the /var/qmail/control/domainkeys folder, so if your domainkeys are stored elsewhere create a symbolic link.

# su vpopmail
# declare -x DKIMQUEUE=/bin/cat
# declare -x DKIMKEY=/var/qmail/control/domainkeys/%/default
# declare -x RELAYCLIENT=""
# /var/qmail/bin/qmail-dkim < /tmp/testmail.txt
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
        d=yourdomain.xyz; s=default; x=1298483339; h=To:From:Subject;
        bh=6rJdFs2WVS8T72i61KhaAvC6O6s=; b=ffnXBB98Gg6iZFEIL6alk8c5davso
        ozyrunXM3C8qaejIrJOwYhnlWQwSdrV599WErmJcDYyMjFjVgLzRQ9OTeYHjEnHT
        X/aiIkvjcxRuOaTK7PcwrcJGdtF0c6LWoK9RgiPctCw7DMcHGmUcSyXWc6ayzHgX
        A7nopQYuHzTuIU=
To: someone@somewhere.xyz
From: postmaster@yourdomain.xyz
Subject: Test Message

Test message FOLLOWING A BLANK LINE THAT YOU DON'T HAVE TO FORGET

Choosing between DKIMSIGN and DKIMKEY

  • man qmail-dkim(8) for more info
Here is the logic behind as explained to me by the author of the patch himself:
  1. If RELAYCLIENT is defined and both DKIMSIGN and DKIMVERIFY are not defined then qmail-dkim looks for DKIMKEY for the private key to sign. If DKIMKEY is not defined, then control/domainkeys/%/default is used

  2. If RELAYCLIENT is not defined, then qmail-dkim uses DKIMSIGN for the key

  3. If RELAYCLIENT is not defined and both DKIMSIGN and DKIMVERIFY is defined, then qmail-dkim ignores DKIMVERIFY
  4. If the key has % in the filename, then it is replaced with the domain name from the From/Sender header. After substituting %, if the private key is not found, the qmail-dkim removes the % and again checks for the key. e.g. strace shows this

    access("control/domainkeys/mydomain.org/default", F_OK) = -1 ENOENT (No such file or directory)
    open("control/domainkeys/default", O_RDONLY|O_NONBLOCK) = 5
  5. If the key has % in the filename and the private key does not exists, then qmail-dkim exits without signing and without any failure. Hence messages will pass through. The reason for this behaviour is i have many clients who run multiple domains on a server and they need DKIM only for few domains.

  6. If the key does not have % sign and the private key does not exist, then qmail-dkim exits with 32 resulting in permanent failure  

    "Private key file does not exist (#5.3.5)"
  7. If none of the variables RELAYCLIENT, DKIMSIGN, DKIMVERIFY are defined, qmail-dkim does verification

 

Commenti

Ottima guida, volevo chiedre come poter cambiare la versione dell'hash di firma per dkim da rsa-sha1 a rsa-sha256 in quanto piu' sicura

Credo che dovresti editare lo script  e settare appositamente openssl, vedi il man. Fammi sapere....