Configuring DKIM for qmail

This note concerns the DKIM patch embedded in my combined patch (more info here). This topic is advanced and you can skip it at the beginning.

DKIM provides a method for validating a domain name identity that is associated with a message through cryptographic authentication. The validation technique is based on public-key cryptography: Responsibility is claimed by the signer by adding a domain name to the message and then also affixing a digital signature of it and the message. The value is placed in the DKIM-Signature: header field. The verifier recovers the signer's public key using the DNS, and then verifies the signature.

You are invited to take a look to the man pages starting from dkim(8) and spawn-filter(8).

Changelog

  • 2016-03-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

Acknowlegments

I would like to address a special thank to Manvendra Bhangui, the author of the DKIM patch, for kindly assisting me during all the configuration.


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.

Creating the domainkey signature for your outgoing emails

Signatures are created using a private key on your system, and verified by a public key stored in the DNS for the email domain.

Before you can sign an email, you must create at least one public/private key pair. You may want to create key pairs for every domain you wish to sign, or use one single signature for all your hosted domains.

First of all download the script (thanks to Joerg Backschues) which we'll use to create the keys and print the DNS record.

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

Now create the folder which will store all the domainkeys.

mkdir /usr/local/etc/domainkeys

Usage

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

The script can create the key or print the existing key if used with the -p option.

When you create a key for a domain.net it will be stored in the /usr/local/etc/domainkeys/domain.net folder. The folder will be owned by qmailr (the user running qmail-remote) if you sign at qmail-remote level or vpopmail, which is the user who runs qmail-smtpd, if you decide to sign at qmail-smtpd level. My script changes the owner to qmailr by default

> domainkey domain.net

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

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

You have to create a TXT record like that in your DNS server. If your Name Server is not bind, google is your friend.

Configuring qmail-remote for signing and qmail-smtpd for verification

References:

rc script

Here is how to modify your /var/qmail/rc script so that qmail-remote will sign your outgoing messages:

#!/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`"

The variable QMAILREMOTE makes qmail to call spawn-filter before the message gets queued, which in turn will execute a filter of your choice declared by FILTERARGS. For individual domain level control it is best using the control file filterargs (man spawn-filter). You can use QMAILLOCAL to sign local deliveries as well.

dk-filter uses /var/qmail/control/domainkeys/%/default as 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 /var/qmail/domainkeys/default.

If you need to store your domainkey elsewhere, define DKIMSIGN as follows (before the last qmail-start command):

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

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 DKIMVERIFY="FGHKLMNOQRTVWjpu"
# This is to avoid verification of outgoing messages
export RELAYCLIENT_NODKIMVERIFY=1

Declaring RELAYCLIENT_NODKIMVERIFY avoids that qmail-dkim will verify outgoing messages.

You are invited to read the qmail-dkim man page in order to choose the best configuration for you.

Testing

Create a test message to be used in the tests below (it's important to exit with ctrl+d and that the first line is not empty):

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

Test message FOLLOWING A BLANK LINE

cntrl-D

Signing test

We'll do the test as qmailr, the user who runs qmail-remote and which owns the 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

Send to yourself a message and look for the DKIM signature in the 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=

verification test

I assume that vpopmail is the user who runs 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

Send a message to yourself from a gmail.com account (which is DKIM signed) and check the header. The message has been verified if you get a header like this:

DKIM-Status: good

Testing the DNS record

Finally, send an email to  check-auth@verifier.port25.com with "test" as subject. They will send you back a reply with the test results and you will know if your DNS configuration is ok.

Making qmail-dkim and simscan live together in peace

[If you didn't install simscan yet skip this and come here later. qmail won't work with this directive without simscan installed.]

As you probably know, also simscan needs to call qmail-queue and must be included in the QMAILQUEUE environment variable, just as qmail-dkim. The same should happen with other qmail scanners.

The work around is to assign qmail-dkim to QMAILQUEUE and assing simscan to the DKIMQUEUE variable. In this case qmail-dkim will call simscan when has finished its work.

You have to modify like this your /var/qmail/supervise/qmail-smtpd/run script (and /var/qmail/supervise/qmail-submission/run as well)

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 at 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=/usr/local/etc/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

 

Comments

Hi

I have a problem with qmail-dkim.
The program mails from RELAYCLIENT signs, but not signed messages sent from other hosts that are not in RELAYCLIENT, and were sent using SMTP-AUTH.

I found the solution to the problem at:
http://qmail.jms1.net/patches/combined-details.shtml

Specifically:
"An example of a patch which needs this functionality, and in fact the initial reason for writing this patch, is the domainkeys patch. In order to verify a signature for an incoming message, it requires that a variable DKVERIFY exist, which contains a list of letters telling which domainkeys results should be considered hard or soft errors. However, in order to sign outgoing messages, it requires that DKVERIFY should NOT exist.

This patch allows me to create an AUTH_SET_DKSIGN environment variable, and when the user AUTH's, it adds a DKSIGN variable to the environment, which forces the qmail-dk program to sign the message instead of verifying it. Without this, the only way to make domainkeys work was to enable it for certain IP addresses in the /etc/tcp/smtp.cdb file, which was no good for clients who used AUTH in order to relay."

Can I count on the fact that a similar mechanism appears in Your patch?

Cheers
:)

