Configuring DKIM for qmail

by 217 comments

This note concerns the DKIM patch embedded in my combo (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

  • Nov 20, 2023
    * The patch now by default excludes X-Arc-Authentication-Results
    * dkim can additionally use the environment variable EXCLUDE_DKIMSIGN to include colon separated list of headers to be excluded from signing (just like qmail-dkim). If -X option is used with dk-filter, it overrides the value of EXCLUDE_DKIMSIGN.
  • Sep 5, 2023
    -patch upgraded to v. 1.42
    *dk-filter.sh: "source $envfn" has been replaced with ". $envfn" in oder to work for pure bourne shells
    *minor corrections to the man pages
  • Jun 30, 2023
    -patch upgraded to v. 1.41
    *dknewkey will allow domains in control/domainkey
    *Made a few adjustments to the man pages and dkimsign.cpp for DKIMDOMAIN to work with qmail-smtpd (in case some configures qmail-smtpd to sign instead of the usual dk-filter/qmail-remote)
  • Apr 26, 2023
    -dkim patch updated to v. 1.40
    -qmail-dkim uses CUSTOM_ERR_FD as file descriptor for errors (more info here)
  • Mar 18, 2023
    - bugfix in dkimverify.cpp: now it checks if the k= tag is missing (tx Raisa for providing detailed info)
  • Mar 14, 2023
    - The split_str() function in dknewkey was modified in order to work on debian 11 (tx J)
  • Feb 19, 2023 (v. 1.37 upgrade)
    - ed25519 support​ (RFC 8463)
    - multiple signatures/selectors via the enhanced control/dkimkeys or DKIMSIGNDKIMSIGNEXTRADKIMSIGNOPTIONS  DKIMSIGNOPTIONSEXTRA variables
    - domainkey script replaced by dknewkey in order to create ed25519 keys and rsa keys with 1024/2048/4096 bit
    - dropped yahoo's domainkeys support (no longer need the libdomainkeys.a library)
    - man pages revised and enhanced
    - domainkeys directory moved to /var/qmail/control/domainkeys
    - the documentation in this page has been revised. You can find how to sign with the rsa key together with the ed25519 key below.

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 the outgoing messages and qmail-smtpd to verify the 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.

Starting from version 1.37 we'll no longer use the domainkey script to create the domainkey. The dknewkey shipped by the dkim patch itself will be used instead, as it can manage both rsa and ed25519 keys.

Create the folder which will store all the domainkeys and assign write priviledges to qmailr:qmail if you are going to sign at qmail-remote level as suggested here, vpopmail:vchkpw if you are going to sign at qmail-smtpd level. In the latter case you have to adjust the priviledges of the keys files modifing the /var/qmail/bin/dknewkey script.

mkdir /var/qmail/control/domainkeys
chown -R qmailr:qmail /var/qmail/control/domainkeys

dknewkey usage

Usage: dknewkey [options] keyfile 
options 
      [-p | --print]          : print DKIM public keys 
      [-r | --remove]         : remove DKIM keys 
      [-d | --domain domain]  : domain name 
      [-b | --bits   size]    : DKIM private key size 
      [-t | --type   type]    : Key type (RSA or ED25519) 
      [-e | --enforce]        : Key is not in testing 
      [-f]                    : force DKIM private key creation

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

keyfile is the name of the "descriptor", which binds the private/public key pair that we are going to generate; it is also the name of the file which holds the private key, while the public key will be saved to keyfile.pub. The TXT record in the DNS, which holds the public key, is also linked to the chosen descriptor; here is an example:

keyfile._domainkey.domain.tld. IN TXT ("v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArscx1X+i6VEViYZpf9C6Bnd6ME15AxQ5U1T3O7Ts1BS8Z3tZBdda68Lg+wlc5B+FQaozqeoiQsOWReyD8JDwZ5WTxom4/Ey1XJX7jADUZ0oad/F4a7OT96JaiCKAKX8otBXTwWdQZxk0J7lFxiBpZYA38YB+B3BYdig04MZiDvFe5lCeBpOHPCICZfjY")

If not sure about what to choose for the descriptor name, use default as in the example below. If you want to use a descriptor of your choice, or you want to sign with the new ed25519 signature, read below.

When you create a key for domain.tld it will be stored in the /var/qmail/control/domainkeys/domain.tld folder.

# dknewkey -d domain.tld -t rsa -b 2048 default 
Generating rsa DKIM private key keysize=2048, file /var/qmail/control/domainkeys/domain.tld/default 
Generating rsa DKIM public  key for default.domainkey.domain.tld, file /var/qmail/control/domainkeys/domain.tld/default.pub, keysize=2048 
DKIM Private key for domain.tld file /var/qmail/control/domainkeys/domain.tld/default 
-----BEGIN RSA PRIVATE KEY----- 
MIIEpAIBAAKCAQEArscx1X+i6VEViYZpf9C6Bnd6ME15AxQ5U1T3O7Ts1BS8Z3tZ 
Bdda68Lg+wlc5B+FQaozqeoiQsOWReyD8JDwZ5WTxom4/Ey1XJX7jADUZ0oad/F4 
xxxxxxxxxxx very long xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
14SQHokCgYAkIUAHxYjuRkvzatWdEhI1buuBDWl2ZwpHnQSWxUKqeQdwygGAS78s 
ZMbHhuoW2Xt/Jjbwx7t1faA0TsJkER+P0WP61AbwTKA32SVkhc9yhPizdN7WZDjW 
scC2+bToOgxQK/6+1sfHrqXSEPFscwx/dYTlHyUtbLaYnFMJfSw4Cg== 
-----END RSA PRIVATE KEY----- 
-rw-r----- 1 root qmail 1679 Feb 19 13:12 /var/qmail/control/domainkeys/domain.tld/default 
------------------------------------------------------ 
DKIM TXT record for domain.tld with selector=default file /var/qmail/control/domainkeys/domain.tld/default.pub 
default._domainkey.domain.tld. IN TXT ("v=DKIM1; k=rsa; t=y; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArscx1X+i6VEViYZpf9C6Bnd6ME15AxQ5U1T3O7Ts1BS8Z3tZBdda68Lg+wlc5B+FQaozqeoiQsOWReyD8JDwZ5WTxom4/Ey1XJX7jADUZ0oad/F4a7OT96JaiCKAKX8otBXTwWdQZxk0J7lFxiBpZYA38YB+B3BYdig04MZiDvFe5lCeBpOHPCICZfjY"
       "G/rO9K9LRoMwXG3Raz7lY2XLhhnHrNxjXjUKmvSXySeedkZl/TbJbjO4vQ8+bIrTjvReEF4YXBqAIWQ4XIFy04S1SdhOFIp1kIXR7x8kKpc1vrjUsMg6Pth76FttlLGk0J2g5UYXPxrGVP1YyRHTiNTYPQIDAQAB") 
-rw-r--r-- 1 root qmail 461 Feb 19 13:12 /var/qmail/control/domainkeys/domain.tld/default.pub 
------------------------------------------------------

Create a TXT record with the part in bold text above in your DNS server.

If you decide to use the same key for all your domains, you have to use dknewkey with no domain. The key will be saved to /var/qmail/control/domainkeys. The hostname of the server "domain.tld" will be used in the example and you have to replace it with the real domain.

# dknewkey -t rsa -b 1024 default
Generating rsa DKIM private key keysize=1024, file /var/qmail/control/domainkeys/default
Generating rsa DKIM public  key for default.domainkey.domain.tld, file /var/qmail/control/domainkeys/default.pub, keysize=1024
DKIM Private key for sagredo.eu file /var/qmail/control/domainkeys/default
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDHZT/CSiZXwbPIzCmZOWrBV4PR4XV/lPOL3f1GJjRVH5NMZwrr
hTxZ3R6JJN91dIlRbcDGQyEdpQDzjHVZgWfm45fGcVTBpF2JcdCycIXtXxX5N3GM
IUgxtrOI8ZyceMvDnu+wpuI/qhQS/zHi90+Ueth9t7S1cL1QX6ESoNu2awIDAQAB
AoGANAqwDnSt9z+ePe1TeiNrQpUl2ZSfxzHIMxw4a6OzCviXyFwolHoM22OEAcV2
8T/+Sxt7MgP5U7RqQCbLxhWpWTrLvUcSQAy6DJbjLUaf0bdvpIGxa+q7zlB5PAzi
uUWGL9s6HFJzp65heNIoDRTBgmQE9l4nXd3ua1JLSUhMCGECQQDrIX0/xeX8Tuvf
m9BWe7JuYTZ0hmSfwjUoNI5AzbtGCsLNor+lqJ8Q6depseXLwHsrt37SGznd7wcx
eNBCjEYbAkEA2RfNUdUnQISmkR4WQzYIICTnnltVTP7atqSB0gHHKwJqYl7F7FFB
3E1Hr9LxrcmhVKVtbABr0wmIs7F2YgCV8QJBALKWeBwlAn61rt/i58WYJDlEKuks
XmcdSeSkrls4J4KWj8lCUM/RGCfvhLdGAGTWaHcW4wNQXI5di5gezAePpXsCQHG3
NxSre7EfCwUu5mh0cBMuYakgnHEFell7mIkB52sPC9zVWgWslrwoOunNrEzlNj3Z
nZSaL+DOuK2vwpwZRHECQQCtgpPrGGnzO6cAuZi5NmBemii4+RYkNTUaXX2DlSpu
JxPpOSA3nf6OsmMatGdT857I3PNzIq/l8P0vSk3lHWlK
-----END RSA PRIVATE KEY-----
-rw-r----- 1 root qmail 887 Mar  8 19:05 /var/qmail/control/domainkeys/default
------------------------------------------------------
DKIM TXT record for domain.tld with selector=default file /var/qmail/control/domainkeys/default.pub
default._domainkey.domain.tld. IN TXT ("v=DKIM1; k=rsa; t=y; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHZT/CSiZXwbPIzCmZOWrBV4PR4XV/lPOL3f1GJjRVH5NMZwrrhTxZ3R6JJN91dIlRbcDGQyEdpQDzjHVZgWfm45fGcVTBpF2JcdCycIXtXxX5N3GMIUgxtrOI8ZyceMvDnu+wpuI/qhQS/zHi90+Ueth9t7S1cL1QX6ESoNu2awIDAQAB")
-rw-r--r-- 1 root qmail 282 Mar  8 19:05 /var/qmail/control/domainkeys/default.pub
------------------------------------------------------​

If you are having problems to add such a long key in your DNS, because you use a kind of control panel that doesn't manage two lines long keys, use a 1024 bit rsa key, which goes in one single line. Also you don't have to use the option DKIMSIGNOPTIONS="-z 2" in this case.

Remember to delete the testing tag (t=y) from the dns record once your tests are fine. dknewkey used in combination with the -e option will show the DNS record without the testing tag.

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

References:

rc script

First of all, let's save to the dkimdomain control file the domain to be used to sign the system messages belonging to the null sender ("<>"). These messages are bounces from our own MTA which have to be signed to avoid rejections because of a missing DKIM signature and/or a DMARC filter. Put here the domain that you saved in the control/me file, as it will be retrieved from the HELO when the messages is sent from the null <> sender.. 

echo "domain.tld" > /var/qmail/control/dkimdomain

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

#!/bin/sh

# declaring NODKIM disables DKIM

# Sign with 2048 bit RSA. Comment out DKIMSIGNOPTIONS to sign with 1024 bit
DKIMSIGNOPTIONS="-z 2"
DKIMDOMAIN=`cat /var/qmail/control/dkimdomain`

# DKIM sign at qmail-remote level
exec env - PATH="/var/qmail/bin:$PATH" \
QMAILREMOTE=/var/qmail/bin/spawn-filter \
DKIMSIGNOPTIONS="$DKIMSIGNOPTIONS" \
DKIMDOMAIN="$DKIMDOMAIN" \
FILTERARGS=/var/qmail/bin/dk-filter \
qmail-start "`cat /var/qmail/control/defaultdelivery`"

# Use this if you are signing at qmail-smtpd level
#exec env - PATH="/var/qmail/bin:$PATH" \
#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/control/domainkeys/default.

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

DKIMKEY=/path/to/domainkeys/domain.tld/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="FGHKLMNOQRTVWp"
# This is to allow msg without "subject" in the h= list
# export UNSIGNED_SUBJECT=1
# This is to avoid verification of outgoing messages
export RELAYCLIENT_NODKIMVERIFY=1

Declaring UNSIGNED_SUBJECT solves rare cases of email from providers which doesn't sign the subject (more info here). This would allow spammers to modify the subject without affecting the DKIM signature, so use at your own risk (I have it enabled since libero.it, a big provider here in Italy, would be blocked otherwise).

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

Signing test

We'll do the test as qmailr, the user who runs qmail-remote and which owns the domainkey.

This is how to test dk-filter:

DOMAIN=domain.tld 
RSA2048_SELECTOR=default 

( 
echo "From: postmaster@${DOMAIN}" 
echo "To: postmaster@${DOMAIN}" 
echo "Subject: Test" 
echo "Date: $(date -R)" 
echo 
echo "Test message" 
) > /tmp/mail.txt 

sudo -u qmailr env - \ 
   QMAILREMOTE="1" \ 
   _SENDER=postmaster@${DOMAIN} \ 
   CONTROLDIR=/tmp/control \ 
   DKIMSIGN=/var/qmail/control/domainkeys/%/${RSA2048_SELECTOR} \ 
   DKIMSIGNOPTIONS="-z 2" \ 
   /var/qmail/bin/dk-filter < /tmp/mail.txt

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 
       d=domain.tld; s=default; h=From:To:Subject:Date; bh=PkbvdhgKiEAA 
       hc+GiwM2ZnxMu+StJ76lWGj3Y9phfFA=; b=W1M3ZoTi+qcb/WwfJK7RIbf3ad0N 
       dBFTEBBDCqcWWnWVptuuILY4uTqq5bAfVEZZGb2O+6f1wuLvwXGbmM2jWvKwXQjJ 
       sFx7EkM+sJ5OtkwIHa/Lu3B91enXHF0bdXwSxkLcqU92UftFzIxArce4XBNBZ9gK 
       QujGix2TkuCOzwGwv3fytt4gizA6yFg+7lbih3m5pAi+MH77yWywpHEA1Ffl1pqh 
       JHbX5eM+THXovWFyOCY2tcijFSjMV53SUnckDHZd3sEZHbrM2iv7SUni2Wb/9Yvz 
       /4vGqRqJ0ZAzVqqfdL1kN+SBRV117ZyzNcS2jl+0sMnuDADy/hRD54n46A== 
From: postmaster@domain.tld
To: postmaster@domain.tld
Subject: Test 
Date: Sun, 19 Feb 2023 18:01:34 +0100 

Test message

In the example above CONTROLDIR=/tmp/control assures that anything defined in control/dkimkeys will interfere in the test.

Send to yourself a message and look for the DKIM signature in the header:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 
      d=domain.tld; s=default; h=From:To:Subject:Date; bh=PkbvdhgKiEAA 
       hc+GiwM2ZnxMu+StJ76lWGj3Y9phfFA=; b=W1M3ZoTi+qcb/WwfJK7RIbf3ad0N 
       dBFTEBBDCqcWWnWVptuuILY4uTqq5bAfVEZZGb2O+6f1wuLvwXGbmM2jWvKwXQjJ 
       sFx7EkM+sJ5OtkwIHa/Lu3B91enXHF0bdXwSxkLcqU92UftFzIxArce4XBNBZ9gK 
       QujGix2TkuCOzwGwv3fytt4gizA6yFg+7lbih3m5pAi+MH77yWywpHEA1Ffl1pqh 
       JHbX5eM+THXovWFyOCY2tcijFSjMV53SUnckDHZd3sEZHbrM2iv7SUni2Wb/9Yvz 
      /4vGqRqJ0ZAzVqqfdL1kN+SBRV117ZyzNcS2jl+0sMnuDADy/hRD54n46A==

Let's see how to test qmail-dkim

We have to set the env variable DKIMSIGN or DKIMKEY. Then set the env variable DKIMQUEUE=/bin/cat so that the result is displayed on screen.

DOMAIN=domain.tld 
RSA2048_SELECTOR=default

( 
echo "From: postmaster@${DOMAIN}" 
echo "To: postmaster@${DOMAIN}" 
echo "Subject: Test" 
echo "Date: $(date -R)" 
echo 
echo "Test message" 
) > /tmp/mail.txt 

sudo -u qmailr env - \ 
   CONTROLDIR=/tmp/control \ 
   DKIMSIGN=/var/qmail/control/domainkeys/%/${RSA2048_SELECTOR} \ 
   DKIMSIGNOPTIONS="-z 2" \ 
   DKIMQUEUE=/bin/cat \ 
   /var/qmail/bin/qmail-dkim < /tmp/mail.txt

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 
       d=domain.tld; s=default; x=1677431613; h=From:To:Subject:Date; 
       bh=PkbvdhgKiEAAhc+GiwM2ZnxMu+StJ76lWGj3Y9phfFA=; b=tqvFwKgs7EspI 
       F3W9kHvSE/FL1cfkE8kDaZkBd2d8R8+aTUEFt9nLk8bQkxWr1A+BUfB80CxAS4CI 
       U7MK+bF5fyQk/xuvyyjQdmEvuL1mQRJq4gshRh43Fs+4CXcJ0WLM6HrQfzFWrRLM 
       hhBrB3ahgDyLCM0cFyzGpyyeuZcxThCtNZmD+XWwk87ONKcNIeJw3pZXqW4I0RuA 
       yOu1rubotq/Q+jgCBmwFiVnBCV8XUsGIUiqB8Rd6Fm+xuY+GZOrUAZksB+G9tyrW 
       vIjuCVbac+nuivJN30Sny9BDjPqRlacg9lFw3GRJgMK5ggqDU9mEJdAvjNtII+qg 
       asw0lc4VQ== 
From: postmaster@domain.tld 
To: postmaster@domain.tld
Subject: Test 
Date: Sun, 19 Feb 2023 18:13:33 +0100 

Test message

Verification test

I assume that vpopmail is the user who runs qmail-smtpd.

DOMAIN=domain.tld

( 
echo "From: postmaster@${DOMAIN}" 
echo "To: postmaster@${DOMAIN}" 
echo "Subject: Test" 
echo "Date: $(date -R)" 
echo 
echo "Test message" 
) > /tmp/mail.txt 

sudo -u vpopmail env - \ 
DKIMQUEUE=/bin/cat \ 
/var/qmail/bin/qmail-dkim < /tmp/mail.txt

DKIM-Status: no signatures 
From: postmaster@domain.tld 
To: postmaster@domain.tld 
Subject: Test 
Date: Sun, 19 Feb 2023 19:58:22 +0100 

Test message

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

This is how to test the signature of a mail that was prevently saved to disk as email.txt (do not cut&paste to avoid to alter the body with white spaces, just save it to disk):

> /var/qmail/bin/dkim -vS < /path/to/email.txt
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.

You can also check the validation of your dns record (not the signature verification) here https://mxtoolbox.com/dkim.aspx.

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 it 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

First of all, let's save in the dkimdomain control file the domain to be used to sign the system messages belonging to the null sender ("<>"). These messages are bounces from our own MTA which have to be signed to avoid rejections because of a missing DKIM signature and/or a DMARC filter.

echo "yourdomain.tld" > /var/qmail/control/dkimdomain

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

DKIMDOMAIN=`cat /var/qmail/control/dkimdomain`

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

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 /var/qmail/control/domainkeys/default

Testing

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.

DOMAIN=domain.tld

( 
echo "From: postmaster@${DOMAIN}" 
echo "To: postmaster@${DOMAIN}" 
echo "Subject: Test" 
echo "Date: $(date -R)" 
echo 
echo "Test message" 
) > /tmp/mail.txt

sudo -u vpopmail env - \
   DKIMQUEUE=/bin/cat \
   DKIMKEY=/var/qmail/control/domainkeys/%/default
   RELAYCLIENT=""
   /var/qmail/bin/qmail-dkim < /tmp/mail.txt

DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
        d=domain.tld; s=default; x=1298483339; h=To:From:Subject;
        bh=6rJdFs2WVS8T72i61KhaAvC6O6s=; b=ffnXBB98Gg6iZFEIL6alk8c5davso
        ozyrunXM3C8qaejIrJOwYhnlWQwSdrV599WErmJcDYyMjFjVgLzRQ9OTeYHjEnHT
        X/aiIkvjcxRuOaTK7PcwrcJGdtF0c6LWoK9RgiPctCw7DMcHGmUcSyXWc6ayzHgX
        A7nopQYuHzTuIU=
From: postmaster@domain.tld 
To: postmaster@domain.tld 
Subject: Test 
Date: Sun, 19 Feb 2023 19:58:22 +0100

Test message

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

Signing with multiple keys. Customizing the selector

  • man dkim for more info

Starting from version 1.37 of the dkim patch, we have the ed25519 support, a new cryptographic signature algorithm for DKIM added by the RFC 8463. Currently no one is verifing the signature with this algorithm, so (Transition Considerations of the RFC 8463)

For backward compatibility, signers can add multiple signatures that use old and new signing algorithms. Since there can only be a single key record in the DNS for each selector, the signatures have to use different selectors, although they can use the same d= and i= identifiers.

In other words, if we want to play with ed25519, we can have two signatures for the same domain: one for rsa and one for ed25519.

Assuming that we have already created the rsa key, here is how to generate the ed25519 one with dknewkey:

# dknewkey -d domain.tld -t ED25519 ed25519 
Generating ed25519 DKIM private key keysize=2048, file /var/qmail/control/domainkeys/domain.tld/ed25519 
Generating ed25519 DKIM public  key for ed25519.domainkey.domain.tld, file /var/qmail/control/domainkeys/domain.tld/ed25519.pub 
DKIM Private key for domain.tld file /var/qmail/control/domainkeys/domain.tld/ed25519 
-----BEGIN PRIVATE KEY----- 
MC4CAQAwBQYDK2VwBCIEIBdgashw5uHx2zxoDCRyIUvPp7Le0d0ljtKiwFreQo58 
-----END PRIVATE KEY----- 
-rw-r----- 1 root qmail 119 Feb 19 13:52 /var/qmail/control/domainkeys/domain.tld/ed25519 
------------------------------------------------------ 
DKIM TXT record for domain.tld with selector=ed25519 file /var/qmail/control/domainkeys/domain.tld/ed25519.pub 
ed25519._domainkey.domain.tld. IN TXT ("v=DKIM1; k=ed25519; t=y; p=l+ZydrxSK4GvFEQvVTKaFxY3+LUh4cCxktsLy8Y2Gl8=") 
-rw-r--r-- 1 root qmail 114 Feb 19 13:52 /var/qmail/control/domainkeys/domain.tld/ed25519.pub 
------------------------------------------------------

In this example "ed25519" is the name of the selector for the ed25519 key.

Now let's see how to manage multiple keys and customize the selector name with the enhanced control/dkimkeys functionality which comes with the new dkim-1.37 patch.

The /var/qmail/control/dkimkeys control file format can have wildcards or regular expressions and can be used to customize the selector name and/or define multiple keys for a given domain.

The below dkimkeys file is for example.* domains. One rsa and another ed25519 keys are declared.

example.*:/var/qmail/control/domainkeys/%/rsa2048:QREGEX=1,DKIMSIGNOPTIONS=-z 2,DKIMSIGNEXTRA=/var/qmail/control/domainkeys/%/ed25519,DKIMSIGNOPTIONSEXTRA=-z 4

The DKIMSIGN and DKIMSIGNOPTIONS variables belong to the the first key, which have the rsa2048 selector. DKIMSIGNOPTIONS=-z 2 specifies that the hash for that key will be rsa-sha256 (rsa with 2048 bits).

DKIMSIGNEXTRA and DKIMSIGNOPTIONSEXTRA refers to the second key declared, which have ed25519 as selector. DKIMSIGNOPTIONSEXTRA=-z 4 means that it will have the ed25519 hash.

NOTE: use DKIMSIGNOPTIONSEXTRA=-z 4 and not DKIMSIGNOPTIONSEXTRA="-z 4" syntax in this file.

The format of the dkimkeys file is

domain.tld:dkim_private_key_file_path[,OPTION1=1,OPTION2=2][:dkim_private_key_file_path2[,OPTION3=3,OPTION4=4]][:...]

NOTE: domain can be a regular expression understood by egrep, e.g. sagr*.* will match sagredo.eu, sagredo.com. etc.

You can have multiple lines in the control file /var/qmail/control/dkimkeys. If there are multiple matches, then the first match will be used.

As always, the basename of the private key file will be used as the selector.

When DKIMSIGN or DKIMKEY has '%' character, it is replaced by domain.tld. If after replacement the private key is not found, the '%' character will be removed.

e.g. if DKIMSIGN=/var/qmail/control/domainkeys/%/private and the file /var/qmail/control/domainkeys/domain.tld/private is not found, then dk-filter will use  /var/qmail/control/domainkeys/private as the private key file.

Testing

To verify the double signature just repeat the example test shown above but adding the DKIMSIGNEXTRA and DKIMSIGNOPTIONSEXTRA for the ed25519 signature.

DOMAIN=domain.tld
RSA2048_SELECTOR=default 
ED25519_SELECTOR=ed25519 

( 
echo "From: postmaster@${DOMAIN}" 
echo "To: postmaster@${DOMAIN}" 
echo "Subject: Test" 
echo "Date: $(date -R)" 
echo 
echo "Test message" 
) > /tmp/mail.txt 

sudo -u qmailr env - \ 
   QMAILREMOTE="1" \ 
   _SENDER=postmaster@${DOMAIN} \ 
   CONTROLDIR=/tmp/control \ 
   DKIMSIGN=/var/qmail/control/domainkeys/%/${RSA2048_SELECTOR} \ 
   DKIMSIGNOPTIONS="-z 2" \ 
   DKIMSIGNEXTRA=/var/qmail/control/domainkeys/%/${ED25519_SELECTOR} \ 
   DKIMSIGNOPTIONSEXTRA="-z 4" \ 
   /var/qmail/bin/dk-filter < /tmp/mail.txt

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 
       d=domain.tld; s=default; h=From:To:Subject:Date; bh=PkbvdhgKiEAA 
       hc+GiwM2ZnxMu+StJ76lWGj3Y9phfFA=; b=W1M3ZoTi+qcb/WwfJK7RIbf3ad0N 
       dBFTEBBDCqcWWnWVptuuILY4uTqq5bAfVEZZGb2O+6f1wuLvwXGbmM2jWvKwXQjJ 
       sFx7EkM+sJ5OtkwIHa/Lu3B91enXHF0bdXwSxkLcqU92UftFzIxArce4XBNBZ9gK 
       QujGix2TkuCOzwGwv3fytt4gizA6yFg+7lbih3m5pAi+MH77yWywpHEA1Ffl1pqh 
       JHbX5eM+THXovWFyOCY2tcijFSjMV53SUnckDHZd3sEZHbrM2iv7SUni2Wb/9Yvz 
       /4vGqRqJ0ZAzVqqfdL1kN+SBRV117ZyzNcS2jl+0sMnuDADy/hRD54n46A== 
DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; 
       d=domain.tld; s=ed25519; h=From:To:Subject:Date; bh=PkbvdhgKiEAA 
       hc+GiwM2ZnxMu+StJ76lWGj3Y9phfFA=; b=JzENCy7Xmtp/BW+xRPdHJuao+gTu 
       q182WxDSu+YDAyBEbEJw3fFDWcDEWuKFETV0f3HMdtn6G4Gt+0+w4WrkDA== 
From: postmaster@domain.tld
To: postmaster@domain.tld
Subject: Test 
Date: Sun, 19 Feb 2023 18:01:34 +0100 

Test message

CONTROLDIR=/tmp/control assures that the program will not read anything in the qmail/control directory, dkimkeys for instance. To test control/dkimkeys, repeat the same test removing CONTROLDIR, DKIMSIGN and DKIMSIGNOPTIONS.

Comments

Selection of the ehader lines to be signed

Buongiorno,

qmail-dkim(8) states:

> By default qmail-dkim will use all of the headers when signing a message.

Is there any way to changed that default other than modifying the source code and recompile?

I ask because a recipient recently has problems with our signature which also include the "ARC-Authentication-Results" of third-party systems when these are forwarded by our mailing-lists.

BTW, I think this header type should be excluded (like e.g. "Authentication-Results" and others already are), because it falls into the category "fields that are modified in transit", compare the recommendations in https://datatracker.ietf.org/doc/html/rfc6376#section-5.4.1 

Personally, to be honest, I'd prefer to be able to configure a list of header types which should be signed instead of the current "sign anything but …" approach, anyway.

Kind regards,
Martin

Reply |

Selection of the ehader lines to be signed

Buongiorno Martin,

I don't think this is possible in the current dkim program. I'll ask Manvendra to have a look to your question.

Reply |

Selection of the ehader lines to be signed

I have updated the latest patch. One can have a list of headers to be not signed as a colon separated list of headers in EXCLUDE_DKIMSIGN. The below has been added to qmail-dkim man page

By default qmail-dkim will use all of the headers when signing a message. You an exclude headers from gettng signed by setting a colon separated list of headers in EXCLUDE_DKIMSIGN environment variable.

I have been down with some kind of viral and recovery is being slow. So it is not possible for me to test the changes.

Reply |

Selection of the ehader lines to be signed

Thanks so much, Manvendra. Get well soon.

There were a couple of missing definitions... 

--- dkim_bak.c    2023-11-14 13:05:07.142460460 +0100 
+++ dkim.c        2023-11-14 13:17:20.866015118 +0100
@@ -95,6 +95,7 @@
int DKIM_CALL
SignThisHeader(const char *szHeader)
{
+  char *ptr;
       if ((!strncasecmp(szHeader, "X-", 2) && strncasecmp(szHeader, "X-Mailer:", 9))
                       || !strncasecmp(szHeader, "Received:", 9)
                       || !strncasecmp(szHeader, "Authentication-Results:", 23)
@@ -104,7 +105,7 @@
               return 0;
       if (!excl)
               return 1;
-       for (i = 0, cptr = ptr = excl; *ptr; ptr++, i++) {
+       for (int i = 0, cptr = ptr = excl; *ptr; ptr++, i++) {
               if (*ptr == ':') {
                       *ptr = 0;
                      fprintf(stderr, "comparing [%s][%s] %d\n", szHeader, cptr, i);

I uploaded a new testing patch here https://notes.sagredo.eu/files/qmail/patches/roberto-netqmail-1.06/roberto-netqmail-1.06.patch-2023.11.14testing 

Martin, can you please test if everything works as expected? I won't be able to test it myself today

Reply |

Selection of the header lines to be signed

Dear Manvendra,
dear Roberto,

thank you very much for the patch! Today I finally found the time to test it. However, to be honest, I haven't got it to work so far.

First, I found out that qmail-dkim probably isn't even used in my setup; I configured DKIM signing like this:

$ cat /var/qmail/supervise/qmail-send/run  
#!/bin/sh

exec env - PATH="/var/qmail/bin:$PATH" \
DKIMSIGNOPTIONS='-z 2' \
NODK=1 \
QMAILLOCAL=/var/qmail/bin/spawn-filter \
QMAILREMOTE=/var/qmail/bin/spawn-filter \
FILTERARGS=/usr/local/sbin/dk-filter \
qmail-start "`cat /var/qmail/control/defaultdelivery`"

Sorry for the confusion!

So if I get it right, I would have to tell my dk-filter script to call the dkim binary with "-X ARC-Authentication-Results". However, unfortunately I could not get this to work, either:

$ echo -e 'ARC-Authentication-Results: foo\nFrom: martin.sluka@mensa.de\nTo: martin@sluka.de\nSubject: Test\n\nDas ist der Rand von Ostermundigen.' | /var/qmail/bin/dkim -X ARC-Authentication-Results -z 2 -x - -y it-2350 -s /var/qmail/control/domainkeys/mensa.de/it-2350 
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mensa.de;
       s=it-2350; h=ARC-Authentication-Results:From:To:Subject; bh=bjee
       NvsU917RAvwnapQsTjKD4aFVjCLhf32ZmQKg6TY=; b=XofAEPLiKhco7l6c1dQS
       v71OBa6tJHFrTh05rTf1KYd22hAbH9J/964Lu5QScBAfoW0GYevnn54ofLcGXQl0
       lH/TmgEz5Fd11STIXUQAvStpTlgcX6wX78ciVOYSi9shC7wobtAe1rozFmv65Ufp
       E/HgXBD9h3DHJVEENFI57td9aw2U6CJ1toWb39CcHLLiZpPjyNOc1njqCvHnEPse
       GR9j14hM1L80Wn+pHGeRrWJcE2fH3TPiMqQ+/92e6obA+IODZ/donsKY2jzWi35p
       8WIPe/vcNyf5DDfqyRgVRNAuxq0MhTjQ98GosLBGEjuZ8A96XPsmJjrjbXCDpH+o
       DQ==

But the patched version of dkim seems to at least something with this -X option, because if I add a colon, I get a coredump:

$ echo -e 'ARC-Authentication-Results: foo\nFrom: martin.sluka@mensa.de\nTo: martin@sluka.de\nSubject: Test\n\nDas ist der Rand von Ostermundigen.' | /var/qmail/bin/dkim -X ARC-Authentication-Results: -z 2 -x - -y it-2350 -s /var/qmail/control/domainkeys/mensa.de/it-2350 
Segmentation fault (core dumped)

Whereas the old version would just ignore the parameter.

Am I still doing it wrong?

Kind regards,
Martin

Reply |

Selection of the header lines to be signed

I have modified the patch and uploaded

1. The patch now by default excludes X-Arc-Authentication-Results

2. dkim can additionally use the environment variable EXCLUDE_DKIMSIGN to include colon separated list of headers to be excluded from signing (just like qmail-dkim). Hence you need not modify dk-filter to add the -X option. If -X option is used, it overrides the value of EXCLUDE_DKIMSIGN

Reply |

Selection of the header lines to be signed

Thanks Manvendra. Combined patch updated.

Seems to be working well:

# grep -r ARC-Authentication-Results
1685002611.M67441P6782.qmail,S=12531,W=12739:2,RS:ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
/var/qmail/bin/dkim -vS < 1685002611.M67441P6782.qmail,S=12531,W=12739:2,RS
DKIM-Status: good

Reply |

Selection of the header lines to be signed

The code is not correct. I have made changes and will issue a new patch.

Reply |

Selection of the ehader lines to be signed

Look at dkimsign.cpp 

/* SignThisHeader - return boolean whether or not to sign this tag
*/
bool CDKIMSign::SignThisHeader(const string &sTag)
{
bool bRet = true;

if (_strnicmp(sTag.c_str(), "X-", 2) == 0
|| _stricmp(sTag.c_str(), "Authentication-Results:") == 0
|| _stricmp(sTag.c_str(), "DKIM-Signature:") == 0
|| _stricmp(sTag.c_str(), "Domainkey-Signature:") == 0
|| _stricmp(sTag.c_str(), "Received:") == 0
|| _stricmp(sTag.c_str(), "Return-Path:") == 0)
{
bRet = false;
}
return bRet;
}

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

Today I stumbled across a curious error when sending a mail from my private mail to our mail server.

The mail gets rejected with detail

qmail-dkim:_signature_error:_DKIM-Signature_could_not_parse_or_has_bad_tags/values_(#5.7.5)

When sending the very same email to auth-results@verifier.port25.com from my private mail it passes all tests.

Receiving mail from i.e. GMail, Outlook and several others on our mail server works just fine.

Any leads what I could check?

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

Sorry, I'm realizing that I have misunderstood your previous message. I think that your "private mail" is intended to be sent TO your email server, right?

In that case please post your dkim configuration

PS are you using my latest patch?

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

That is correct.

By DKIM config do you think of the private mails DNS record?

uberspace._domainkey.blackblizzard.org. 3600 IN TXT "v=DKIM1;t=s;n=core;p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8gFgGJLv7j0dI3yvyb9t/epY1S4VTYK5jhanOF31mg43ipIwm26y07C/4PvgR9wgwHILTDXJ1E41uDujf+sQW7hd8IEbMwXRgeiQbOEyr29y6IR3MDQyD36PiVfWAwuPMfmnaE7qkhOZHBv8ybo/hGzYxHUP0o5JD/AjoYAZnwxdeaJ3zAYbCuEmkdLV/V" "VqYWjNy4L5RgVscgHPVcuBjWkscYFleFD5l0FNlLtqux890WfocyT7c4r1PSvs3kpkYBw41o+pyDA/fGLeaui1OBnfEjL303sauzCS5VSKfPlRVM0lonnWJ3ivsM1zQcZCeVQI5eEXAHE7a2NxcdOYw62KVlDDFfLYumBNO7VEkyl2ervGe1pyuAe91U9AdYctnwqds9633KtAZMLMV1Eis9ydO+EVUawDyzQO4r5niTY2hwXm+va3RwXv0JD86" "Kz6ttAQ3Wk3yKCVi2DruJRAA1quUjEZkiJqTgN3qUNZNQCMfqrCYKyGxCOX4q6moLlBFIQGGilKs8/mHzulDZ5SJLQdynCOh6dv7TKcikpJuNpqbEeqr4vgrx8WuIxplMqasyx8h3J2xo37kgCWUo7T2tk4xDkp51YLX0lzhg5kZKuRmy51hGbZnY24LsD+gE7q6BSJb5noSTn9Fnh+KUTgI948cs8y8rSmvXbliqY163UCAwEAAQ=="

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

The k tag is missing in the DNS record. Did you update the qmail patch?

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

The server my private mail is from does not run your patch (it's not mine), only our server does :D

Besides the k tag is optional with a default value of rsa (https://www.rfc-editor.org/rfc/rfc4870#page-13), so that causing a syntax error is a bug, isn't it?

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

If you can tell us the value of DKIM-Signature header it could give a clue. Using your mail client you can save the email as test.eml. Gmail has 'show original' option. Once you have save the content of the mail with all the headers, one can do the following to test it

> $ dkim -v < test.eml

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

Of course. As the original message contains provate info I sent a new one just for test. This is the message source as returned by our mail server

Return-Path: <xxxxxxxx@blackblizzard.org>
Received: (qmail 31870 invoked by uid 500); 15 May 2023 13:11:57 -0000
Authentication-Results: borrelly.uberspace.de;
auth=pass (plain)
MIME-Version: 1.0
Date: Mon, 15 May 2023 13:11:57 +0000
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
From: xxxxxx@blackblizzard.org
Message-ID: <cde3ad50799195bf0f5d1711b2631d833aebfbc1@blackblizzard.org>
TLS-Required: No
Subject: DKIM-Test#1
To: xxxxxxxxxxxxxx@as-trainer.com
X-Rspamd-Bar: /
X-Rspamd-Report: MIME_GOOD(-0.1)
X-Rspamd-Score: -0.1
Received: from unknown (HELO unkown) (::1)
by borrelly.uberspace.de (Haraka/3.0.1) with ESMTPSA; Mon, 15 May 2023 15:11:57 +0200
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
d=blackblizzard.org; s=uberspace;
h=from;
bh=fdkeB/A0FkbVP2k4J4pNPoeWH6vqBm9+b0C3OY87Cw8=;
b=hBlW17MYT9K/jz2H1xWojtote/8t7vm5fyf25DTAjloSTjcQ5GQn1xTOfNVePIg89YhqZRVtih
OOzGHb8FHF4l/B5OsnbXHdBb7ouap+x+Uw+AoGk5YlJjIhxfSj9Wrg3cyyMIP6neRJlDkfAQYiFy
pBWPQgJQvDMVZsBUmS33LwD9v8RIZWJhH1R/llfDgXFohQgd6maKtqJhjiP0W41mx77ru7u4Xzct
aakXRmAu+YXcqbXrHYanD/cvJmh0KOkvPieibaBi11w3X8dy0TkZ4WfEEAkz68PcVnOhy/OpHEkd
UdnmsaXYfnHoVCVYhuTa+9A2scp//VIQNeZAoLvBwNEp3t6NfpjJqHgxIOg+KL60vaVEyDYuFjKq
UZZMO7aXhwQ92Vt/YV3YE79GXaKRlZkSTB6yBhl1PWNdkJfIDUAPJ8QiWXiitQNELBaYaEmSzPi8
4A52y0RX3njPKsNKGECoWR0F/AiBNmLIfrCTLgOLQd/I8+zN1f1Y5T7mY399E807TMOjkeVJCF/R
8CGz5wgbo3UdALq2T46PUXftm6KmJljGqXdPgz1v5wibro25Nw0mSYZf3C5BHP7Bk4UgCrvOcWl4
ClcXHDaiGWs48AqyosAWVR/4guMdHwXD4/Citx//bKhwGLlzAfGhsqW44CapzebMOQ0U8lxnePZx
w=

Test

$ /var/qmail/bin/dkim -v < /home/administrator/test-email_2.eml

on our server yields

signature error: DKIM-Signature could not parse or has bad tags/values
DKIM-Status: signature error: DKIM-Signature could not parse or has bad tags/values

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

The DKIM-Signature doesn't include the Subject as part of the signed headers. Your DKIM signature just has

h=from

In such a case, you must set the environment variable UNSIGNED_SUBJECT to anything. So just set this environment variable in your run script. You can also execute dkim like this (to allow unsigned subject)

dkim -S -v < /tmp/email2.eml

Section 5.4

> INFORMATIVE IMPLEMENTER'S NOTE: Although not required by this specification, all end-user visible header fields should be signed to avoid possible "indirect spamming". For example, if the Subject header field is not signed, a spammer can resend a previously signed mail, replacing the legitimate subject with a one-line spam.

Section 5.5

5.5 Recommended Signature Content

In order to maximize compatibility with a variety of verifiers, it is recommended that signers follow the practices outlined in this section when signing a message. However, these are generic recommendations applying to the general case; specific senders may wish to modify these guidelines as required by their unique situations. Verifiers MUST be capable of verifying signatures even if one or more of the recommended header fields is not signed (with the exception of From, which must always be signed) or if one or more of the disrecommended header fields is signed. Note that verifiers do have the option of ignoring signatures that do not cover a sufficient portion of the header or body, just as they may ignore signatures from an identity they do not trust.

The following header fields SHOULD be included in the signature, if they are present in the message being signed:

  • From (REQUIRED in all signatures)
  • Sender, Reply-To
  • Subject
  • Date, Message-ID
  • To, Cc
  • MIME-Version
  • Content-Type, Content-Transfer-Encoding, Content-ID, Content-Description
  • Resent-Date, Resent-From, Resent-Sender, Resent-To, Resent-Cc, Resent-Message-ID
  • In-Reply-To, References
  • List-Id, List-Help, List-Unsubscribe, List-Subscribe, List-Post, List-Owner, List-Archive

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

Thank you very much, this did it!

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

> The server my private mail is from does not run your patch (it's not mine), only our server does :D

I know, but you are verifing the signature with your qmail server, and I guess that server is not able to manage the missing k tag

> Besides the k tag is optional with a default value of rsa (https://www.rfc-editor.org/rfc/rfc4870#page-13), so that causing a syntax error is a bug, isn't it?

correct. It has been fixed it in a previuos release.

So, again, are you using my latest patch?

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

Sorry, for missing that info.

As far as I know, yes. To verify, I am currently using the 2023.04.26 combined patch.

Reply |

DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values

I cannot retrieve your dns dkim record belonging to the domain of the email that you have registered in your comment. I assume that you use a non conventional descriptor.

Can you send me a private message so that I can try to test your signature and dkim record?

Reply |

qq-innternal bug

Howdy,

All of a sudden I got the qqinternal-bug as well.
Been working fine, but all of a sudden on 2 may 2023 I got the following in my logs:

@400000006450df932d64a0dc qlogreceived: result=rejected code=451 reason=queue_delay detail=qq_internal_bug_(#4.3.0) helo=56-dmta.msdp1.com mailfrom=bounce-4WGM6ogHtCNRnOsqsK227oL2eSLEu6DyjNY-_UW3lLc4@e.kaartje2go.nl rcptto= relay=no rcpthosts= size=44201 authuser= authtype= encrypted=tls sslverified=no localip= localport=25 remoteip= remoteport=56867 remotehost=56-dmta.msdp1.com qp=53110 pid=53103

I couldn't find any in the logs, so I rebooted but that didn't work as well.

For now I disabled the DKIM checks and it's working but of course without the DKIM check.

Reply |

qq-innternal bug

Have also a look to this thread https://notes.sagredo.eu/en/qmail-notes-185/testing-qmail-smtp-and-auth-22.html#comment2960. That issue is solved in the latest patch

Reply |

qq-innternal bug

Hi, do you have a copy of that email? We should do an strace against it. If there are not privacy issues feel free to send it via mail to me, or at least the strace where you perform the qmail-dkim test together with the header of the message 

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

Hi Roberto,

After installing everything I've got a strange error in my smtpd. I assume it got something to do with 'unable_to_exec_qq'. But I can't find any reason what's failing. The DNS is working fine, that I checked.
Do you maybe have an idea as where to look?

@400000006446aa7736fb477c Zqmail-dkim: signature error: temporary dns failure requesting selector (#4.7.0)
qlogreceived: result=rejected code=451 reason=queue_delay detail=unable_to_exec_qq_(#4.3.0) helo=xtrwnvrh.outbound-mail.sendgrid.net mailfrom=bounces+27743972-ef7b-=@em3306.railsport.nl rcptto=@ relay=no rcpthosts= size=29669 authuser= authtype= encrypted=tls sslverified=no localip= localport=25 remoteip=167.89.40.80 remoteport=40386 remotehost=xtrwnvrh.outbound-mail.sendgrid.net qp=27451 pid=27448

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

I'm not familiar with the qlog patch, but it looks like there are two different errors in the log. One is a temporary dns error for fetching the selector record from the DNS  and the other is the error reported by the below line in the qlog patch, when qmail_close returns an error.

+    qlogreceived("rejected","queuedelay",qqx + 1,"451");

In the above case, qmail-dkim has exited with a temporary error and qqx + 1 is as shown below. So to to me it looks like something else happened after the qmail-dkim error. Probably an strace -f -p tcpserver_pid will reveal what is happening.

qmail-dkim: signature error: temporary dns failure requesting selector (#4.7.0)

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

Hi Goofy,

the dkim verification went wrong because of a DNS problem while resolving the dkim record of the sender, so it is not your server's fault.

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

Hi Roberto,

With the help of strace it turns out simscan is treating 88 which qmail-dkim returns for (custom error patch) as unable_to_exec_qq error as default. Now your combined patch uses CUSTOM_ERR_FD as 4 and qmail-dkim uses 2 as the descriptor. However one can change that for qmail-dkim by setting the environment variable ERROR_FD=4 in the run script to send the error to descriptor 4 instead. Hopefully that should solve the ambiguous error being reported by qmail-smtpd.

qmail.h:#define CUSTOM_ERR_FD 4

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

Great! Thanks for pointing out that. I'll update my notes accordingly

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

With the help of Manvendra I t-shooted the issue further. Also came to the conclusion that Ubuntu 22.04 does not understand 'declare -x'.

I also had to patch and recompile qmail-dkim.c. I assume Manvendra will come back to that.

For people having simular issues:

find the errfd = 2;  in qmail.dkim & change to:

erffd = CUSTOM_ERR_FD;

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

Hi Roberto,

Also in qmail-dkim.c it will be the right thing to do if we change

errfd = 2;

to

errfd = CUSTOM_ERR_FD;

If we do that, we will not require to set the environment variable ERROR_FD. This change is in the custom_error() function.

Reply |

Zqmail-dkim: signature error: temporary dns failure requesting selector.

I'll do it. It's even simpler. Thank you

Reply |

Bug in dknewkey

The following command creates a private key correctly but fails to output corresponding public key.

# dknewkey -d domain.tld -t rsa -b 2048 default

It generates one line of public key without any public key.

# cat default.pub
default._domainkey.domain.tld. IN TXT (
#

Reply |

Bug in dknewkey

I cannot reproduce the problem. Can you show how are you using dknewkey in order to create the key?

Reply |

Bug in dknewkey

The script seems to print the first line then stops but does not generate any error. I tried with default selector and different domain names but results are same. I am running Debian 11.

# dknewkey -d abcd.com -t rsa -b 2048 asdf1
Generating rsa DKIM private key keysize=2048, file /var/qmail/control/domainkeys/abcd.com/asdf1
Generating rsa DKIM public key for asdf1.domainkey.abcd.com, file /var/qmail/control/domainkeys/abcd.com/asdf1.pub, keysize=2048
# cat /var/qmail/control/domainkeys/abcd.com/asdf1
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAw931TJiXXM3I30va2hCs+sNmUR5ZJ0DU5yZVFOfuDEJPauB5
HBN5hUqpyK2p9cccuEBJToiUk6fVP6MiO0hXACbsTGhEAodq7Id1xZzs+tWuFz8y
ZnO5d7ZylMEtS0p3xhRTGrTCYlq7QkX44Jk9xJCJFG50/hv9Y1wMtxhM/XsWPj0w
2A0SpgfgTaH26xQYvqyhr6q1pE1cH4DDF8C7LHDWUcm0LudNx9xt3LUDFtUbHdLt
BWzJHtZa6FEN55UQx1ql1t7dB5VbF2CBFPFMcsIxOPUhxnCegyTw5vHRf9ooMTCo
MUptoeALDoM9HsFj48/ONhgP3/BzCT5N2b4gswIDAQABAoIBAQC1rtKWHUjx/bSh
.......
/+I91+oas+DhOqtgdJqf6QJnMyk1FKB0oZhO8dxIM/m/pMpfAuLnLCdZfyqvv+XA
Wj9d7JiaNHktCeDJZOZxGldjirRchbG50qVdyv/l1KvI4ZD7Au+A/UIa/7/UcU0g
qD272h8CgYEA10LxYhZ+MnHJMOlzSXS0ya7rsxOrTvnXuoFv91umn8aw/pxWqp87
VWBPJQYtMdag+ftYbAVpDbpIIKsHf6zQR+a2eGfVnepoMwAWYpwl63ZRTfRtkXnJ
cAagUSnHbemvt/bsIeT8ChuFMym3hqeU1LiPZF40OfbzEldd6k7Af+Y=
-----END RSA PRIVATE KEY-----
# cat /var/qmail/control/domainkeys/abcd.com/asdf1.pub
asdf1._domainkey.abcd.com. IN TXT (#

Reply |

Bug in dknewkey

Does this command work

cd /var/qmail/control/domainkeys/abcd.com/
openssl  rsa -in asdf1 -pubout -outform PEM | grep -v '^--' | tr -d '\n'

Reply |

Bug in dknewkey

The command

openssl  rsa -in default -pubout -outform PEM | grep -v '^--' | tr -d '\n'

seems to work on debian as it prints the rsa key. But the key was not printed at all when it was created and the default.pub file is broken

default._domainkey.test.com. IN TXT (

I can confirm that patching as suggested below solves.

Reply |

Bug in dknewkey

I have been unable to simulate this. But I believe the split_str function is bash specific and maybe giving problems on systems where /bin/sh doesn't have BASH extensions. A portable way to split a string longer than 255 characters is to use the fold -w255 command. That's what I have done in the new patch

6b50946f7fe5c9dc5761f56118be2bcb  dkim-netqmail-1.06.patch-1.38.gz

https://sourceforge.net/projects/indimail/files/netqmail-addons/qmail-dkim-1.0/dkim-netqmail-1.06.patch-1.38.gz

Reply |

Bug in dknewkey

split_str() works when using my old program with the same split_str() function by Tatsuya Yokota https://github.com/kotaroman/domainkey but I cannot figure out what's causing the problem in your modified version

Reply |

Bug in dknewkey

Yes, it works!
I think there is an issue with split_str function in the dknewkey script. It works well after changing as per below:

65c65
< split_str "v=DKIM1; k=$ktype;$t p=$pubkey"
---
> printf "v=DKIM1; k=$ktype;$t p=$pubkey"

Reply |

Bug in dknewkey

I will try to simulate this and fix the split_str function. The split function is needed to split the text records into multiple strings smaller than 255 bytes for some dns service providers.

Reply |

Bug in dknewkey

I have modified split_str() so it works in Debian 11.

--- dknewkey.orig 2023-03-14 21:09:35.306738818 +1300
+++ dknewkey 2023-03-14 21:36:54.068728994 +1300
@@ -25,26 +25,19 @@
# of length 255 or less
split_str()
{
- local STR="$1"
- local START=0
- local STR_COUNT=0
- local LINE=""
- local SPLIT=255
+ local INPUT="$1"
+ local LEN=$(echo "$INPUT" | wc -c)
+ local COUNT=$((LEN / 255))

- while true
- do
- START=$STR_COUNT
- LINE=${STR:$START:$SPLIT}
- if [ ${#LINE} -eq 0 ]; then
- break
- fi
- if [ $START -eq 0 ]; then
- printf "\"${LINE}\"" # first line
- else
- printf " \"${LINE}\""
- fi
- STR_COUNT=$(expr $STR_COUNT + $SPLIT)
- done
+ for i in `seq 0 $COUNT`
+ do
+ LINE=`echo "$INPUT" | cut -c $((i * 255 + 1))-$(((i + 1) * 255))`
+ if [ $COUNT -eq 0 ]; then
+ echo "\"${LINE}\"" # first line
+ else
+ echo " \"${LINE}\""
+ fi
+ done
}

write_pub_key()

Reply |

Bug in dknewkey

Hi J,

Can you let me know your name (or first name) so that I can credit you for the new split_str function in the dknewkey code.

Regards Manvendra

Reply |

Bug in dknewkey

Thank you. That was nice of you. I will leave it to Roberto to include this version in his combined patch. Will apply the same changes at my end.

Reply |

Bug in dknewkey

Thank you. Appreciated

Reply |

Bug in dk-filter with DKIDOMAIN

Thanks to you and Manvendra for the patch. However, I have a problem with dk-filter when using DKIDOMAIN for bounces with empty sender. I get the following error:

% export QMAILREMOTE=/var/lib/qmail/bin/spawn-filter
% export DKIMSIGNOPTIONS="-z 2"
% export DKIMDOMAIN=`cat /var/lib/qmail/control/dkidomain`
% unset _SENDER
% var/lib/qmail/bin/dk-filter < testmail.txt
/var/lib/qmail/bin/dk-filter: 135: strip_default: not found
basename: missing operand
Try 'basename --help' for more information.
Private Key not provided
usage: dkim [-lqthvH] [-p <0|1|2>] [-b <1|2|3>] [-c <r|s|t|u>]
[-d domain] [-i you@domain] [-x expire_time] [-z hash] [-y selector] -s privkeyfile
....

I looked at the dk-filter script, and it does seem to try to call a strip_default function that is never defined. 

I also question why it is calling this function. Assuming it says what it is supposed to do, I don't see a reason to strip the 'default' selector part of the key file path, otherwise the file would not be found. 

As such, I assume the following patch should fix it (it seems to do so for me), but not sure whether that is the right fix. 

--- /usr/sbin/dk-filter.orig 2023-01-01 00:28:45.000000000 +0000
+++ /usr/sbin/dk-filter 2023-01-01 00:35:39.000000000 +0000
@@ -132,7 +132,7 @@
fi
if [ $percent_found -eq 1 ] ; then
if [ -n "$DKIMDOMAIN" -a -z "$_SENDER" ] ; then
- dkimkeyfn=$(strip_default $(echo $DKIMSIGN | sed "s{%{$DKIMDOMAIN{g"))
+ dkimkeyfn=$(echo $DKIMSIGN | sed "s{%{$DKIMDOMAIN{g")
if [ ! -f $dkimkeyfn ] ; then # remove % and check if file exists
t=$(echo $DKIMSIGN | sed "s{/%{{g")
if [ -f $t ] ; then

Reply |

Bug in dk-filter with DKIDOMAIN

Hi Andreas,

Thank you for posting the fix. The fix is correct. The strip_default was supposed to be removed but somehow it escaped my eyes.

Reply |

Bug in dk-filter with DKIDOMAIN

Ok, great. I assume the patch really needs to be applied to the .sh file in the sources. Sorry also for the typo in the subject. And I assume that you will incorporate that into the next version of the patch, right? 

Happy new year to everybody!

Andreas

Reply |

Bug in dk-filter with DKIDOMAIN

Happy new year!

Combined patch updated

Reply |

Custom Selector

Good Day!

I worked through this page but could not get a custom selector working for signing.  I note that some have previoulsy commented on this issue, but the listed solutions and workarounds didn't solve the issue for me.

I traced through things until I found that the dk-filter script was not properly stripping the word default from the domainkeys strings. The file claims to be auto-generated, so clearly that file is not the correct place to fix the problem permanently, presumably this will need to be fixed in the patch. 

This is still in my sandbox, so not tested in production and may need some further tweaking, and only tested with DKIM, not DK (but I put the changes for DK as well so presumably will work), but the following patch updates the dk-filter file so that it properly detects the selector, generates the keys, and outputs the correct headers:

--- /root/dk-filter 2022-09-26 15:08:30.492717661 -0400
+++ /var/qmail/bin/dk-filter 2022-09-26 17:17:42.888588987 -0400
@@ -88,17 +88,21 @@
fi
if [ -z "$NODK" -a -x /var/qmail/bin/dktest -a -z "$DKVERIFY" ] ; then
if [ -z "$DKSIGN" ] ; then
- DKSIGN=/var/qmail/control/domainkeys/%/default
+# DKSIGN=/var/qmail/control/domainkeys/%/default
+ DKSIGN=/var/qmail/control/domainkeys/%
dksign=2
- elif [ " $DKSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+# elif [ " $DKSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+ elif [ " $DKSIGN" = " /var/qmail/control/domainkeys/%" ] ; then
dksign=2
fi
fi
if [ -z "$NODKIM" -a -x /var/qmail/bin/dkim -a -z "$DKIMVERIFY" ] ; then
if [ -z "$DKIMSIGN" ] ; then
- DKIMSIGN=/var/qmail/control/domainkeys/%/default
+# DKIMSIGN=/var/qmail/control/domainkeys/%/default
+ DKIMSIGN=/var/qmail/control/domainkeys/%
dkimsign=2
- elif [ " $DKIMSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+# elif [ " $DKIMSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+ elif [ " $DKIMSIGN" = " /var/qmail/control/domainkeys/%" ] ; then
dkimsign=2
fi
fi
@@ -132,7 +136,8 @@
if [ $dksign -eq 0 -a $percent_found -ne 1 ] ; then
exit 32
fi
- dkselector=`basename $dkkeyfn`
+# dkselector=`basename $dkkeyfn`
+ dkselector=$(cat $dkkeyfn/selector)
fi
if [ -z "$NODKIM" -a -n "$DKIMSIGN" ] ; then
if [ ! -f /var/qmail/bin/dkim ] ; then
@@ -153,10 +158,11 @@
else
dkimkeyfn=$DKIMSIGN
fi
- if [ $dkimsign -eq 2 -a ! -f $dkimkeyfn ] ; then
+ if [ $dkimsign -eq 2 -a ! -d $dkimkeyfn ] ; then
+ echo "here is $default_key"
dkimkeyfn=$default_key
fi
- if [ -f $dkimkeyfn ] ; then
+ if [ -d $dkimkeyfn ] ; then
dkimsign=1
else
dkimsign=0
@@ -164,7 +170,8 @@
if [ $dkimsign -eq 0 -a $percent_found -ne 1 ] ; then
exit 32 # private key does not exist
fi
- dkimselector=`basename $dkimkeyfn`
+# dkimselector=`basename $dkimkeyfn`
+ dkimselector=$(cat $dkimkeyfn/selector)
fi
if [ -z "$NODK" -a -n "$DKVERIFY" ] ; then
if [ ! -f /var/qmail/bin/dktest ] ; then
@@ -266,7 +273,8 @@
dkimopts="$dkimopts -y $dkimselector"
fi
if [ $sopt -eq 0 ] ; then
- dkimopts="$dkimopts -s $dkimkeyfn"
+# dkimopts="$dkimopts -s $dkimkeyfn"
+ dkimopts="$dkimopts -s $dkimkeyfn/$dkimselector"
fi
exec 0</tmp/dk.$$
eval $dkimopts
@@ -310,7 +318,8 @@
shift # next flag
done
if [ $sopt -eq 0 ] ; then
- dkopts="$dkopts -s $dkkeyfn"
+# dkopts="$dkopts -s $dkkeyfn"
+ dkopts="$dkopts -s $dkkeyfn/$dkselector"
fi
exec 0</tmp/dk.$$
eval $dkopts
root@postmanlian:/var/qmail/man/man8# --- /root/dk-filter 2022-09-26 15:08:30.492717661 -0400
+++ /var/qmail/bin/dk-filter 2022-09-26 17:17:42.888588987 -0400
@@ -88,17 +88,21 @@
fi
if [ -z "$NODK" -a -x /var/qmail/bin/dktest -a -z "$DKVERIFY" ] ; then
if [ -z "$DKSIGN" ] ; then
- DKSIGN=/var/qmail/control/domainkeys/%/default
+# DKSIGN=/var/qmail/control/domainkeys/%/default
+ DKSIGN=/var/qmail/control/domainkeys/%
dksign=2
- elif [ " $DKSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+# elif [ " $DKSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+ elif [ " $DKSIGN" = " /var/qmail/control/domainkeys/%" ] ; then
dksign=2
fi
fi
if [ -z "$NODKIM" -a -x /var/qmail/bin/dkim -a -z "$DKIMVERIFY" ] ; then
if [ -z "$DKIMSIGN" ] ; then
- DKIMSIGN=/var/qmail/control/domainkeys/%/default
+# DKIMSIGN=/var/qmail/control/domainkeys/%/default
+ DKIMSIGN=/var/qmail/control/domainkeys/%
dkimsign=2
- elif [ " $DKIMSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+# elif [ " $DKIMSIGN" = " /var/qmail/control/domainkeys/%/default" ] ; then
+ elif [ " $DKIMSIGN" = " /var/qmail/control/domainkeys/%" ] ; then
dkimsign=2
fi
fi
@@ -132,7 +136,8 @@
if [ $dksign -eq 0 -a $percent_found -ne 1 ] ; then
exit 32
fi
- dkselector=`basename $dkkeyfn`
+# dkselector=`basename $dkkeyfn`
+ dkselector=$(cat $dkkeyfn/selector)
fi
if [ -z "$NODKIM" -a -n "$DKIMSIGN" ] ; then
if [ ! -f /var/qmail/bin/dkim ] ; then
@@ -153,10 +158,11 @@
else

Reply |

Custom Selector

New combined patch with Manvendra's fresh fix published

Reply |

Custom Selector

Thanks to you both!!  will test later this week.

Reply |

Custom Selector

The correct file to change would be dk-filter.sh. dk-filter is auto-generated from dk-filter.sh after replacing QMAILHOME with value in conf-qmail.

You are right about the string 'default' is not getting stripped when a dkim key exists with the domain name in /var/qmail/control/domainkeys/yourdomain. This is what qmail-dkim does, but somehow I have missed this part in the shell version dk-filter.sh.

Thank you for bringing this to my attention. This is a bug. I will fix it by weekend and submit the fix to Roberto.

Reply |

Custom Selector

Thank you Manvendra,

Glad my diagnosis is correct.

In my research I note that DKIM is supposed to allow for multiple selectors per domain name, and I don't see a way to do that with dk-filter either.  I don't foresee needing this in my case, but I did put some thought into how to adjust the script to accommodate it just in case I ever need it.  Unfortunately, I don't really see a straightforward way, but might be worth considering if you are fixing things.

your work is admired and appreciated, thank you!

Reply |

Custom Selector

Take a look at having /var/qmail/control/dkimkeys. The format of this file is

domain:private_key_file_path

I find that I have not updated the dk-filter and qmail-dkim with dkimkeys control file.  This will be fixed in the next path that I will submit to Roberto by this weekend.

The basename of the private_key_file_path will be used as selector. dkim keys are supposed to be rotated/generated. You can have a cron script to generate new keys and and also generate the file /var/qmail/control/dkimkeys

Regarding the first issue that you reported, I did some testing and did find issues. I have fixed it and currently testing the script. 

I'm putting below the description of dkimkeys control file. I feel that will satisfy your requirement

       To sign a message, set the DKIMSIGN environment variable to the pathname of the private key that will be used to sign the message. If there is  a

       %  character in the environment variable, it is removed and replaced by the domain name in the From: header. The selector (s=) will be taken from

       the basename of the file. If, after substituting the %, that file does not exist, the % character will be removed to check if the file exists. In

       addition to DKIMSIGN environment variable, you can have the domain and the pathname of the private key in the control file dkimkeys which has the

       following format

       domain:private_key_path

       If an entry for domain exists in dkimkeys, the value of DKIMSIGN environment variable is ignored. domain can be a regular expression.

Reply |

Custom Selector

Hi Manvendra,

Okay, if I understand correctly, setting the DKIMSIGN variable requires that all domains use the same selector, as the only thing that can be substituted in the varilable is the domain name?  Different selectors for each domain name will require the control file?

I also understand that I will wait till next week so I can use the dkimkeys control file.  I am not clear from the example format; I think the format requires a full absolute path, like so:

testdomain.tld:/var/qmail/control/domainkeys/testdomain.tld/customselector

Is that correct?

Also; will using a control file require restarting the qmail service when it is updated?  or does it get read on the fly when dk-filter is executed?

Reply |

Custom Selector

> Okay, if I understand correctly, setting the DKIMSIGN variable requires that all domains use the same selector, as the only thing that can be substituted in  the varilable is the domain name?  Different selectors for each domain name will require the control file?

Correct

> I also understand that I will wait till next week so I can use the dkimkeys control file.  I am not clear from the example format; I think the format requires a full absolute path, like so:

testdomain.tld:/var/qmail/control/domainkeys/testdomain.tld/customselector

> Is that correct?t

Correct

Also; will using a control file require restarting the qmail service when it is updated?  or does it get read on the fly when dk-filter is executed?

You don't have to restart anything. It will be read on the fly when dk-filter is executed.

Reply |

Custom Selector

Hi Manvendra,

Understood, thank you.  I will wait till next week and talk to you then.

Reply |

Custom Selector

I just took a look at the code. The string default is never supposed to be removed. It is just the name of the selector.

So if I have DKIMSIGN=/var/qmail/control/domainkeys/%/myselector

Then if the domain is abcd.com following should happen

First the key /var/qmail/control/domainkeys/abcd.com/myselector will be checked. If it exists then the private key /var/qmail/control/domainkeys/abcd.com/myselector will be used. The selector will be myselector

If the file /var/qmail/control/domainkeys/abcd.com/myselector doesn't exist then the private key /var/qmail/control/domainkeys/myselector will be used as the private key file with the selector named as myselector.

If that too doesn't exist then /var/qmail/control/domainkeys/default will be used as the private key file with the selector named as default.

If you want specific keys for your domains you have to use the control file /var/qmail/control/dkimkeys. But unlike the DKIMSIGN variable, one has to have all your domains in this control file. Format of this control file is

domain:private_key_file_path

I will test all of these situations. Maybe something is wrong because of which it is not working for @computerisms

Reply |

Custom Selector

Hi, thanks for your contribution. Can you confirm that the solution described here (defining DKIMKEY) didn't work for you?

Reply |

Custom Selector

Hi Roberto,

To be honest, I didn't try the DIMKEY variable, because if I understand correclty it will still hardcode the selector, in that case as MyDKIM instead of as default, but please correct me if I am wrong.  In turn, that presumes that I will want the same selector across all domains, which if possible I won't.

If my patch is correct, the script will pull the value from the selector file, which allows for individual/unique selectors per domain, and should also allow scripted rotation of the selector if I want to do that, as well. 

But as mentioned, this is only in my sandbox, will see if I encounter problems once I add a few dozen domains.  In reading over my patch, I see I could have cleaned it up a bit more, will send a better copy in the future.

Reply |

"IndiMailfilter" command is missing?

I got following error from qmail-send with DKIM 

/var/qmail/bin/dk-filter:_(spawn-filter)_exit_code:_127:_IndiMailfilter:_applet_not_found/._(#4.3.0)spawn-filter_said:_Message_deferred

and It seems spawn-filter.c is trying to call "IndiMailfilter" comand that standard linux would not have.

# find . -type f | xargs grep -n "IndiMail"
./spawn-filter.c:267: execl("/bin/sh", "IndiMailfilter", "-c", filterargs, (char *) 0);

Is the command from https://github.com/mbhangui/indimail-virtualdomains?

Reply |

"IndiMailfilter" command is missing?

I've just asked Manvendra to take a look at this.

Reply |

IndiMailfilter command is missing?

This is Manvendra's reply:

IndiMailFilter is just argv[0]. It is not an actual program that is being called. It is what will appear in the ps -ef output. The actual program being executed is /bin/sh. I searched for the error applet not found and it is something to do if busybox is the shell. i.e. /bin/sh is linked to busybox. Ask the person to do

ls -l /bin/sh /usr/bin/sh

The output of the above command might give a clue.

Reply |

IndiMailfilter command is missing?

Thanks for replay. Indeed, my system is AlpineLInux Docker image that uses busybox.

# ls -l /bin/sh /usr/bin/sh
ls: /usr/bin/sh: No such file or directory
lrwxrwxrwx 1 root root 12 May 23 16:51 /bin/sh -> /bin/busybox

Reply |

IndiMailfilter command is missing?

So the dkim filter cannot work. I suggest to link another shell like bash, but I don't know if your system will be ok after that, or disable dkim

Reply |

IndiMailfilter command is missing?

Hi Roberto

Actually dkim filter can work with busybox. The problem is the "IndiMailfilter" argument,

which does not make any sense in spawn-filter.c. Busybox relies on argv[0] to be "/bin/sh".

The patch below is tested by myself, and works like a charm on busybox.

Based on your latest patch (2023.01.31), so it should cleanly apply.

--- netqmail-1.06-original/spawn-filter.c
+++ netqmail-1.06/spawn-filter.c
@@ -264,7 +264,7 @@
/*- Avoid loop if program(s) defined by FILTERARGS call qmail-inject, etc */
if (!env_unset("FILTERARGS") || !env_unset("SPAMFILTER"))
report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0);
- execl("/bin/sh", "IndiMailfilter", "-c", filterargs, (char *) 0);
+ execl("/bin/sh", "/bin/sh", "-c", filterargs, (char *) 0);
report(111, "spawn-filter: could not exec /bin/sh: ", filterargs, ": ", error_str(errno), ". (#4.3.0)", 0);
default:
close(pipefe[1]);

Reply |

IndiMailfilter command is missing?

Thank you for the hint.

btw I would stick with Manvendra's original patch, just to avoid patching a patch all the time

Reply |

IndiMailfilter command is missing?

As you wish. Maybe we can ask Manvendra to revise his code.

"IndiMailfilter" argument really does not make sense in spawn-filter.c.

Just search it in your combined patch, and you will see that it only appears once.

Therefore changing it to /bin/sh will not make things worse than they were before,

but it certainly fixes the problem in my Alpine docker image.

Regards

Ali Erturk TURKER

Reply |

IndiMailfilter command is missing?

yes, I'll ask him. Anyway I know that he is receiving these comments. These days I'm in touch with him because his new patch is on the way and he is looking for testers

Reply |

IndiMailfilter command is missing?

I'm getting the comments. The IndiMailfilter is actuall just the argv[0] which shows up in ps -ef listing. It is not the actuall command. The command is just /bin/sh. So if it is failing, it is probably because of /bin/sh is missing. On many systems, there is a move to remove /bin/sh. In fact when you generate RPMs on fedora, the RPM package creation replaces #!/bin/sh in shell scripts with #!/usr/bin/sh

If /bin/sh is missing just create a link to /usr/bin/sh or to busybox and you should be fine. Meanwhile I will test this on alpine and see what the issue is.

Reply |

IndiMailfilter command is missing?

Hİ Manvendra

Trust me /bin/sh is there, and is a symbolic link to /bin/busybox:

/ # file /bin/sh
/bin/sh: symbolic link to /bin/busybox

After hours of searching, I found that busybox relies on argv[0] to be "/bin/sh"

from this email. Then I checked the function arguments from this link

and tried the patch below and it solved the "applet" error:

--- netqmail-1.06-original/spawn-filter.c
+++ netqmail-1.06/spawn-filter.c
@@ -264,7 +264,7 @@
/*- Avoid loop if program(s) defined by FILTERARGS call qmail-inject, etc */
if (!env_unset("FILTERARGS") || !env_unset("SPAMFILTER"))
report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0);
- execl("/bin/sh", "IndiMailfilter", "-c", filterargs, (char *) 0);
+ execl("/bin/sh", "/bin/sh", "-c", filterargs, (char *) 0);
report(111, "spawn-filter: could not exec /bin/sh: ", filterargs, ": ", error_str(errno), ". (#4.3.0)", 0);
default:
close(pipefe[1]);

So, we can either ignore this issue and force Alpine users to install bash for no reason and bloat their docker images, or we can apply this simple patch and save many people from wasting hours like me.

I trust your common sense.

Regards,

Ali Erturk TURKER

Reply |

IndiMailfilter command is missing?

Thank you for letting me know that busybox returns error when argv[0] is not /bin/sh. I will make a change so that it works on the alpine docker image.

Reply |

IndiMailfilter command is missing?

Hi Roberto,

I have been reviewing your combined patch since last week.

It is really a masterpiece, but there is always room for improvement.

I'll be more than happy to test his code.

Regards,

Ali Erturk TURKER

Reply |

IndiMailfilter command is missing?

Thank you, Ali. It would be of no value without users' contributions and people like Manvendra and all the others. So feel free to post further fixes.

Manvendra will have the test patch ready in a couple of days and I'll let you know here. He is working on making the patch RFC 8463 compliant and testers are needed before final release

Reply |

IndiMailfilter command is missing?

I have uploaded the latest patch. This has the updated man page and should work for alpine docker images that has /bin/sh linked to busybox.

1. The testqmail-dks script tests signing + verification for both rsa and ed25519 signatures

2. The man pages have been updated

3. dkimkeys control file has been enhanced. You can set any environment variable using this control file. The format of this file is

regex_pattern_for_domain:private_key_file_path:comma_separated_env_variables

e.g. The below entry will make qmail-dkim use /var/qmail/control/domainkeys/example.org/dkimkeys2 as the private key file and set the hash encryption method to ed25519. It will unset env variable ABCD and set env variable EFGH=2

ex.*.org:/var/qmail/control/domainkeys/%/dkimkeys2:QREGEX=1,DKIMSIGNOPTIONS=-z 4,ABCD=,EFGH=2

https://sourceforge.net/projects/indimail/files/netqmail-addons/qmail-dkim-1.0/dkim-netqmail-1.06.patch-1.33.gz

CAUTION: qmail-dkim.c has significant changes and I forsee few bugs. Please let me know. Also If you can review the man pages for dkim and qmail-dkim it will be appreciated

Reply |

IndiMailfilter command is missing?

Hi All,

I have uploaded the latest patch as https://sourceforge.net/projects/indimail/files/netqmail-addons/qmail-dkim-1.0/dkim-netqmail-1.06.patch-1.32.gz

The patch also comes with testqmail-dks to test multiple methods and mixed signatures. You don't have to deply the DNS records to use testqmail-dks. The verification process in testqmail-dks directly uses the selector from the public key file.

I still have 2 things pending. I have to update the qmail-dkim and dkim man page. I will do it tomorrow. This patch adds new cryptographic method for DKIM-Signature. Earlier we just had RSA. This patch adds ED25519 method as detailed in https://www.rfc-editor.org/rfc/rfc8463.

AFAIK no one at present is signing using this method.

Ed25519 public keys are 256 bits long, the base64-encoded
   key is only 44 octets, so DNS key record data will generally fit in a
   single 255-byte TXT string and work even with DNS provisioning
   software that doesn't handle multistring TXT records.
Signers SHOULD implement and verifiers MUST implement the
   Ed25519-SHA256 algorithm
For backward compatibility, signers can add multiple signatures that
   use old and new signing algorithms.  Since there can only be a single
   key record in the DNS for each selector, the signatures have to use
   different selectors, although they can use the same d= and i=
   identifiers.

qmail-dkim can add signatures for both. You will have to set DKIMSIGNEXTRA and DKIMSIGNOPTIONSEXTRA. The updated man pages are available for reading below. I will update the same on the patch as soon as possible

https://github.com/mbhangui/indimail-mta/wiki/qmail-dkim.8 

and

https://github.com/mbhangui/indimail-mta/wiki/dkim.8 

Reply |

IndiMailfilter command is missing?

Installing bash and link /bin/sh to /bin/bash solved this issue. Thanks.

Reply |

compiling netqmail with tls and dkim support

hello guys, I'm trying to compile netqmail by applying the tls and dkim patch, I'm using the following patches

https://notes.sagredo.eu/files/qmail/patches/dkim/dkim-netqmail-1.06.patch-1.28 
https://notes.sagredo.eu/files/qmail/patches/tls/netqmail-1.06-tls-20200107.patch

I applied the tls patch first and then fixed the dkim patch to work on the netqmail code patched with the tls patch. However when executing make it generates the following error

https://paste.ubuntu.com/p/k6jv42gyvK

```
./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a `cat socket.lib`
./compile qreceipt.c
./load qreceipt headerbody.o hfield.o quote.o token822.o \
qmail.o getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a \
substdio.a error.a str.a auto_qmail.o
qmail.o: In function `qmail_open':
/packages/v2/libdomainkeys-0.69/netqmail-1.06/qmail.c:50: undefined reference to `scan_int'
collect2: error: ld returned 1 exit status
make: *** [Makefile:1737: qreceipt] Error 1
[root@qmail netqmail-1.06]#
```

Any idea?

Reply |

Unable to read private key

Hi, i have the following issue for the last few days. It appeared after I tried to install simscan. Can you advise? It used to work before.

@400000005f1744850b64bd8c qlogreceived: result=rejected code=451 reason=queuedelay detail=qmail-dkim:_Unable_to_read_private_key._(#4.3.0) 
helo=Sags-MacBook-Pro-A1990.local mailfrom=kliment.toshkov@netfinity.bg rcptto=kt@netfinity.bg relay=yes rcpthosts= size=1016
authuser=kliment.toshkov@netfinity.bg authtype=plain encrypted=tls sslverified=no localip=194.153.118.30 localport=587
remoteip=10.6.6.8 remoteport=62916 remotehost= qp=29305 pid=29301

Reply |

Unable to read private key

Hi, check the owner of /usr/local/etc/domainkeys/netfinity.bg/ folder. If you are signing at qmail-remote level it should be owned by qmailr:qmail, if you are signing at qmail-smtpd level it should be owned by vpopmail:vchkpw

Reply |

DKIMVERIFY documentation

The letters present in the DKIMVERIFY variable indicate which tests must be considered to reject an email, as follows:

A - DKIM_SUCCESS - Function executed successfully
B - DKIM_FINISHED_BODY - process result: no more message body is needed
C - DKIM_PARTIAL_SUCCESS - verify result: at least one but not all signatures verified
D - DKIM_NEUTRAL - verify result: no signatures verified but message is not suspicious
E - DKIM_SUCCESS_BUT_EXTRA - signature result: signature verified but it did not include all of the body
F - DKIM_3PS_SIGNATURE - 3rd-party signature
G - DKIM_FAIL - Function failed to execute
H - DKIM_BAD_SYNTAX - signature error: DKIM-Signature could not parse or has bad tags/values
I - DKIM_SIGNATURE_BAD - signature error: RSA verify failed
J - DKIM_SIGNATURE_BAD_BUT_TESTING - signature error: RSA verify failed but testing
K - DKIM_SIGNATURE_EXPIRED - signature error: x= is old
L - DKIM_SELECTOR_INVALID - signature error: selector doesn't parse or contains invalid values
M - DKIM_SELECTOR_GRANULARITY_MISMATCH - signature error: selector g= doesn't match i=
N - DKIM_SELECTOR_KEY_REVOKED - signature error: selector p= empty
O - DKIM_SELECTOR_DOMAIN_NAME_TOO_LONG - signature error: selector domain name too long to request
P - DKIM_SELECTOR_DNS_TEMP_FAILURE - signature error: temporary dns failure requesting selector
Q - DKIM_SELECTOR_DNS_PERM_FAILURE - signature error: permanent dns failure requesting selector
R - DKIM_SELECTOR_PUBLIC_KEY_INVALID - signature error: selector p= value invalid or wrong format
S - DKIM_NO_SIGNATURES - no signatures
T - DKIM_NO_VALID_SIGNATURES - no valid signatures
U - DKIM_BODY_HASH_MISMATCH - sigature verify error: message body does not hash to bh value
V - DKIM_SELECTOR_ALGORITHM_MISMATCH - signature error: selector h= doesn't match signature a=
W - DKIM_STAT_INCOMPAT - signature error: incompatible v=
X - DKIM_UNSIGNED_FROM - signature error: not all message's From headers in signature

For example, if you want to permanently reject messages that have a signature that is expired, include the letter 'K' in the DKIMVERIFY environment variable.

A conservative set of letters is FGHIKLMNOQRTUVWjp. Reject permanently 3PS, FAILURE, SYNTAX, SIGNATURE_BAD, SIGNATURE_EXPIRED, SELECTOR_INVALID, GRANULARITY_MISMATCH, SELECTOR_KEY_REVOKED, DOMAIN_NAME_TOO_LONG, SELECTOR_PUBLIC_KEY_INVALID, NO_VALID_SIGNATURES and BODY_HASH_MISMATCH errors, and temporarily SIGNATURE_BAD_BUT_TESTING and DNS_TEMP_FAILURE.

Add in S if you want to reject messages that do not have a DKIM signature. You can use the control files signaturedomains and nosignature domains (See Below) to further fine tune the action to be taken when a mail arrives with no DKIM signature. Note that qmail-dkim always inserts the DKIM-Status header, so that messages can be rejected later at delivery time, or in the mail reader. In that case you may set DKIMVERIFY to an empty string. If you want to check all message's From header in signature set the UNSIGNED_FROM environment variable to an empty string. If you want to check messages without signed subject header, set UNSIGNED_SUBJECT environment variable. If you want to honor body lengh tag (l=), set HONOR_BODYLENGTHTAG environment variable.

Reply |

DKIMVERIFY documentation

man qmail-dkim for latest documentation on the purpose

Reply |

djbdns and DKIM recorder builder

Hello again Roberto,

Google is my friend !
;-)

I found Recorder Builder for djbdns https://andersbrownworth.com/projects/sysadmin/djbdnsRecordBuilder/

We can give djbdns sintax for DKIM

Marco Varanda

(Brazil)

Reply |

SPF, DKIM and DMARC

I would really recommend to set up the full stack: SPF, DKIM, and DMARC. No one should send emails without having this configuration ready. The mentions tools in the article to verify DKIM are great, but for this purpose, I use another free tool from https://www.emailchecky.com/en/ because it has more features and also offers a very handy all-in-one analysis for emails.

Reply |

SPF, DKIM and DMARC

These topics are all covered here, DMARC is presented in the spamassassin section, SPF is inside the Configuring page.

If I understand the scarse documentation of the page you suggest, this tool seems just like an external tool where to redirect private msg and personal data in order to validate the email. Not a  good idea.

Reply |

DMARC

Hello,

I know this topic is reserved for DKIM but do you intend to write something about DMARC as well?

Did you found any posibility to implement DMARC? Apparently there is something possible with qpsmtp and opendmarc , a plugin support in spamassassin(i find it in a very incipent way) or implemented via spamassassin AskDNS like it's presented on my blog.

Do you have any other ideeas?

Reply |

DMARC

Iulian, you may want to take a look at this fix for the askDNS rule here

Reply |

DMARC

Finally I added a page on DMARC with AskDNS here. Thanks for your contribution

Reply |

DMARC

Hi Iulian,

I implemented a DMARC filter for incoming mails; maybe it's of use to you: https://github.com/fany/App-Qmail-DMARC

Regards
Martin

Reply |

DMARC

I don't have plans to write anything concerning DMARC filters, as I'm not familiar with them yet.

Anyway I would not consider qpsmtp as a good option, since I don't like the idea of completely replace my qmail-smtpd. I would play with a spamassassin plugin like the one that you suggest in your blog, when I'll have the time

Reply |

PID Process with DKIM + Simscan

Hello,

I've noticed that when chaining dkim with simscan the pid of the process changes in simscan.

QMAILQUEUE="/var/qmail/bin/surblqueue",SURBLQUEUE="/var/qmail/bin/qmail-dkim",DKIMQUEUE="/var/qmail/bin/simscan"

This is bad when it comes to processing the logs

2019-06-24 16:23:35.203214500 tcpserver: pid 2639 from 192.168.200.164 - Procedencia:
2019-06-24 16:23:35.203215500 tcpserver: ok 2639 desmx1.mydomain.com:192.168.200.165:25 :192.168.200.164::38536
2019-06-24 16:23:35.205136500 qmail-smtpd 2639: connection from 192.168.200.164 (unknown) to desmx1.mydomain.com
2019-06-24 16:23:35.205137500 qmail-smtpd 2639: enabled options: max msg size: 25000000 starttls relayclient sanitycheck sendercheck qmailqueue /var/qmail/bin/simscan
2019-06-24 16:23:35.206499500 qmail-smtpd 2639: remote ehlo: friend.mydomain.com
2019-06-24 16:23:35.207420500 qmail-smtpd 2639: mail from: me@test.mydomain.com
2019-06-24 16:23:35.207420500 qmail-smtpd 2639: sender verify, sender not in goodmailaddr
2019-06-24 16:23:35.207421500 qmail-smtpd 2639: sender verify, sender is local
2019-06-24 16:23:35.215157500 qmail-smtpd 2639: sender verify OK
2019-06-24 16:23:35.216389500 qmail-smtpd 2639: rcpt to: someaccount@gmail.com
2019-06-24 16:23:35.218563500 qmail-smtpd 2639: go ahead
2019-06-24 16:23:35.220986500 simscan:[2642]: calling clamdscan
2019-06-24 16:23:35.232338500 simscan:[2642]: normal clamdscan return code: 0
2019-06-24 16:23:35.232340500 simscan:[2642]: calling /home/vmail/spam/Mail-SpamAssassin/bin/spamc -d localhost -p 10783 -u simscan@test.mydomain.com -c -s 5000000
2019-06-24 16:23:35.359233500 simscan:[2642]:Mensaje en Salida ==> NO SPAM: [0.000000,8.000000]
2019-06-24 16:23:35.359235500 simscan:[2642]:CLEAN (0.00/8.00):0.1407s::192.168.200.164:me@test.mydomain.com:someaccount@gmail.com
2019-06-24 16:23:35.366057500 simscan:[2642]: qmail-queue exited 0
2019-06-24 16:23:35.366342500 qmail-smtpd 2639: message queued: 1561386215 qp 2641 size 287 bytes
2019-06-24 16:23:35.366890500 qmail-smtpd 2639: quit, closing connection
2019-06-24 16:23:35.367126500 tcpserver: end 2639 status 0

Any ideas?

Regards

Reply |

PID Process with DKIM + Simscan

This is because simscan goes in a sub-process. the simscan pid is bounded to its parent ppid in the email header, for example

Received: (simscan 1.4.0 ppid 8424 pid 8429 t 0.1287s) (scanners:

Reply |

dk-filter: choosing the signing domain

I don't get it: dk-filter states: "dk-filter uses the domain found in the Sender: header to set the domain tag. If not it uses the From: header."

But when I test it and also when reading its code, I find no evidence that the From: header would ever be considered. Thus, bounce messages do not get signed, which according to my understanding of RFC 7489 they should for a correct DMARC alignment.

In fact, when _SENDER is empty, dk-filter seems to use /var/qmail/control/domainkeys/default if present. However, this also does not work as intended, because "d=" has en empty value then, and forwarded bounce messages from foreign domains will also get signed, which is obviously not desirable.

Am I holding it wrong, or is the documentation / code just incorrect?

Regards
Martin

Reply |

dk-filter: choosing the signing domain

Ah. I see what you meant by the following

"I don't get it: dk-filter states: "dk-filter uses the domain found in the Sender: header to set the domain tag. If not it uses the From: header."

But when I test it and also when reading its code, I find no evidence that the From: header would ever be considered. Thus, bounce messages do not get signed, which according to my understanding of RFC 7489 they should for a correct DMARC alignment."

For bounce messages, since the from/sender will be null, you can set the DKIMDOMAIN environment variable in the script which starts up qmail-send. DKIMDOMAIN also overrides anyting in the From: or Sender: header.

Reply |

dk-filter: choosing the signing domain

I am wrong about DKIMDOMAIN in my earlier reply. DKIMDOMAIN env variable doesn't override the From: or Sender: header value. It is used only if From and Sender are both null (like in case of bounce). Here is the code in dkimsign.cpp

if (sDomain.empty()) {
  p = getenv("DKIMDOMAIN");
  if (p && *p)
  { 
    if (!(at = strchr(p, '@')))
      at = p;
    else
      at++;
    sDomain.assign(at);
  } else
    sDomain.assign(sAddress.c_str() + pos + 1);
  RemoveSWSP(sDomain);
}

Reply |

dk-filter: choosing the signing domain

dk-filter uses _SENDER, _RECIPIENT env variable which is set by spawn-filter. spawn-filter is a program that gets called by qmail-lspawn when QMAILLOCAL is set to /var/qmail/bin/spawn-filter for local deliveries. It also gets called by qmail-rspawn for remote deliveries when you set QMAILREMOTE env variable to /var/qmail/bin/spawn-filter. the spawn-filter than gathers all information like the sender and recipient. It then calls whatever program is defined by FILTERARGS env variable. The input to FILTERARGS is the original email and the output of the FILTERARGS is fed to qmail-local for local deliveries and qmail-remote for remote deliveries. The real workhorse for DKIM verfication and signing is not the dk-filter program. It is actually the binary /var/qmail/bin/dkim which does the actual work using the libdkim library.

Check out the man pages for spawn-filter, dkim, dk-filter, qmail-lspawn, qmail-rspawn to know more. My documenation may not be good and could use some help there (especially things that you find it wrong or do not understand).

If you set DKIMVERIFY env variable for qmail-send, then dk-filter will not do signing. Hence bounce messages will not get signed. But one can do the following - do DKIM verification for local deliveries and DKIM Signing for remote deliveries by having two entires in /var/qmail/control/filterargs

*:remote:env DKIMSIGN=/var/qmail/control/domainkeys/%/default /var/qmail/bin/dk-filter
*:local:env DKIMVERIFY=1 /var/qmail/bin/dk-filter

In my setup, I do DKIM verification during the SMTP transaction and DKIM signing during remote deliveries.

Maybe you could describle what you want to achieve with examples and I could work out a solution which will work for you

Reply |

dk-filter: choosing the signing domain

Hi Mandreva,

thanks for your answers!

What I am trying to achieve is that all outgoing e-mail which has our domain in its RFC5322.From address (and thus a corresponding /var/qmail/control/domainkeys/$domain/default key file exists) gets a DKIM signature, whereas other messages (e.g. those which came from remote and get forwarded to other remote addresses) are left untouched.

In /var/qmail/supervise/qmail-send/run I have:

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`"

In practice this works for "normal" messages, but only because their RFC5322.From is usually identical to their RFC5321.MailFrom address, and the latter is contained in the environment variable _SENDER when dk-filter gets invoked. For bounce messages however, the RFC5321.MailFrom address is empty, thus _SENDER is empty, which causes dk-filter to fall back to /var/qmail/control/domainkeys/default – but then, it cannot correctly distinguish between bounce messages generated by our system and foreign bounce messages which should only get forwarded, but not signed.

So, to cut it short, the IMHO correct solution would be to use the RFC5322.From address for choosing the key, either always or at least when the RFC5321.MailFrom is empty.

According to dk-filter(8), "dk-filter uses the domain found in the Sender: header to set the domain
tag. If not it uses the From: header." What is meant by "If not it uses the From: header"? I understand it as: If there is no sender, then it uses the From: header, that is the RFC5322.From (for choosing the signing key to use). But I cannot see that it would really do that. So either I misunderstand the documentation, or the documentation does not match the actual behaviour of dk-filter.

Or are you trying to explain that the _SENDER environment variable which dk-filter uses to select the key should already be set to the RFC5322.From by a component earlier in the call chain? If yes, which component would that be and how would one achieve this?

BTW, in the meantime I've patched dk-filter to do an appropriate lookup, so it works for me now. I just wonder if there is a better solution.

Reply |

dk-filter: choosing the signing domain

Yes. The _SENDER environment variable which dk-filter uses is already set by spawn-filter earlier in the call chain.

Howerver this is NULL for bounces, eventhough the RFC5233.From will be mailer-daemon@bounce_domain. The bounce_domain will be a value set by qmail-send from /var/qmail/control/me

Looks like I have understood your problem and that problem will be there for all users. There are two issues. The first issue isn't really the blocker. The blocker is the wrong key being used for signing by the dk-filter script when the _SENDER env variable is NULL.

1. the libdkim library uses the following logic

  if (!sReturnPath.empty())
    sAddress.assign(sReturnPath);
  else
  if (!sSender.empty())
    sAddress.assign(sSender);
  else
  if (!sFrom.empty())
    sAddress.assign(sFrom);
  else
   return false;

This implies that it uses the envelope from address first for signing the domain. This should be like this

  if (!sSender.empty())
   sAddress.assign(sSender);
  else
  if (!sFrom.empty())
    sAddress.assign(sFrom);
  else
  if (!sReturnPath.empty())
    sAddress.assign(sReturnPath);
  else
    return false;

2. The sender/from address comes from the _SENDER environment variable. This variable is set by spawn-filter program

The spawn-filter gets this from the command line arguments passed to qmail-local / qmail-remote by qmail-lspawn, qmail-rspawn respectively. For bounces, this will be NULL. The problem is that dk-filter falls back to using /var/qmail/control/domainkeys/default.

One way to solve this is to use /var/qmail/control/me as the signing domain for bounces as the bounce will be from MAILER-Daemon@. The other solution is to define your default DKIM key in dk-filter rather than using a hardcoded  var/qmail/control/domainkeys/default

I am contemplating at using an environment variable DEFAULT_DKIM_KEY which dk-filter will use in such cases. You can set DEFAULT_DKIM_KEY like this

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

Reply |

Problem using a selector different than default

Hi

Finally I have all working, but I decided not to use "default" as "default" selector
I used domainkey to generate the key

# domainkey my_domain.com MYdkim

I have in usr/local/etc/domainkeys/my_domain.com

default -> /usr/local/etc/domainkeys/my_domain.com/rsa.private_MYdkim
rsa.private_MYdkim
rsa.public_MYdkim
selector

# cat /usr/local/etc/domainkeys/my_domain.com/selector
MYdkim

Inside the DNS I added a txt as folow

MYdkim._domainkey.my_domain.com. IN TXT "v=DKIM1; k=rsa; t=y; p=xxxxxxxxxx"

I'm using qmail-smtpd for signing outgoing messages
The messages are signed, but with the wrong "CNAME"

I sent an email to "auth-results@verifier.port25.com" and I have this answer

DKIM check details:
----------------------------------------------------------
Result: permerror (key "default._domainkey.mydomain.com" doesn't exist)

Any idea where is the error ?

Reply |

Problem using a selector different than default

strange... what happens if you verify your own message with gmail or even your own server?

Reply |

Problem using a selector different than default

Thank you for bringing this to my attention. I will work on this and provide a fix ASAP. Give me some time till weekend.

Reply |

Problem using a selector different than default

More tests
Now, with my domain
I made few changes to fit my configurations

I changed the location for domainkeys to other folder where I have all the configs
I made a ln -s for /usr/local/etc/domainkeys to the new domainkeys folder
I configured qmail-smtpd for signing outgoing messages

/var/qmail/supervise/qmail-smtpd/run

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMKEY=/web/conf/domainkeys/%/default

I created a new domainkey for pablomurillo.com.ar with RNAdkim as "selector"

# ls -l /web/conf/domainkeys/pablomurillo.com.ar/
total 12
lrwxr-xr-x 1 vpopmail vchkpw 60 Feb 14 12:41 default -> /web/conf/domainkeys/pablomurillo.com.ar/rsa.private_RNAdkim
-rw------- 1 vpopmail vchkpw 887 Feb 14 12:41 rsa.private_RNAdkim
-rw------- 1 vpopmail vchkpw 272 Feb 14 12:41 rsa.public_RNAdkim
-rw------- 1 vpopmail vchkpw 8 Feb 14 12:41 selector

# cat /web/conf/domainkeys/pablomurillo.com.ar/selector
RNAdkim

Test to check-auth@verifier.port25.com

DKIM check details:

Result: permerror (key "default._domainkey.pablomurillo.com.ar" doesn't exist)
ID(s) verified:

Canonicalized Headers:
message-id:<C39E4713200C4EC8801981F69B885FE3@killer1>'0D''0A'
from:"Pablo'20'Murillo"'20'<info@pablomurillo.com.ar>'0D''0A'
to:<check-auth@verifier.port25.com>'0D''0A'
subject:test'0D''0A'
date:Thu,'20'14'20'Feb'20'2019'20'12:52:18'20'-0300'0D''0A'
mime-version:1.0'0D''0A'
content-type:text/plain;'20'format=flowed;'20'charset="iso-8859-1";'20'reply-type=original'0D''0A'
content-transfer-encoding:7bit'0D''0A'
x-mailer:Microsoft'20'Outlook'20'Express'20'6.00.2900.5931'0D''0A'
dkim-signature:v=1;'20'a=rsa-sha1;'20'c=relaxed/relaxed;'20'd=pablomurillo.com.ar;'20's=default;'20'x=1550764320;'20'h=Message-ID:'20'From:To:Subject:Date:MIME-Version:Content-Type:'20'Content-Transfer-Encoding:X-Mailer;'20'bh=2jmj7l5rSw0yVb/vlWAYkK/YB'20'wk=;'20'b=

Canonicalized Body:

DNS record(s):
default._domainkey.pablomurillo.com.ar. TXT (NXDOMAIN)

NOTE: DKIM checking has been performed based on the latest DKIM specs
(RFC 4871 or draft-ietf-dkim-base-10) and verification may fail for
older versions. If you are using Port25's PowerMTA, you need to use
version 3.2r11 or later to get a compatible version of DKIM.

-------------------------------------------------------------------------------------------------------------------

Test to gmail:
-------------------------------------------------------------------------------------------------------------------

Authentication-Results: mx.google.com;
dkim=temperror (no key for signature) header.i=@pablomurillo.com.ar header.s=default header.b=uEm6qI0Z;
spf=pass (google.com: domain of info@pablomurillo.com.ar designates 190.224.160.64 as permitted sender) smtp.mailfrom=info@pablomurillo.com.ar
Received: (qmail 24866 invoked by uid 0); 14 Feb 2019 12:52:00 -0300
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
d=pablomurillo.com.ar; s=default; x=1550764320; h=Message-ID:
From:To:Subject:Date:MIME-Version:Content-Type:
Content-Transfer-Encoding:X-Mailer; bh=/edzoYuyn17WXm8KeqcX/R+kh
dQ=; b=uEm6qI0ZdhmeJ3mEdyjl62sLwHk23D9mpcD07AoNw39Hg8pXx+oBkL/sV
r8iTGVLz+irfaRXCDrfa57421fLrgGUgMaxkFjVvqqUii6UQVmXknCTwT9mlSAIV
feFvejzyC2Mz90vIdA4gESV/Bd6xYsdPb64yDseZ1ZMcHqqq1U=

If I use something different as default for selector don´t work

I checked DKIM on DNS with : https://dkimcore.org/tools/keycheck.html and it's OK

I think that qmail-dkim is not "reading" the selector file to make de DKIM signature

"DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
d=pablomurillo.com.ar; s=default; x=1550765686; h=Message-ID:"

"s=" is allways "default"

Reply |

Problem using a selector different than default

Hi,

file: /var/qmail/bin/dk-filter

modify #90 line:

dkselector=`basename $dkkeyfn`  => dkimselector=$(<"${dkimkeyfn/default/selector}")

and rebulid domainkeys

Reply |

Problem using a selector different than default

Sorry!

file: /var/qmail/bin/dk-filter

modify #124 line:

dkimselector=`basename $dkimkeyfn`  => dkimselector=$(<"${dkimkeyfn/default/selector}")

You don't need to rebuild domainkeys.

Reply |

Problem using a selector different than default

The result for gmail es a failure too

Authentication-Results: mx.google.com;
dkim=temperror (no key for signature) header.i=@my_domain.com header.s=default header.b=Kf3SBDLh;

Received: (qmail 51868 invoked by uid 0); 14 Feb 2019 01:38:29 -0300
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=my_domain.com;
s=default; x=1550723909; h=MIME-Version:Content-Type:Date:From:
To:Subject:Message-ID:User-Agent; bh=Kxb4hoiPtpyfLSNHnDfG2he0CLo
=; b=Kf3SBDLhRSnVuRb8tOJxpuTvbGO7/iX6Sl8zlNiSKbitvLQ+CUfPvc3K9Tr
thoKI7qrGgLQAl/0/k8WEyqdSaZi+VanX852bYnnAqhrOilo396xZqHJghhI+oML
mVZ9WgIjOhspY8X5NIStKcmy/Om+4+5JyoATS9BWjqbVVTco=

I created a new domainkey with "default" as selector, and everything works good

Authentication-Results: mx.google.com;
dkim=pass (test mode)

I wil made more test with more domains to see if the problem persist

Reply |

Problem using a selector different than default

So you want your selector to be MYdkim

This is what you should do. Remember that the selector is always taken from the basename of the file that the environment variable DKIMKEY is set to.

If the last component of the path is 'default', the selector will be default. If the last component is MYdkim, the selector will by MYdkim.

So your private key should be named MYdkim. i.e.

/web/conf/domainkeys/pablomurillo.com.ar/MYdkim

The file MYdkim can be a symbolic link too to the filename of your choice.

and your public key could be named anything as it is not used internally by qmail-dkim

/var/qmail/supervise/qmail-smtpd/run

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMKEY=/web/conf/domainkeys/%/MYdkim

Reply |

Problem using a selector different than default

Hi

I'm doing that
After read a little I discovered the "problem"
Is not the best way if you need to use more than one "selectors"
The right solution is read the selector file , but my C is not as good as I like to do this

Reply |

Problem using a selector different than default

Ok, let me know. I'll do some tests when I find some time and eventually inform M.Bhangui

Reply |

Problem using a selector different than default

Finally !, I found the solution
I think, is not the best , but ...
The selector is taken from "DKIMKEY" , so I changed DKIMKEY in qmail-smptd/run to :
DKIMKEY=/web/conf/domainkeys/%/RNAdkim

Also, I changed the "ln -s" of "rsa.public_RNAdkim" from "default" to "RNAdkim"

Is a solution, not the right one for me, because if you plan to use different selectors, this will be a problem

I think that the right behavoir will be read the "selector" file, not use the "name" of the "symbolic link"

Reply |

Problem using a selector different than default

Great. 

Anyway, as you may have noticed, Manvendra Bhangui will take a look at this in the w/e https://notes.sagredo.eu/en/qmail-notes-185/configuring-dkim-for-qmail-92.html#comment1230

Reply |

usage 2038 keys

can you change script domainkey to usage 2048 keys ?

Reply |

usage 2038 keys

Hi,

1. modify domainkey file:

openssl genrsa -out $CONFIGDIR/$1/rsa.private_$SELECTOR 1024

to

openssl genrsa -out $CONFIGDIR/$1/rsa.private_$SELECTOR 2048

2. modify dk-filter file:

if [ $zopt -eq 0 ] ; then
    dkimopts="$dkimopts -z 1"
fi

to 

if [ $zopt -eq 0 ] ; then
    dkimopts="$dkimopts -z 2"
fi

or use DKIMSIGNOPTIONS option

3. rebuild domainkeys

4. settings dns

Reply |

usage 2038 keys

thank you

to have such a long dns record under bind I had to split the domainkey as follows

default._domainkey.mydomain.tld. IN TXT ("v=DKIM1\; k=rsa\; t=y\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQZJmKV9pModJLj0fWPTYV8JTYkqp8Jb+nxSGmYjKvdDNgk26Uc7GYghF/lWxa8kXBxfbYmtr1vBUi2BIOK3ijIDntKqGJaljSyJSAh7SESbG6ob+45uF1V9gYMA4Lk1x/pMeExLR6f7qfKwoT"
"dRRw4BVs1aHy2iUZOJpHXD1hWG99AhbozhZVTgdCopqU3lFEYlpVQ/YdqiNmZpc04BVyOTG71VOCdm+MuCFpQYckWmxJIh8WFhaCDlIByE88uAupp+28538V9HSWIi3CIigQmD/OIQ/XwaXA7uO0VBEWw7+F1cAfvPdTTl/gal1EMg1FXdBq2ZVJVxHyZZs4H5KQIDAQAB")

so that each line doesn't exceed 256 chars lenght

I tested this sending a test mail to check-auth@verifier.port25.com and the verification was good. Unfortunately a test against gmail failed (verification failure) so I'm sticking with 1024 keys.

Any hint would be appreciated

Reply |

usage 2038 keys

Hi,

Gmail is no problem!

My dns:

20190420._domainkey.chcode.com. IN TXT "v=DKIM1\; k=rsa\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsDfmZGeRoC3QINDAeTm5P8YPgRPsBu/9puMaF6kUj7M47iJqmN8S6B60vvBCr0HOCqhiTnrq7hBdf+c3BjG8YKWcQMfFy6UqaBipm3crjwQ++4Vgg4t38T0SZ88" "FoI1AUw7RZYbixAE0DbSzZ Ur5cHUGwV/t5GnWekDvwadiEp1T87xZdBEU7XHELR+d0Wq7PbnQVdybWL+bqxpYsclbYacxtxSNCUlOC6vSdQBinJ6JCr/8o9xg00C/jNC+ZOdLBIi6AOIH+tBVPnos0DE1UVzZhK4iXALxTZAQ4cpBSqOJqACSMo6JGaWikb15ow/HQEXYC6gW/DCM8T1CQ1SlLQIDAQAB"

Reply |

usage 2038 keys

I've followed this howto concerning the long dns splitting and I'm still unable to pass the gmail dkim test.

In addition, sending a test mail to check-auth@verifier.port25.com results in a wrong dns record interpretation (note the default._domainkey.mydomain.tld. IN TXT inside):

default._domainkey.mydomain.tld. 60 IN TXT "v=DKIM1; k=rsa; t=y; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAopYfx74JYL12O5i8RJ1GqYxkbkTf9MXkeJ/4RLxJGrKLpGlYnFuKfAH8dZAtIqOpvaai9ipG/6kw2Sj7Ss6/qkutvdbfnKIl/9RsGws/xq3jCf9Zc19V0Zeo96FZI0PuvKqAKKxQar4j8WJ+eN1ahxe3default._domainkey.pacinotti.edu.it.INTXT5hUIiYCnmx3Y80JXj89Qwie1l5G5xDl7jLICXa+kZJF+orfQ8KH0HURCmUCrRwJTvuTHI+zSgUcrjgrJnQjCkqkMhy3LAy/ybfAZnaYozloaqIoGZOeas4+X/O97OHhSq5EIRPLtJtyEFJ8WMbpDD7kql8ztS6jMulhIUjHZNBwcgnU0bSw2mO9nu8uxLwIDAQAB"

while my dkim record(s) is

default._domainkey.mydomain.tld. IN TXT ("v=DKIM1\; k=rsa\; t=y\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAopYfx74JYL12O5i8RJ1GqYxkbkTf9MXkeJ/4RLxJGrKLpGlYnFuKfAH8dZAtIqOpvaai9ipG/6kw2Sj7Ss6/qkutvdbfnKIl/9RsGws/xq3jCf9Zc19V0Zeo96FZI0PuvKqAKKxQar4j8WJ+eN1ahxe3"
default._domainkey.mydomain.tld. IN TXT "5hUIiYCnmx3Y80JXj89Qwie1l5G5xDl7jLICXa+kZJF+orfQ8KH0HURCmUCrRwJTvuTHI+zSgUcrjgrJnQjCkqkMhy3LAy/ybfAZnaYozloaqIoGZOeas4+X/O97OHhSq5EIRPLtJtyEFJ8WMbpDD7kql8ztS6jMulhIUjHZNBwcgnU0bSw2mO9nu8uxLwIDAQAB")

Note that check-auth@verifier.port25.com was not complaining when setting my dns like this

default._domainkey.mydomain.tld. IN TXT ("v=DKIM1\; k=rsa\; t=y\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAopYfx74JYL12O5i8RJ1GqYxkbkTf9MXkeJ/4RLxJGrKLpGlYnFuKfAH8dZAtIqOpvaai9ipG/6kw2Sj7Ss6/qkutvdbfnKIl/9RsGws/xq3jCf9Zc19V0Zeo96FZI0PuvKqAKKxQar4j8WJ+eN1ahxe3"
"5hUIiYCnmx3Y80JXj89Qwie1l5G5xDl7jLICXa+kZJF+orfQ8KH0HURCmUCrRwJTvuTHI+zSgUcrjgrJnQjCkqkMhy3LAy/ybfAZnaYozloaqIoGZOeas4+X/O97OHhSq5EIRPLtJtyEFJ8WMbpDD7kql8ztS6jMulhIUjHZNBwcgnU0bSw2mO9nu8uxLwIDAQAB")

On the contrary mxtoolbox.com tests are ok

Reply |

usage 2038 keys

Hi,

My case:

send mail to gmail: fail

after 10minutes: fail

after 30minutes: pass

after 1hour: pass

after 1day: pass

I think, you're dns is correct.

Reply |

usage 2038 keys

Great, gmail verification passed!

My dns is like this:

default._domainkey.mydomain.it. IN TXT ("v=DKIM1\; k=rsa\; t=y\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAopYfx74JYL12O5i8RJ1GqYxkbkTf9MXkeJ/4RLxJGrKLpGlYnFuKfAH8dZAtIqOpvaai9ipG/6kw2Sj7Ss6/qkutvdbfnKIl/9RsGws/xq3jCf9Zc19V0Zeo96FZI0PuvKqAKKxQar4j8WJ+eN1ahxe3"
"5hUIiYCnmx3Y80JXj89Qwie1l5G5xDl7jLICXa+kZJF+orfQ8KH0HURCmUCrRwJTvuTHI+zSgUcrjgrJnQjCkqkMhy3LAy/ybfAZnaYozloaqIoGZOeas4+X/O97OHhSq5EIRPLtJtyEFJ8WMbpDD7kql8ztS6jMulhIUjHZNBwcgnU0bSw2mO9nu8uxLwIDAQAB")

I'm signing at qmail-remote level adding DKIMSIGNOPTIONS="-z 2" in my /var/qmail/rc

#!/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 \
DKIMSIGNOPTIONS="-z 2" \
FILTERARGS=/var/qmail/bin/dk-filter \
qmail-start "`cat /var/qmail/control/defaultdelivery`"

Reply |

usage 2038 keys

At this point having a modified domainkey script file, which outputs a splitted dns record in case of 2048 key, from someone who have shell skills better than mine would be very much appreciated... :-)

Reply |

usage 2038 keys

upgraded. thanks

Reply |

usage 2048 keys

I restored the 1024 key, because my bind server was failing to load zones with such a long line. Any comment would be appreciated

Reply |

usage 2048 keys

you must separate long key with more than 255 charset " (quotation marks)

Reply |

usage 2048 keys

I tried to support the domainkey command for 2048bit.
TXT record for BIND is automatically set to 2 lines.

modified
https://acoustype.com/domainkey

original
https://notes.sagredo.eu/files/qmail/domainkey

thank you.

Reply |

usage 2048 keys

I published your modified script. Thanks again

Reply |

usage 2048 keys

I was very surprised.
Thank you very much.

Reply |

usage 2048 keys

Great contribution, very much appreciated. I'm going to make tests as soon as possible

Reply |

Improvement

Thank you Roberto for such a good and clear guide to DKIM and qmail.

I've made a little improvement that I want to share. I've made it to solve my need to sign messages sent by authenticated users, and to verify all non authenticated ones.

With the current code, it is not possible to achieve this. However with a little modification, it can be done pretty easily. I changed the behavior of RELAYCLIENT_NODKIMVERIFY (which IMHO is wrong at the moment, since it will skip verification, but also any eventual signing that may have been requested).

I've added a check for env variable RELAYCLIENT_NODKIM, which if present, will skip verification and signing step, going on directly with the next QUEUE command (like the current behavior).

Instead, if RELAYCLIENT_NODKIMVERIFY is present, it will void any DKIMVERIFY, and will go on with the code, allowing to sign a message if DKIMKEY is specified or a default domainkey is available for that domain (!DKIMSIGN && !DKIMVERIFY && RELAYCLIENT).

Pheww, too much words. The patch is simpler and easier to read, though ;) 

/etc/tcprules.d/tcp.smtp:

:allow,QMAILQUEUE="/var/qmail/bin/qmail-dkim",DKIMVERIFY="FGHKLMNOQRTVWjpu",DKIMKEY="/etc/domainkeys/%/private",RELAYCLIENT_NODKIMVERIFY="1"

Patch:

--- netqmail-1.06/qmail-dkim.c 2018-08-17 13:42:40.000000000 +0200
+++ netqmail-1.06.relaynoverify.patch/qmail-dkim.c 2018-08-17 13:44:11.000000000 +0200
@@ -1115,10 +1115,13 @@
dkimsign = env_get("DKIMSIGN");
dkimverify = env_get("DKIMVERIFY");
p = (env_get("RELAYCLIENT") || env_get("AUTHINFO")) ? "" : 0;
- if (dkimverify && p && env_get("RELAYCLIENT_NODKIMVERIFY")) {
+ if (p && env_get("RELAYCLIENT_NODKIM")) {
execv(*binqqargs, binqqargs);
die(120, 0);
}
+ if (dkimverify && p && env_get("RELAYCLIENT_NODKIMVERIFY")) {
+ dkimverify = 0;
+ }
if (!dkimsign && !dkimverify && p) {
if (!(dkimsign = env_get("DKIMKEY"))) {
if (!stralloc_copys(&dkimfn, "domainkeys/%/default"))

Ciao!

Reply |

Improvement

Actually the logic behind the RELAYCLIENT_NODKIMVERIFY variable is to avoid that the outgoing messages will be verified as well

Reply |

Improvement

Ok, but the name _NODKIMVERIFY misleaded me to think that only the verification step was skipped.

Reply |

Improvement

This is what actually does... that variable is there to avoid that outgoing msg could be verified before getting the queue and be signed via qmail-remote

Reply |

Improvement

Great! Thank you

Reply |

mails do not have a signature via php

Hi,

I have in the file /var/qmail/supervise/qmail-smtpd/run

export QMAILQUEUE=/var/qmail/bin/qmail-dkim
export DKIMKEY=/etc/domainkeys/my_domain/default

The dkim signature is present if I use outlook for example (relay) but is not present if I send a mail by a php script from the mail server.

Have I forgotten anything? Thank you for your help

regards

Reply |

Re: mails do not have a signature via php

I have never tested this, as I usually run php in a server that is separated from qmail. As you know, the php mailer calls the sendmail program, which is an alias of /var/qmail/bin/sendmail. Perhaps the qmail's sendmail program injects the message directly via qmail-inject without opening a connection to qmail-smtpd on port 25 and without the call of any filter like qmail-dkim, but I admit that I didn't look at the code, so any other explaination would be welcome

Reply |

How can I use this patch only and not all the package ?

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 ?

Reply |

Sorry Pablo, I can't get what

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

Reply |

How to sign with algorithm rsa-sha256

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?

Reply |

As I suspected, it was a

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.

Reply |

Fails to verify if subject not in h= list

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?)

Reply |

Re: Fails to verify if subject not in h= list

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

Reply |

Re: Fails to verify if subject not in h= list

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

Reply |

Re: Fails to verify if subject not in h= list

Thank you Manvendra. I have updated my combined patch accordingly

Reply |

I will ask Manvendra Bhangui

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

Reply |

qmail-dkim: signature error: RSA verify failed but testing

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

Reply |

Re: qmail-dkim: signature error: RSA verify failed but testing

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.

Reply |

No Output and Exit status 53

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

Reply |

DKIM Failing [SOLVED]

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

Reply |

This example implies qmail-dkim man page to be corrected.

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

Reply |

glad to know that your problem got fixed

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

Reply |

exit code 53 means that qmail

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.

Reply |

it seems like you don't have

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

Reply |

I had the DKIM working for

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

Reply |

You have the letter 'j' in

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

Reply |

I've been running with the

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

 

Reply |

DKIM DNS Long records Issue

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

 

Reply |

DKIM DNS Long record issue

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. 

Reply |

Raw text

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

Reply |

DKIM Signature problem with emails received from apple.com

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.

Reply |

Re: DKIM DNS Long records Issue

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

Reply |

qmail-dkim: signature error: permanent dns failure

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

Reply |

the answer is in the qmail-dkim man page

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..

Reply |

wrong password logs

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

Reply |

yes it is /var/log/maillog

yes it is /var/log/maillog

Reply |

Many thanks =)

Many thanks =)

Reply |

Authentication-Results

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

Reply |

I don't know of any patch to

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.

Reply |

dkim for local mails not work

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

Reply |

dkim for local mails not work

Had the same problem here today, and it was a permission issue. In our case, /var/qmail/control/cache was incorrectly configured. Fixed it with:

chown vpopmail:vchkpw /var/qmail/control/cache

It sounds simple, but it took me several hours to fix this as I was thinking that it was a DKIM configuration/permission issue.

Reply |

dkim for local mails not work

This should have already been done by the time you installed my patch....

Reply |

I don't know... your config

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

Reply |

now sign but not verify

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 

Reply |

can you post your smtpd

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

Reply |

sorry, I see know that the

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

Reply |

Question about run scripts config with simscan

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

Reply |

Hi Marc, thanks for your

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

Reply |

Contents of DKIMSIGN environment variable

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

Reply |

thanks

Hi Otto, thanks for your contribution.

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

Reply |

White List form DKIM

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 :)

Reply |

unfortunately there's no

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

Reply |

invalid structure

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

please discard previous comment

thanks

Reply |

Invalid structure

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

Reply |

qmail-dkim error

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

Reply |

what do you have in your

what do you have in your DKIMVERIFY?

Reply |

export DKIMVERIFY="DEGIJKfh"

export DKIMVERIFY="DEGIJKfh"

Reply |

I don't know exactly what is

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

Reply |

DKIM not sign

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

Reply |

RE: DKIM do not sign

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

Reply |

Thanks for your reply

Thanks for your reply.

I have

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

regards
nic

Reply |

Apparently your config is

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.

Reply |

Many thanks again.This box

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

Reply |

No, just add one more line

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)

Reply |

Thanks roberto.I had done

Thanks roberto.

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

Thanks
nic

Reply |

What the tests from the

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

Reply |

Hi,The tests are identical to

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

Reply |

Tests from the command line

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

Reply |

Thanks.Am i right to strace

Thanks.

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

regards

nic

Reply |

No, simply the process id of

No, simply the process id of qmai-smtpd

Reply |

HiI had strace pid 994 which

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

Reply |

Actually you have to strace

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

Reply |

Ok.Nothing is logged

Ok.

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

27792 accept(3,

regards
nic

Reply |

Try this way

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..

Reply |

Nothing at all.. Weird.

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

Reply |

you have a 300s timeout in

you have a 300s timeout in the rblsmtpd..

Reply |

Ok.I remove all other

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

Reply |

and how you are using strace?

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...

Reply |

qmail-dkim not sign the mail

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
:)

Reply |

qmail-dkim not sign the mail

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

Reply |

Re: qmail-dkim

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..

Reply |

Hi á I have a different,

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 ;)

Reply |

Hey Jacekalex, I double

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.. :-)

Reply |

Thanks For me I do not want

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
;)

Reply |

Why qmail-dkim should check

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

Reply |

Let me know what change I should make

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

Reply |

Recent comments
Recent posts

RSS feeds