Hi Jacekalex,

qmail-dkim will sign your messages if the variable RELAYCLIENT is set and will verify all messages from IPs where RELAYCLIENT is not set (but only if you set DKVERIFY). So this is exactly how it should work.

The mechanism of the patch included in the John Simpson's combined patch is different from the one of the DKIM patch authored by Manvendra Bangui and embedded in my big one, as the signing is not triggered by the authentication here.

For any further info and/or troubleshooting do not hesitate to contact me in private, in you like.

Cheers


Edit:

I assume, if you are using my patch, that you have

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

in your supervise/qmail-submission/run script as well

Concerning the signing after the smtp-auth, it's not clear to me what you mean by "sent by hosts that are not in RELAYCLIENT". Infact, once authenticated, the sender has the IP of the server, so if 127.0.0.1 has RELAYCLIENT it is going to sign the email..

Hi

 

I have a different, simpler idea.

Why qmail-dkim should check and parse RELAYCLIENT 5 or ~ 20 different IP addresses, since exactly the same thing does qmail-smtpd?

I have 2 questions:
I'm not a C programmer, all my experience, this short script in the shell or perl.
Where - where in the qmail-smtpd.c, and in what form (int, void, other), add a piece of code:

if ((flagauth = 1) | | RELAYCLIENT) (env_put2 ("SIGNMAIL", 1));
else (env_put2 ("SIGNMAIL", 0));
return;

 

Why this code?
Depending on the AUTH ||  RELAYCLIENT,  SIGNMAIL variable will have value 1 or 0

Then in the qmail-dkim going to remove a function

* Revision 1.14 2009-03-31 08:21:58 +05:30 Cprogrammer
* When set dkimsign RELAYCLIENT is defined dkimsign When Both are undefined and dkimverify

and give their own in the shape similar to:

if AUTH then dkimsign;
if RELAYCLIENT then dkimsign;
else dkimverify

A precisely if $SIGNMAIL = 1 then dkimsign else dkimverify.

In my opinion a much simpler solution, and certainly feasible.

Any suggestions very welcome.

 

Cheers ;)

thanks for the contribution, Jacekalex. Unfortunately I've never inspected the code of the DKIM patch. You may want to refer to the author

Why qmail-dkim should check and parse RELAYCLIENT 5 or ~ 20 different IP addresses, since exactly the same thing does qmail-smtpd?

Concerning the first part of your question, you can include just the 127.0.0.1 which counts for all the IPs which do the smtp-auth and use subnets..

cheers

Just stumbled upon this post. The thread is long and I will read all the posts when I get time.

Hey Jacekalex, I double checked my configuration and inside my tcp.submission I simply have:

:allow

and my outgoing emails from submission port 587 are signed. No need to put RELAYCLIENT if the client is authenticated.

I don't have the time to study qmail-dkim.c to see where it happens, but the program proves to act as you like.. :-)

Thanks

For me I do not want at this moment to sign mail with the authorization of the hosts! RELAYCLIENT, try again to compile the entire qmail, if this does not help, then he'll write a function to the Qmail-scanner, which will sign a check and mails, if need be, then I'll be able to sign up to create a rule in the sql;)
I'm not a C programmer, but in Perl I can cope quite well, and such a function to check or signing with the use of / var / qmail / bin / dkimtest - these are just a few (maybe several) lines of fairly simple code in qmail-scanner, and a little in qmail . c (qq error status).

Cheers
;)

Jacekalex ,

you could do the following. Write a dkim shell wrapper as below

#!/bin/sh
if [ "$AUTH_SET_DKSIGN" != "" ] ; then
DKIMSIGN="whatever you want it to be"
fi
exec /var/qmail/bin/qmail-dkim

and have the above shell script defined in QMAILQUEUE instead of qmail-dkim

I had tried to use verifier-feedback@port25.com to check, it came with a neutral result.

DomainKeys check details:
----------------------------------------------------------
Result:         neutral (message not signed)

In my named.conf i had also added the TXT record

default._domainkey.domain.com. IN TXT "v=DKIM1\; k=rsa\; t=y\; o=-; p=MIGfMA0GCSqG..........................."

dig default._domainkey.domain.com TXT
default._domainkey.domain.com. 86400 IN TXT "v=DKIM1\; k=rsa\; t=y\; o=-\; p=MIGfMA0GCSqG..........................."

My run file i have

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMQUEUE=/var/qmail/bin/simscan
export DKIMKEY=/var/qmail/control/domainkeys/%/default
export DKIMVERIFY="DEGIJKfh"

In /var/qmail/control/domainkeys/domain.com folder i have

default -> /var/qmail/control/domainkeys/domain.com/rsa.private_default
rsa.private_default
rsa.public_default
selector

Am I missing out anything?

Thanks
Nic

Nick, the config seems ok. Did you remember to set the variable RELAYCLIENT in your tcp.smtp?

Thanks for your reply.

I have

127.:allow,RELAYCLIENT=""
:allow,CHKUSER_WRONGRCPTLIMIT="3",QMAILQUEUE="/var/qmail/bin/qmail-dkim"

regards
nic

Apparently your config is ok.. are you sure that your loopback IP is working? Try to assing RELAYCLIENT to your LAN and to your public IP as well.

In addition, but that's not so important, you have already exported QMAILQUEUE in your run file, so declaring it in the last line is redundant.

Many thanks again.

This box has only a public IP.

Do i replace 127 with my public IP to do testing?
127.:allow,RELAYCLIENT=""

I had also removed QMAILQUEUE

No, just to add add one more line like this:

127.:allow,RELAYCLIENT=""
123.456.789.123:allow,RELAYCLIENT="" (LAN Address)
11.11.11.11:allow,RELAYCLIENT="" (public IP)
:allow ...................... (others)

This will work in case  your loopback is not working (just a guess)

Thanks roberto.

I had done what you had sugguested. But it is still not working

Thanks
nic

What the tests from the command line say? Did you check the priviledges of the domain key? I everything is ok I would try to debug with strace. That will show everything

Hi,

The tests are identical to your tutorial.

/var/qmail/bin/qmail-dkim < /tmp/testmail.txt
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
        d=domain.com; s=default; x=1373469291; h=To:From:Subject;
        bh=WwQSWknnZ1oltdz9LF0JNbJjHdQ=; b=yg0/TKU/xOJ1lmmLZ1NU538rIH/Ri
        Zbyv4h41Vpa8dQhR7YL28uEpl0egvzGBsUL4FnI0QkK1KgXiaaNRdfb0YKCwbk2C
        PcH0rMWZHyG5a4eFeIsLsOguUGefQLs5iiw5zwk63w8uU8muudJMeoB8LC5NHQQL
        Rd+6M03M2cghl8=
To: postmaster@domain.com
From: postmaster@domain.com
Subject: Test Message

/var/qmail/bin/qmail-dkim < /tmp/testmail.txt
DKIM-Status: no signatures
To: postmaster@domain.com
From: postmaster@domain.com
Subject: Test Message

ls -la /var/qmail/control/
drwx------  3 vpopmail vchkpw 4096 May 10 14:46 domainkeys

How do i use strace to debug?

Thanks
nic

Tests from the command line are ok. It must be a tcp.smtp/QMAILQUEUE issue..

You can save the strace log in this way:

strace -Ff -o /tmp/test.log -p <pid_of_tcpserver>

But do not post the log as a comment, because it will be very long. Feel free to contact me in private instead

Thanks.

Am i right to strace /usr/local/bin/tcpserver -v -H -R -l 0 -x /home/vpopmail/etc/tcp.smtp.cdb ?

regards

nic

No, simply the process id of qmai-smtpd

Hi

I had strace pid 994 which is running the process  "supervise qmail-smtpd"
I tried sending out an email to gmail. Received the email but nothing is logged.

994   restart_syscall(<... resuming interrupted call ...> <unfinished ...>

Many thanks again
nic

Actually you have to strace the tcpserver process_id which belongs to qmail-smtpd..

Ok.

Nothing is logged. Send out a few mails to gmail account and the log shows

27792 accept(3,

regards
nic

18008 ?        S      0:00  |   \_ supervise qmail-smtpd                                                                                                                                      
26888 ?        S      0:00  |   |   \_ /usr/local/bin/tcpserver -v -H -R -l 0 -x /home/vpopmail/etc/tcp.smtp.cdb -c 20 -u 89 -g 89 0 25 /usr/local/bin/rblsmtpd -w 30 -r zen.spamhaus.org -r b

root@qmail:/# strace -Ff -o /tmp/test.log -p 26888

Also remember that you have to wait for the greetdelay, so don't stop strace immediately..

Nothing at all.. Weird. Outgoing is not stracable? But incoming does. I had send out 5 test mails to gmail and make sure they are delivered before stopping the strace.

19151 ?        S      0:00 /usr/local/bin/tcpserver -v -H -R -l 0 -x /home/vpopmail/etc/tcp.smtp.cdb -c 20 -u 89 -g 89 0 smtp /usr/local/bin/rblsmtpd -t 300 -b -r psbl.surriel.com /var/qmail/bin/qmail-smtpd /home/vpopmail/bin/vchkpw /bin/true

The log reads 19151 accept(3,

regards

you have a 300s timeout in the rblsmtpd..

Ok.

I remove all other additional.

23694 ?        S      0:00 /usr/local/bin/tcpserver -v -H -R -l 0 -x /home/vpopmail/etc/tcp.smtp.cdb -c 20 -u 89 -g 89 0 smtp /var/qmail/bin/qmail-smtpd /home/vpopmail/bin/vchkpw /bin/true

This time round, i sent out 5 test mails each to yahoo and gmail and made sure all 10 mails are received before checking the log

log file reads
23694 accept(3,

If outgoing is not logging, will incoming log helps in my case?

regards
nic

and how you are using strace? I mean which process id?

PS Nic, can we continue this conversation as a private msg? This thread is going to be so long...

Hi Roberto,
 
I am getting alot of the errors below. Seems like the receiving mail server cannot verify the DKIM of the incoming email. Is it right to say that? What can i do to allow this coming email?

 message delayed (qmail-dkim: DKIMContext structure invalid for this operation (#4.3.0)): investigations@FBI.GOV from 194.50.9.6
 
 Thanks
 nic

what do you have in your DKIMVERIFY?

export DKIMVERIFY="DEGIJKfh"

I don't know exactly what is causing the error and I'm not sure that it's a regular rejection.

To make tests we need a raw message like that, but in this case you should temporarily disable the verification. Send me it in private if you like

Hello,

First let me thank you for the excellent write up on the qmail installation guide.

I am having a problem where sending mail to only certain users on my mail server are being rejected with the following error:

451 qmail-dkim: DKIMContext structure invalid for this operation (#4.3.0)

The mails are being sent from a ticketing system and the problem started to occur recently.

Regards,

ss

found the solution to the problem, was an issue with the ticketing system

please discard previous comment

thanks

Hi,

I have the following error and would need to receive these e mails.

Jun  5 18:07:09 mail spamdyke[10900]: DENIED_OTHER from: XXXX@undelivered.ovh.net to: ME_MAIL origin_ip: 178.32.228.195 origin_rdns: mo195.mail-out.ovh.net auth: (unknown) encryption: (none) reason: 554_qmail-dkim:_signature_error:_permanent_dns_failure_requesting_selector_(#5.7.0)

Is there any way to include a whitelist domains?

Thanksss :)

unfortunately there's no whitelist functionality in the dkim program. The error suggests a permanent dns error

Hi Roberto,

You should probably make all examples consistent with the default key locations.

In your /var/qmail/rc example script, you have:

DKIMSIGN=/var/qmail/control/domainkeys/%/default

But this should instead be:

DKIMKEY=/usr/local/etc/domainkeys/%/default

Same with the Signing test example.

Or as an alternative, point out to the reader that the keys are generated in one path but the script examples assume they have been copied to another path.

I think this is probably what went wrong for the reader who couldn't get his signing to work.

Regards

/ Otto

Hi Otto, thanks for your contribution.

Corrected. Of course it was a not wanted error and there will surely be other :)

Hello,

after using your guide to install simscan i am a little bit confused about the config of the qmail-smtpd/run and qmail-submission/run scripts. Before Simscan installation you wrote in the DKIM tutorial:

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

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMVERIFY="FGHKLMNOQRTVWjpu"

In the description Making qmail-dkim and simscan live together you wrote:

You have to modify like this your /var/qmail/supervise/qmail-smtpd/run script (and /var/qmail/supervise/qmail-submission/run as well)

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

The question is, why i have to add in the simscan configuration the parameter export DKIMKEY=/usr/local/etc/domainkeys/%/default. I thougt this was covered with the /var/qmail/rc script. Maybe i miss something in my understanding of the how the things work together.

And another question: The export parameters in the qmail-submission/run script should match with all the Export settings in the qmail-submission/run script?

Thanks for helping.
cheers

Hi Marc, thanks for your contribution.

You can do in both ways. That was the old method, when the signing had to be done at qmail-smtpd level with all the variables declared in the qmail-smtpd run file. But now I'm signing at qmail-remote level, so the variables have to be declared in the rc file.

I'm going to correct this. Thank you

even with set QMAILLOCAL to /var/qmail/bin/spawn-filter   in /var/qmail/rc , I can not sign local mails.

and if I set QMAILQUEUE=/var/qmail/bin/qmail-dkim I received "qq temporary problem (#4.3.0)" when sending local mails.

/var/qmail/rc :

exec env - PATH="/var/qmail/bin:$PATH" \
QMAILREMOTE=/var/qmail/bin/spawn-filter  \
QMAILLOCAL=/var/qmail/bin/spawn-filter  \
DKIMKEY=/usr/local/etc/domainkeys/%/default \
FILTERARGS=/var/qmail/bin/dk-filter \
qmail-start "`cat /var/qmail/control/defaultdelivery`"

qmail-smtpd/run

...
export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMVERIFY="FGHKLMNOQRTVWjpu"
#export RELAYCLIENT_NODKIMVERIFY=1
...

/var/qmail/control/defaultdelivery

| /home/vpopmail/bin/vdelivermail '' bounce-no-mailbox

It's strange... your config seems to be correct, but there's no need of declaring QMAILLOCAL to have local mails signed.

Have you done the tests suggested toward the bottom of this page? If yes you should try to debug with strace

Thanks for your reply :-)

I found the problem was permission of private key that root user ( owner of qmail-lspawn ) can not read that file.

now my local mails is somethins like this :

 ( when DKIMVERIFY="FGHKLMNOQRTVWjpu" is set )

Return-Path: <behnam@example.com>
Delivered-To: example.com-postmaster@example.com
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com;
        s=default; h=DKIM-Status:MIME-Version:Content-Type:
        Content-Transfer-Encoding:Date:From:To:Subject:Message-ID:
        User-Agent; bh=SSDFuMUWjUihK52L1yEyQKqsfM=; b=JkjuEmSVhW6IBTj2W
        DkVA+sKtbrFaasdSEO2yLsVEisCZ01KL3I5kQmypl06is6F42bQ+64d+vlNxdwSb
        eg7AH6yoVWO+h57F6iBKKDSJIEKSLAOWKSOras5Mlqvy9zDVECzvzZUlotSd7PfF
        ctDc9PGdO4EEm4WehmZNsSVRPw=
DomainKey-Signature: a=rsa-sha1; q=dns; c=simple;
  s=default; d=example.com;
  b=XVH2sA9Tj1TQY6is9i4e7NpHNyjYcuKhaJ58Hl2O5UHUPX9yqVq62RailJgCgZVWEIeAX1M2TPT/b2CKqqTGJjQEOQwr8TC7HJKDxQYUEWgNe4jiu6lvU7o9se8HcOT5XbnSKFgMqXwfwIOQNoitt+SqKtlGHFpy9PIk3UvoffY=;
Received: (qmail 50945 invoked by uid 89); 26 Dec 2014 15:00:23 +0000
Received: by simscan 1.4.0 ppid: 50912, pid: 50916, t: 3.7977s
         scanners: attach: 1.4.0 clamav: 0.98.5/m:55/d:19840 spam: 3.4.0
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.example.com
X-Spam-Level:
X-Spam-Status: No, score=-1.0 required=4.5 tests=ALL_TRUSTED,AWL,
        TVD_SPACE_RATIO autolearn=ham autolearn_force=no version=3.4.0
DKIM-Status: no signatures
Received: from unknown (HELO mail.example.com) (behnam@example.com)

 ( when DKIMVERIFY="FGHKLMNOQRTVWjpu" is not set )

Return-Path: <example@example.com>
Delivered-To: example.com-postmaster@example.com
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com;
        s=default; h=MIME-Version:Content-Type:Content-Transfer-Encoding:
        Date:From:To:Subject:Message-ID:User-Agent; bh=+Y1O6gkU5mqhqyI0b
        Y/c1ISV2qA=; b=psfLDKIRmdkdlW<fkespHN/srbgZuUXSOb8l0wI2zgpWsj1SZ
        ewrk3r3KJDIEMF3K/2xCfRnpJGCxVJuyiLehLXwrEWZ/Rc2h4enbtP6qOp4gGOt/
        zR/x5kuURD9zq8EUFa94igRHJigKxjkUn2/M3eVR26wn0CJ+HnVd+UAFZQ=
DomainKey-Signature: a=rsa-sha1; q=dns; c=simple;
  s=default; d=example.com;
  nVoQP2iXnFn1yNbbNn/dyWSqoCCF/UlaoimqzTrKi6/RCKSImskeowk83ukwjsuje83jswoqke8w839skwikbfVcDucbnpf5DFZHp7eZRGQEzwXBsNOg=;
Received: (qmail 49537 invoked by uid 89); 26 Dec 2014 14:55:12 +0000
Received: by simscan 1.4.0 ppid: 49511, pid: 49515, t: 22.2933s
         scanners: attach: 1.4.0 clamav: 0.98.5/m:55/d:19840 spam: 3.4.0
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.example.com
X-Spam-Level:
X-Spam-Status: No, score=-1.0 required=4.5 tests=ALL_TRUSTED,AWL,DKIM_SIGNED,
        DKIM_VALID,DKIM_VALID_AU autolearn=ham autolearn_force=no version=3.4.0
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com;
        s=default; x=1420197890; h=MIME-Version:Content-Type:
        Content-Transfer-Encoding:Date:From:To:Subject:Message-ID:
        User-Agent; bh=+Y1O6gkU5mqhqyI0bY/c1ISV2qA=; b=Cm4zaswMi5MPTBgr8
        SKIEMSnhsmdkwKDjUKDjKSJDKiPKAKWiJSUEKSMAhNAQQBMXikssoaMKS4zas3wd
        M8Lupl4uNZTGe17U8WP8xLm9BEpjUfhJ4kQ1aCiehbKl3+zo+h04cfc4AEpDn1gs
        avWNu9ZYlUKRW4kyPp8f+yR6yA=
Received: from unknown (HELO mail.example.com) (behnam@example.com)
  by 0 with ESMTPA; 26 Dec 2014 14:54:50 +0000

and I hadn't any DKIM-Status in the second mail 

can you post your smtpd run file, or at least confirm that DKIMVERIFY and DKIMSIGN are NOT both defined there?

sorry, I see now that the verification is done, but for an unknown reason the sign is not matched into the message...

The DKIM verification inside the X-Spam-Status field has nothing to do with the qmail patch, as it's written by spamassassin. So you have to declare DKIMVERIFY

Hi

I have some questions

Do you know any solution or patch to add Authentication-Results header for dkim and spf to your combind patch?

how can I sign and verify my local mails?

when I set QMAILLOCAL and set the proper permission to private key and public key, I can sucssesfuly sign local mails but I can not verify that mails and it has DKIM-Status: no signatures ( I comment "export RELAYCLIENT_NODKIMVERIFY=1" to verify local mails ).

Thanks

Behnam

I don't know of any patch to write dkim and/or spf results into that field, but you can see their response in "DKIM-status" and "Received-SPF" respectively.

Hi Roberto,

I remembered when i was still using Bill's toaster, i have a log of wrong password logins. Is this log available in your version?

It was in /var/log/maillog in Bill's version.

Thanks

nic

yes it is /var/log/maillog

Many thanks =)

Dear Roberto,

I had just recieved an error "qmail-dkim: signature error: permanent dns failure requesting selector (#5.7.0)" from a remote domain. That domain does not publish any domainkey. My configure is like so

export DKIMVERIFY="FGHIKLMNOQRTVWjpu"

Any idea where i should start to look?

Thanks
nic

Nic, the answer is in the qmail-dkim man page.. you have to relax the filter if you don't want to reject those kind of msg. The Q letter should be lowercase, but I'm not sure that doing so is a good idea..

Hi,

I found that apple.com, for example, use DNS long records that are splitted in TXT chunks. You can try it doing "dig -t txt mailout2048s._domainkey.apple.com" . My qmail-dkim is failing to check this DKIM signature (google.com is working instead).

Is it possible that qmail-dkim module have problems dealing with this kind of DNS records?

I hope Manvendra Bhangui or someone else can address on this issue.

Thank you

Regards,

Marcello

 

Thanks for pointing this out. WIll investigate this during the weekend and come up with a fix in case there is a bug.

qmail-dkim does not have an issue with assembling long text records. e.g.

$ dig -t txt insideapple2048._domainkey.insideapple.apple.com

; <<>> DiG 9.9.6-P1-RedHat-9.9.6-11.P1.fc21 <<>> -t txt insideapple2048._domainkey.insideapple.apple.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49080
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;insideapple2048._domainkey.insideapple.apple.com. IN TXT

;; ANSWER SECTION:
insideapple2048._domainkey.insideapple.apple.com. 8034 IN TXT "v=DKIM1\;" "k=rsa\;" "h=sha1\;" "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoo2sqljdU766Eq9AqRGm" "aGd2YN784ATBBikYAhl9VxY8Ji3xMU4DAyD3QSZGvKpk5qOIG+1GBWxKVRk3jlvp" "TuaAQuGdKPkcgvRTeb31BzAltWwGvtzsLxiLQGUPFzbv81XomOWemC9QCIYWcddr" "v9CD7PDV1K8sV2BTrfIe9iKspcjia1D9wLgzYg1OU99202DHhRTcE6PucxUtXDgh" "za3pu4FTddllhMJ5eeGCk4z2ctZFCe1SRMtRbaLpDV3yET2icAjTV4w8xhEFuC64" "K0auCaYVWS1rldfV4+jt2A/9RmB7jho2H31XbDm9JqCflMKfoQeHCNQwwJGCRxzq" "eQIDAQAB"

;; Query time: 1 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Sun Dec 13 09:24:37 IST 2015
;; MSG SIZE  rcvd: 503

The same result from indimail's dnstxt program (qmail-dkim uses the same function)

$ dnstxt insideapple2048._domainkey.insideapple.apple.com

v=DKIM1;k=rsa;h=sha1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoo2sqljdU766Eq9AqRGmaGd2YN784ATBBikYAhl9VxY8Ji3xMU4DAyD3QSZGvKpk5qOIG+1GBWxKVRk3jlvpTuaAQuGdKPkcgvRTeb31BzAltWwGvtzsLxiLQGUPFzbv81XomOWemC9QCIYWcddrv9CD7PDV1K8sV2BTrfIe9iKspcjia1D9wLgzYg1OU99202DHhRTcE6PucxUtXDghza3pu4FTddllhMJ5eeGCk4z2ctZFCe1SRMtRbaLpDV3yET2icAjTV4w8xhEFuC64K0auCaYVWS1rldfV4+jt2A/9RmB7jho2H31XbDm9JqCflMKfoQeHCNQwwJGCRxzqeQIDAQAB
record length 415

Also all emails from apple.com seems to be getting verified. You can send me a raw text of any one email that is not getting verified so that I can investigate. 

Hi Manvendra,

yes I can send raw text email to you but prefer to do it in a PM.

Can you send me you email or let Roberto to give it to me?

Thank you,

Regards,

Bye

Marcello

 

I have debugged the issue with help of the raw email. There were two issues. The first issue is verifiying if the signature has expired. This is done by using t= and x= tags. Unfortunately, one of the funtions is using an integer variable to compare the timestamps and due to this, the signature is shown as expired. This issue was easy to fix and I have made the changes

The second problem is X-Brightmail-Tracker header inserted below the DKIM-Signature. This causes the signature not to verify. After removing the X-Brightmail-Tracker, I am able to verify the signature as good. This issue can be solved by ignoring headers not present in the h= tag. However, since this part of the code is from ALT-N technologies, I might take some time to add some code to skip such headers. I will get back as soon as possible with a fix. If I cannot find a way to fix this, I can always put a wrapper before calling qmail-dkim to skip headers not present in the h= tag.

I've noticed that Sky UK is sending out legitimate emails including a dkim signature that does NOT include the subject:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skymail.sky.com;
    s=20141008185601; t=1455627787; x=1471352587;
    bh=..........; h=From:Reply-To;

I don't think excluding the subject from the signature is against the spec, even if it is silly. It does, however, fail verification

I've added this option to qmail-dkim.c to relax this restriction:

        if (env_get("UNSIGNED_FROM"))
                vopts.nAllowUnsignedFromHeaders = 1;
        vopts.nSubjectRequired = 1;
        DKIMVerifyInit(&ctxt, &vopts);          /*- this is always successful */

This value ensures it will permit a signature that does not include the subject

It may be worth making this configurable (with an environment variable or a switch to DKIMVERIFY?)

I will ask Manvendra Bhangui to look at your comment. Thank you

I've been running with the patch for a few days. Here are some of the domains that seem to be sending these problem signature:

  • @email.barclaycard.co.uk
  • @b.e.disneyinteractive.com
  • @m.email.sonyentertainmentnetwork.com
  • @b.skymail.sky.com
  • @emea.e.paypal.com

These emails are now being accepted and validated. It looks like a fairly new trend to exclude the subject from the list of headers. I guess paypal is probably the most serious on the list

 

Hi,

even if I installed the latest patch on my system I'm not able to receive password reset email from GitHub.

I created another account on GitHub using a Gmail account and on that account I receive the email correctly.

Can you help me to understand why on my server it is failing?

These are the DKIM headers i receive on Gmail account for the pasword reset email:

Received: from github-smtp2b-ext-cp1-prd.iad.github.net (github-smtp2-ext6.iad.github.net. [192.30.252.197])
        by mx.google.com with ESMTPS id 139si3247415ion.136.2017.03.24.09.52.24
        for <hunters14473@gmail.com>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Fri, 24 Mar 2017 09:52:24 -0700 (PDT)
Received-SPF: pass (google.com: domain of noreply@github.com designates 192.30.252.197 as permitted sender) client-ip=192.30.252.197;
Authentication-Results: mx.google.com;
       dkim=pass (test mode) header.i=@github.com;
       spf=pass (google.com: domain of noreply@github.com designates 192.30.252.197 as permitted sender) smtp.mailfrom=noreply@github.com;
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=github.com
Date: Fri, 24 Mar 2017 09:52:24 -0700
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=github.com;
s=pf2014; t=1490374344;
bh=SMIcRquEv41jyIeUc9eCvSloLz6xCzCOEK8yKIKvhHg=;
h=From:To:Subject:From;
b=mFmuh44xku3V+DMvHmrjdar3DaXkqcbLvZG7FhGDmW5PTKbObbOfdf2lcstEMquq+
  5Jool/dRJERdbTCrhl9ovA2LRGr/5JtLgELbNviqXh/9Ciab4D1lDE+IDE+R3AQvRu
  BPz8JTvYVjEvouFf0ZovoaaS+MLzlja1Ehuxo5no=
From: GitHub <noreply@github.com>
To: hunters144732 <hunters14473@gmail.com>
Message-ID: <58d54ec84991a_2a2bf3ff8981afc2c88634@github-fe-54106a2.cp1-iad.github.net.mail>
Subject: [GitHub] Please reset your password

Thank you

Regards

Marcello

it seems like you don't have the DKIM correctly configured. Did you perform all the tests suggested in this page? Which one eventually failed?

Please post your run file

I had the DKIM working for years and due to this error i was getting i made the update to your latest patch on today but the problem still persist.

I'm able to receive mail from gmail and other DKIM enabled servers but not this one. I was thinking the it can be related to the UNSIGNED_SUBJECT but i seems not to be this the issue.

Here my run file:

QMAILDUID=`id -u vpopmail`
NOFILESGID=`id -g vpopmail`
MAXSMTPD=`cat /var/qmail/control/concurrencyincoming`
LOCAL=`head -1 /var/qmail/control/me`

export SMTPAUTH="-"

export SMTPD_GREETDELAY=15
export DROP_PRE_GREET=1


export CHKUSER_START=ALWAYS

export SURBL=1 # Comment out to enable SURBL filtering
export QMAILQUEUE=/var/qmail/bin/surblqueue # executes surblfilter
export SURBLQUEUE=/var/qmail/bin/qmail-dkim # executes qmail-dkim after sublfilter
export DKIMQUEUE=/var/qmail/bin/qmail-scanner-queue     # qmail-scanner-queue is executed after qmail-dkim
export DKIMVERIFY="FGHIKLMNOQRTUVWjp"

if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" -o -z "$LOCAL" ];
then
    echo QMAILDUID, NOFILESGID, MAXSMTPD, or LOCAL is unset in
    echo /var/qmail/supervise/qmail-smtpd/run
    exit 1
fi

if [ ! -f /var/qmail/control/rcpthosts ]; then
    echo "No /var/qmail/control/rcpthosts!"
    echo "Refusing to start SMTP listener because it'll create an open relay"
    exit 1
fi

exec /usr/local/bin/softlimit -m 100000000 \
    /usr/local/bin/tcpserver -v -R -H -l "$LOCAL" -x /home/vpopmail/etc/tcp.smtp.cdb -c "$MAXSMTPD" \
    -u "$QMAILDUID" -g "$NOFILESGID" 0.0.0.0 smtp \
    /var/qmail/bin/qgreylistrbl.pl /var/qmail/bin/qmail-smtpd /home/vpopmail/bin/vchkpw /bin/true 2>&1

Thank you

Bye

You have the letter 'j' in DKIMVERIFY. So qmail-dkim will not exit with 100. Have QMAILQUEUE changed temporarily  to bypass qmail-dkim and check. If you still do not receive email then it could be something else. If you receive the qmail

export QMAILQUEUE=/var/qmail/bin/qmail-scanner-queue

After making the above change, save the incoming email to /tmp/mail.txt and you can do the following to troubleshoot

cat mail.txt | env - \
DKIMVERIFY="FGHIKLMNOQRTUVWjp" \
DKIMQUEUE=/bin/cat \
/var/qmail/bin/qmail-dkim

What is the value of your DKIMVERIFY envrionment variable?

In DKIMVERIFY have the letter 'j' included in lower case. Once you have the email in your system, you can test it by supplying the raw text on stdin to dkimtest.

Hi Manvendra,

if I disable the DKIM on the system the email is received perfectly.

If i pass the raw email to DKIM on the shell i get no output and the exit code is 53 .

If i make the same with a normal gmail email recevide from the server i get the the complete Email on the output with the DKIM-Status: good Header.

Have you any suggestion?

Thank you

Bye

Marcello

exit code 53 means that qmail-dkim was not able to write to either stdout or stderr. The function die_write() exits with 53. Is it possible to attach the raw email and send it to my private email address? I shoudl be able to debug. I hope there is nothing sensitive in the email.

Hi,

I found the problem. It was a Baesyan filter on a FortiMail system in front of my server that was recognizing that email as SPAM and was altering the Subject. When the email reach my server with the Subject altered it fail the DKIM Check. Now without the Subject altered it works perfectly.

Thank you for your availability and sorry if i make you loose some time.

Bye

Marcello

That's good news.

However I was surrprised when you were getting error code 53. Maybe you were piping the output to less or more.

if you use the following script as cat instead of /bin/cat then the troubleshooting always works

#!/bin/sh
exec 1>/dev/tty
exec /bin/cat

Problem: Marcelo was receiving an email where the content of the email was changed (in particular the Subject header).

This caused qmail-dkim to issue the following error

J - DKIM_SIGNATURE_BAD_BUT_TESTING      - signature error: RSA verify failed but testing

The man page states that DKIMVERIFY should have the letter j for returning temporary error and the letter J for issuing permanent error.

It does not mention that if you omit the letter 'j' or the letter 'J', the email will successfully pass through the queue and get delivered.

So should I modify the qmail-dkim patch for this change in the man page. Most of the dkim verification error results because the message gets modified by some filter before qmail-dkim and you could potentially lose email, like Marcelo.

The troubleshooting test that Marcelo was doing also failed because DKIMVERIFY had the small letter 'j'. If he omits the leter 'j', he should get the output along with the DKIM-Status header. My view is that if you do not want to lose emails and you do not have the habit of looking at the logs for temporary errors, the letters 'j' or 'J' should be completely omitted from DKIMVERIFY

Thank you. It is a simple fix. Will have the environment variable UNSIGNED_SUBJECt and let Robert know the url for the latest patch

Two New patch uploaded to https://sourceforge.net/projects/indimail/files/netqmail-addons/qmail-dkim-1.0/

One which includes spf + ipv6 + dkim

and one which has only dkim

Thank you Manvendra. I have updated my combined patch accordingly

I hope this isn't a stupid question.  I've got qmail signing outgoing email, but they're all using  rsa-sha1.  How can get it to use rsa-sha256?

As I suspected, it was a stupid question.  I checked out my version of openssl and it didn't have sha256 available.  The man page for openssl dgst recommended using SHA1, it was so old.   I'm currently building a newer version from source.

Hi

I'm FreeBSD user, and I don't use netqmail, Is there a way to only implement DKIM patch and not all the others ?

Sorry Pablo, I can't get what you mean.. you say that you don't use netqmail but that is a patch for netqmail...