Prevent spoofing with DKIM

Email sender spoofing is the act of pretending to be in control of someone else’s email address. This is a common problem with phishing. Frequently scammers send emails with a sender address of something@paypal.com and hope that the recipient falls for it and trusts them. In fact SMTP does not care which sender address you send. Many mail service providers enforce that you send emails only using your own email address. But some do not. And spammer and scammers obviously do not care at all.

Example without DKIM

So a new method was conceived that added a cryptographic signature to the header of an email that the recipient could check to verify the authenticity of the sender and the integrity of the email. The signature is created using a private key that only the sending mail server has. It can then be verified by the recipient by downloading the corresponding public key from the DNS zone of the sending domain and running a signature check. This works very similar to PGP or S/MIME signing – just on a domain level. Your mail server can sign all outgoing emails automatically. The method used nowadays is called Domain Keys Identified Mail – or short: DKIM.

Let’s take an example. I have just sent an email from GMail to my personal email account on my own mail server. Google uses DKIM signing so the email got this additional header from Google’s mail servers:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=gmail.com; s=20161025;
 h=mime-version:from:date:message-id:subject:to;
 bh=/FpkZfBuKR0WWcH2fFcr9M4qgX4Z4+/0dX4dpqycK28=;
 b=fZ4Efy1TuXAl1ho2twkEuNiVP8k5GRKqlol/f/dTawaxciAv1bwinkbuTCpK4T3SoL
 ZFhdh/p82MYiIt75V5eGFtSMQfocVIKfsusggj3ZKlwUNvSbB/jd4fn3SKwGjLSyKMT0
 agJFblxF+ydGzRKYzJNPfFYhdQY3YZcMEria87SpqgVgqECCMRvuT10w7KQGIx7AsvDy
 F2coh2TnX400sRidMVF1S/9QhD85dE3xSie3ZdTfWBsP00Y7xWbos7MlSl1MnsVvXPtQ
 7bnNBVdcn1tP9x8IeNKp6qEYoLYzEeLZVp8eLB0F0AoWIgRb348FaIvMF9jYvO/h/cQ+
 YP5Q==

I need Google’s DKIM public key to verify that signature. It is stored in their DNS zone as a TXT record of “20161025._domainkey.google.com”. The “20161025” is the key selector that is mentioned in the signature as “s=20161025“. You can use any number of keys as long as you create the signatures with the matching private key.  The “_domainkey” part is the standard subdomain for DKIM keys. So let’s get that TXT record:

dig +short 20161025._domainkey.google.com txt

“k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXNZF1j8sJPDleRjf9SPBNem0ik58kF1ilC1nUgKAttl9v7FX9hXJXPmLNhVtSKVZ8yruaeOZLeIxtgtk1s81zzIE5Mj0AiGn2wlFt4kYfqlDfYe95YLQHjynu4i7vj1Tj” “ksf62btcCbL+3XhbK+oD5PlqYhXHWuzoKoEp5L4lCihgkONvU/oy7NNeE6quqfF/y0YSLwF2WVA2Kd8L6R0Ar2dYT/3wZCFknI7xhvPqh9HNcIWBELGPwtXcsHbX1wvBlCgNQAUcdJrf2YWzAwqmZ564/1ipL1IMk1nafPJk75ktumVNz6ORuIn3jbZWp9rRpnaeI9cu/8KfSKH2EY9QIDAQAB”

This is the public key that I can use to verify the signature. An automated check can be done using the “opendkim-testmsg” tool as described later. I can run it and paste the entire email including headers and body into it. If it doesn’t complain with an error message then the signature is correct.

Sounds good? Okay, let’s implement that for your email domain, too.

Creating a keypair

As explained above you need a private key that your mail server will use and a public key that gets added to your DNS zone. rspamd can create DKIM keys already. You may want to install “dig” though which allows to query DNS records. It works like “nslookup” but is more versatile.

apt install dnsutils

rspamd has its built-in DKIM signing module enabled by default. If you put your key file into /var/lib/rspamd/dkim/ using a certain naming scheme it will pick it up automatically. Create that directory to store keys in:

mkdir /var/lib/rspamd/dkim
chown _rspamd:_rspamd /var/lib/rspamd/dkim

Create your keypair:

rspamadm dkim_keygen -d example.org -s 2018022301

The selector (-s) I chose is 2018022301 because that’s the day I created it. The first (01) key on 2018-02-23. It doesn’t matter though – you can name it anything you want. If you are lazy and unconcerned you could even use “dkim” as the selector and later spare some work by not needing DKIM maps that define which key is supposed to be used for each domain. “dkim” is the default selector if you do not use maps. However if you need to replace your key later without invalidating previously sent emails you are in trouble. So I recommend you rather use maps as explained further below. It gives you more flexibility and is pretty easy to do.

The output will look like this:

-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALF6ce6mRgs+YUxs
mNX11AgIpSXbEf9p7FJFTAK7DtMn12R12og37q3LDhUqGdbxHT9SVvOVIUuZWAxT
S5STBO1WrIMeG1JTstX9KRViZSy3h1NQXWv7w++ECbu+hsxgp3C9Gw6rbsAG1lzw
/ihTZdceqprotTyziw3GzXaEtb2zAgMBAAECgYEAltFCuFa79xoPfO5cApZglGMk
VEMRzEaq+E7DBR8Ivg+BTnGIP3Godi+zy/B2/NzwybqjAWOdY6zv0amG9L7q04sM
BnhM06S+DFbmetEV0CKGg+yGQ3QRIxm5ZeFj7OOcssPxzyTrzI3MU2vhDkOrKycE
kaiWu4PI2TwvBF7PtGECQQDaq4rJfd8IITtL84qqt6DxWNb45cuay8oWnq2kjU0k
nkcLhpvCdO5a037AUnBmpQzQWxsE1OMhl54oV6QY8EhPAkEAz8a2q2wshFuiSBjV
BU3kXELdjqxEoti+zBuuT8QldCUntHbG1Vyo8A6ObVOnbbGEJmmRqjajjBV3Imvj
+NW3XQJATiqR8xLmnh5a9vx47iu0AXITbmeej5gXhlx0j+Te1Z8qoEke9rUb2yXN
ImyVt2t6mCRpFSIQixqKs7sYcr256wJBALFbSDZPojhhF8c/Gybp9FIk6YaN2hC/
vy3vOv3vyqC3zoqnENazv6kaY81CqRpjexBm8OZAuZ4r/IOvYOvZUikCQQCtWZtZ
8oYlVB2R4OMF5CMrjEkMNW9J5wZwPj7NHdbXLTtzDoI+oCrjus9foffe3T5ADFQ6
x6ZDbufbaRujG8/B
-----END PRIVATE KEY-----
2018022301._domainkey IN TXT ( "v=DKIM1; k=rsa; "
 "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxenHupkYLPmF … QAB" ) ;

The first part is the private key. And that includes “…BEGIN…” and “…END…” lines. This key must be kept secret and will only be used by your mail server to sign outgoing emails.

The second part is the DNS record you need to add to your domain’s DNS zone. Let’s start with that.

Adding the DNS record

Before you start signing your emails you must make sure that the public key is properly present in your DNS zone for the domain you are sending emails from. Otherwise the recipient will be unable to verify the signature and may incorrectly assume that the email was spoofed.

Take a look at the 2018022301.txt file. It will look something like this:

2018022301._domainkey IN TXT ( “v=DKIM1; h=sha256; k=rsa; “p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxenHupkYLPmFMbJjV9dQICKUl2xH/aexSRUwCuw7TJ9dkddqIN+6tyw4VKhnW8R0/UlbzlSFLmVgMU0uUkwTtVqyDHhtSU7LV/SkVYmUst4dTUF1r+8PvhAm7vobMYKdwvRsOq27ABtZc8P4oU2XXHqqa6LU8s4sNxs12hLW9swIDAQAB” ) ;

If you are running your own DNS server you should be able to copy this entire file and put it into your DNS zone. However if your internet provider offers you just a web interface to manage your domains then create a new TXT record with a host name of “2018022301._domainkey” and put the string within the double-quotes into it as the value. In my example:

2018022301._domainkey ➠p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxenHupkYLPmFMbJjV9dQICKUl2xH/aexSRUwCuw7TJ9dkddqIN+6tyw4VKhnW8R0/UlbzlSFLmVgMU0uUkwTtVqyDHhtSU7LV/SkVYmUst4dTUF1r+8PvhAm7vobMYKdwvRsOq27ABtZc8P4oU2XXHqqa6LU8s4sNxs12hLW9swIDAQAB

Depending on your ISP it may take a while until the new record is visible on the internet. You can use dig to verify that:

dig +trace 2018022301._domainkey.example.org txt

If you get the TXT entry like as follows then you are ready to enable DKIM signing in rspamd for that domain:

TXT “p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxenHupkYLPmFMbJjV9dQICKUl2xH/aexSRUwCuw7TJ9dkddqIN+6tyw4VKhnW8R0/UlbzlSFLmVgMU0uUkwTtVqyDHhtSU7LV/SkVYmUst4dTUF1r+8PvhAm7vobMYKdwvRsOq27ABtZc8P4oU2XXHqqa6LU8s4sNxs12hLW9swIDAQAB” “” from server foo.bar in 24 ms.

Enabling DKIM maps in rspamd

As explained above it is advised to use DKIM maps. It’s nothing fancy. Just a simple file defining which selector you want to use for a certain domain. rspamd will assume that your selector is always “dkim” unless specified otherwise in a map. If you used “dkim” then you may get into trouble when you later want to replace your key. DNS is a sluggish system and propagating a new DKIM public key may take a day. Emails signed with a newer key may get rejected while the DNS record is not yet known everywhere in the world.

Using maps is simple. First we need to change the selector_map setting of the dkim_signing module. To do that create a new file in /etc/rspamd/local.d/dkim_signing.conf and make it contain just these two lines:

path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector_map = "/etc/rspamd/dkim_selectors.map";

The configuration is pretty self-explaining. rspamd will look for the domain-to-key mapping in the dkim_selectors.map file. Create that file and make it contain this line:

example.org 2018022301

That’s all really. rspamd now knows that whenever it sees an outgoing email from anyone@example.org it will get the DKIM private key from /var/lib/rspamd/dkim/example.org.2018022301.key and use it to sign the email.

Reload the configuration:

service rspamd reload

This method works well if you just have a few domains that virtually never change. If you are rather serving random customer domains you should consider putting the keys into a Redis database instead as described in the documentation. There is not yet a way to manage DKIM keys in a database like MySQL.

Adding the domain key to rspamd

Take the private key that was created earlier (the multi-line string including “…BEGIN PRIVATE KEYS…” and “…END PRIVATE KEY…”) and put it into a file at the location where rspamd will look for it:

/var/lib/rspamd/dkim/example.org.2018022301.key

The name of the file has to be  DOMAIN + dot + SELECTOR + “.key” like above. If you name the file incorrectly you will get an error in your rspamd.log file like “lua_dkim_sign_handler: cannot load dkim key /var/lib/rspamd/dkim/example.org.dkim.key“.

Make sure that only _rspamd can read it:

chown _rspamd /var/lib/rspamd/dkim/*
chmod u=r,go= /var/lib/rspamd/dkim/*

rspamd will automatically pick up the files and does not need to be restarted.

Send a test email

If you have another email account at another location then you could just send a test email there via your mail server. If you take a look at the received email it should have a DKIM header now like:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.org;
	s=2018022301; t=1519400838;
	h=from:subject:date:message-id:to:mime-version:content-type:content-transfer-encoding;
	bh=kpYel1IlDvqXEUc0SyIpXbMte3XpQOCXHl+zTyHQvGc=;
	b=NEUyWUoeKEoKAYTY8g04o73j+wrYUcEGSq7uwpbsAGo0OzuuIBluEfG1MbGF/Tf6yxxJB4
	gTDD3sqb19EsQxv39QsAwgddAz01Osw5LKU0MjLZpxw6NA8zLllJUsrNdNQAYSII9ip4xX
	ImU7+KFOEF+gmxR5aseUt5H6JT/aOmhPE9xsSyg9wLf0Bikyy5Cgh+Ay7AHQLMZogbTi9W
	dAPpZZcZs0pTwhcard6SaesypJ+xZNna+BA+C1vXrGDc+9stYZVi+Zufh6zlZo1E/sQSRL
	jowB1mjv1vjINRY30aq0rh4dT8RHe38/PKFf8vQHOSOKvjIKv984UeOTIFIUHw==
DKIM signature verification

To verify the signature install the opendkim-tools package, copy the entire test email (including headers and body), run opendkim-testmsg in your shell and paste the email (finish with CTRL-D).

If you get no output then the signature verified correctly. But if you get something like “opendkim-testmsg: dkim_eom(): Unable to verify” then double-check your DNS record.

You can also use the dkimvalidator.com service to verify that your signatures are working well.

SPF and DMARC

Adding DKIM signatures is a good first step. But you can take it further by telling receiving mail servers that they should not accept any email from your domain without a valid signature or from servers that you do no operate. There are two concepts that aim to help. The older SPF and the newer DMARC. Either of them means creating a machine-readable string in a predefined format and adding a TXT record to your DNS zone. Receiving mail servers can check those records and take your advice (as the domain owner) what to do if the criteria of the email are not met. It could accept the email anyway or flag it as spam or reject it altogether.

Let’s take a look at a typical SPF record:

"v=spf1 ip4:157.97.194.11 mx ~all"

What it means:

  1. this is an SPF record of version 1 of the standard (there is currently no other version)
  2. please accept emails from the IP address 157.97.194.11
  3. alternatively accept emails from any server that is mentioned in our domain’s MX record (the server(s) that receive email for your domain)
  4. any other email should be considered suspicious – it might be spam or worse

There are websites like SPFwizard that help you create your SPF string to add to your DNS domain. Keep in mind though:

  • You should know which mail servers send email from your domain. Do not forget to include mailing list or newsletter services that send in your name.
  • Start with “~all” to mark emails as spam that do not meet the criteria. If all goes well switch to “-all” after a few weeks if you like.
  • Note that forwarding emails from your domain may break SPF because suddenly the email appears to be coming from an IP address that is not authorized. This has been a common problem for mailing lists and is gradually being fixed by resending the email from the domain of the mailing list service.

I mentioned that DMARC is the newer standard. So why use SPF anyway? Because some email providers value your effort if you use SPF, too. Technically it’s sufficient to specify a DMARC entry. In my opinion restricting the IP addresses allowed to send is a little dangerous and a little inflexible. It is fare more interesting to require that emails from your domain have a valid DKIM signature. Such a record may roughly look like:

"v=DMARC1; p=reject; adkim=s"

However to create a proper DMARC entry I suggest you use one of the web sites that aid you there and explain the restrictions and extra features.

40 thoughts on “Prevent spoofing with DKIM”

  1. Hello!

    Thank you for your tutorial!

    I am going to configure my mail server in the near future according to your tutorial. It is very nice of you to provide such a detailed guide. I have been researching this possiblity for few months and have found a lot of other tutorials but by far yours is the best. I probably will try to replace MariaDB with Postgres though.

    There is one thing you did not mention which was mentioned in some other tutorials: Are there any special requirements about PTR DNS records?

    They say that without proper configuration of PTR record ones mail could be rejected by the other big ISP e-mail providers (e.g. Google, Microsoft, etc). I am interested in this informtion because it is not always possible to change a value of the record easily. Could you clarify this please?

    Thanks again for your tutorial – it is awesome!

    1. Craig Stewart

      In theory some email providers will not except an email from a server if the PTR record doesn’t match the domain that the sending server claims to be, and some if the PTR record doesn’t match a domain that has the sending server’s IP as it’s forward lookup, and in theory sometimes both must be true.

      That said in more than a decade of running a mail server with a PTR record that didn’t match either of those conditions I never came across a mail server that failed to accept an email from me (for that reason anyway). When I used a previous version of this guide to move to a mail server not on my home connection, I neglected to have any PTR records set for the mail servers I set up, and even then it took a while to get my mail rejected.

      It is good practice to have PTR record that matches a forward lookup to the server, and have the server claim to be that name. But generally I find it isn’t critical, as long as the server has a PTR record that isn’t blank in practice that will be all you need, and if you don’t get the right PTR record you won’t be the only one. Of the two conditions a PTR that matches a forward lookup for the server is probably the one that matters more than the other.

  2. Perfect 🙂 It took a while until I figured out the right syntax for bind, but now it works perfectly 😉

  3. hi,
    Since rspamd provide dkim generator such as rspamadm dkim_keygen -b 2048 -s 2017 -k /var/lib/rspamd/dkim/2017.key, what is the advantage of using opendkim-genkey?

    1. I totally agree, the rspamadm command generates the keys, place them in the right folder and display the DNS record.

    1. Christoph Haas

      If you consider Redis a database – then yes. rspamd is offloading a lot to Redis for performance reasons. In a larger setup you should consider putting DKIM keys there.

      1. Is Redis the only method? As I use postgresql already for database, I would like to also place dkim keys there. Then backups (barman) has everything in one place.

  4. Singularis

    Some notes, worth to be added to the main text, I think.

    If your record is not accepted by your DNS hoster, a 2048 bit key might be too long. You can generate a shorter key by specifying -b 1024 instead of -b 2048 and running the rspamadm dkim_keygen command again.
    Most of these fields only allow 255 chars of length, since being database varchar 255 fields.
    opendkim-genkey –bits=1024 -d domain.tld -s 201801

    I also changed /etc/rspamd/local.d/dkim_signing.conf adding the mismatch option:

    path = “/var/lib/rspamd/dkim/$domain.$selector.key”;
    selector_map = “/etc/rspamd/dkim_selectors.map”;

    ### Enable DKIM signing for alias sender addresses
    allow_username_mismatch = true;

    I am not sure whether this and/or the following made dkim verification work.

    But for sure this configuration needs to be copied to /etc/rspamd/local.d/arc.conf, since the ARC module makes use of the same parameters, and to prevent the rspamd.log error “task; lua_dkim_sign_handler: cannot load dkim key /var/lib/rspamd/arc/example.com.arc.key: cannot stat private key /var/lib/rspamd/arc/example.com.arc.key: No such file or directory”

    cp -R /etc/rspamd/local.d/dkim_signing.conf /etc/rspamd/local.d/arc.conf

    Which finally did it.
    🙂

  5. Singularis

    Another thing I found and forgot to mention in my previous post, that
    dig +short +trace 2018022301._domainkey.example.org txt
    did not work at all. I only found this
    dig 2018022301._domainkey.example.org txt +short
    giving me the right answer.

  6. as we’re able to configure multiple domains by adding them to the `virtual_domains` table, is there a way to set up DKIM with a single key and multiple domains as well?

    I guess something like multiple `-d` parameters with letsencrypt?

      1. I am managing three different Top Level Domains on the mail-server. The mails from one of these domains are correctly signed by dkim. But how can I include the other two domains?

  7. Andi Olsen

    The “Next page” link at the bottom is missing on this page, so I was forced to scroll ALL THE WAY back up to the top, to get to the next page… Geeeesh! ;P

      1. Andi Olsen

        I was however only joking. Hope that was correctly reflected by the smiley at the end! 😀

  8. Hint 1:
    If there are any problems with rspamd and DKIM, then create file
    /etc/rspamd/local.d/logging.inc
    and put there
    debug_modules = [“dkim_signing”]

    Hint 2:
    chown -R _rspamd:_rspamd /var/lib/rspamd/dkim/

  9. Francesco Piraneo G.

    Hi all,
    No way! On my emails no DKIM record has been added!
    Any hint to solve this issue is greatly appreciated.
    Thanks in advance.

  10. Thomas Kjaergaard

    Hi Christoph Haas
    Thank you for the great guide.
    I have been using your guide since Lenny.
    I have trouble getting the rspamd DKIM_signing to work.
    After combined 7 hours struggle with it, with different configuration strategies I have still not managed to get it to work. Id did sleep in between 🙂

    Strategies testet:
    1) Direct from the main text as you described it with path and mappings.
    2) Modified version of the main guide text with modifications as user “Singularis” suggested.
    cp -R /etc/rspamd/local.d/dkim_signing.conf /etc/rspamd/local.d/arc.conf

    3)
    A different approach using the official guide with and without mappings.
    https://rspamd.com/doc/modules/dkim_signing.html

    Copy of config where also a direct domain is defined:
    # local.d/dkim_signing.conf

    # If false, messages with empty envelope from are not signed
    allow_envfrom_empty = true;

    # If true, envelope/header domain mismatch is ignored
    allow_hdrfrom_mismatch = false;

    # If true, multiple from headers are allowed (but only first is used)
    allow_hdrfrom_multiple = false;

    # If true, username does not need to contain matching domain
    allow_username_mismatch = false;

    # If false, messages from authenticated users are not selected for signing
    auth_only = true;

    # If false, messages from local networks are not selected for signing
    sign_local = true;

    # Symbol to add when message is signed
    symbol = “DKIM_SIGNED”;

    # Whether to fallback to global config
    try_fallback = true;

    # Domain to use for DKIM signing: can be “header” (MIME From), “envelope” (SMTP From) or “auth” (SMTP username)
    use_domain = “header”;

    # Domain to use for DKIM signing when sender is in sign_networks (“header”/”envelope”/”auth”)
    #use_domain_sign_networks = “header”;

    # Domain to use for DKIM signing when sender is a local IP (“header”/”envelope”/”auth”)
    #use_domain_sign_local = “header”;

    # Whether to normalise domains to eSLD
    use_esld = true;

    # Whether to get keys from Redis
    use_redis = false;

    selector_map = “/etc/rspamd/dkim_selectors.map”;
    path_map = “/etc/rspamd/dkim_paths.map”;
    #path = “/var/lib/rspamd/dkim/$domain.$selector.key”;

    # If `true` get pubkey from DNS record and check if it matches private key
    check_pubkey = false;
    # Set to `false` if you want to skip signing if publick and private keys mismatches
    allow_pubkey_mismatch = true;

    # Domain specific settings
    #domain {
    # pci.dk {
    # # Private key path
    # path = “/var/lib/rspamd/dkim/$domain.$selector.key”;
    # # Selector
    # selector = “nrs2018070701”;
    # }
    #}
    ——————

    I enabled more logging:
    Quote:
    /etc/rspamd/local.d/logging.inc
    and put there
    debug_modules = [“dkim_signing”]

    Hint 2:
    chown -R _rspamd:_rspamd /var/lib/rspamd/dkim/
    ————-

    2018-07-08 21:34:01 #7977(rspamd_proxy) ; proxy; proxy_accept_socket: accepted milter connection from 127.0.0.1 port 48816
    2018-07-08 21:34:01 #7977(rspamd_proxy) ; milter; rspamd_milter_process_command: got connection from 77.68.232.4:50926
    2018-07-08 21:34:01 #7977(rspamd_proxy) ; proxy; proxy_backend_master_error_handler: abnormally closing connection from backend: ::1, error: IO write error: Connec$
    2018-07-08 21:34:01 #7977(rspamd_proxy) ; proxy; proxy_backend_master_error_handler: retry connection to: 127.0.0.1 retries left: 4
    2018-07-08 21:34:01 #7979(normal) ; task; accept_socket: accepted connection from 127.0.0.1 port 59444, task ptr: 00007F8200C70300
    2018-07-08 21:34:01 #7979(normal) ; task; rspamd_message_parse: loaded message; id: ; queue-id: ; size: 52$
    2018-07-08 21:34:01 #7979(normal) ; task; rspamd_mime_part_detect_language: detected part language: en
    2018-07-08 21:34:01 #7979(normal) ; task; dkim_symbol_callback: skip DKIM checks for local networks and authorized users
    2018-07-08 21:34:01 #7979(normal) ; task; spf_symbol_callback: skip SPF checks for local networks and authorized users
    2018-07-08 21:34:01 #7979(normal) ; lua; once_received.lua:95: Skipping once_received for authenticated user or local network
    2018-07-08 21:34:01 #7979(normal) ; lua; dmarc.lua:218: skip DMARC checks for local networks and authorized users
    2018-07-08 21:34:01 #7979(normal) ; dkim_signing; lua_dkim_tools.lua:34: user is authenticated
    2018-07-08 21:34:01 #7979(normal) ; dkim_signing; lua_dkim_tools.lua:107: use domain(header) for signature: pci.dk
    2018-07-08 21:34:01 #7979(normal) ; dkim_signing; lua_dkim_tools.lua:126: final DKIM domain: pci.dk
    2018-07-08 21:34:01 #7979(normal) lua; dkim_signing.lua:159: dkim_signing
    —————

    Currently I guess it’s related to
    “dkim_symbol_callback: skip DKIM checks for local networks and authorized users”

    Do you have a hint I can use?

    Best Regards
    Thomas

    1. VonLatvala

      No, it isn’t related to:

      “dkim_symbol_callback: skip DKIM checks for local networks and authorized users”

      This just tells that rspamd isn’t checking for a valid DKIM signature on this message, because it is from a local network. This check should be run on INCOMMING mail and not outgoing, so this is correct.
      What you are looking for is dkim_signing, and the relevant (but unhelpful) lines in your log are:

      2018-07-08 21:34:01 #7979(normal) ; dkim_signing; lua_dkim_tools.lua:34: user is authenticated
      2018-07-08 21:34:01 #7979(normal) ; dkim_signing; lua_dkim_tools.lua:107: use domain(header) for signature: pci.dk
      2018-07-08 21:34:01 #7979(normal) ; dkim_signing; lua_dkim_tools.lua:126: final DKIM domain: pci.dk
      2018-07-08 21:34:01 #7979(normal) lua; dkim_signing.lua:159: dkim_signing

      Bad news buddy, my logs look exactly the same, and my messages aren’t signed either. Will report back here when I sort this one out. What version of rspamd are you using? eg.`rspamd –version`, I am using `Rspamd daemon version 1.7.8`.

      1. VonLatvala

        Solved my problem, it seems like the following message –v

        2018-07-08 21:34:01 #7979(normal) lua; dkim_signing.lua:159: dkim_signing

        actually is a pretty fatal error message, but without the actual error message. I tried with an older version of rspamd (1.7.4-2), it gave me a line like this (with the domain changed):

        2018-07-17 20:17:57 #19531(normal) ; dkim_signing; dkim_signing.lua:121: file /var/lib/rspamd/dkim/MY_DOMAIN.default.key does not exists

        So rspamd couldn’t read the private key to sign with, huh. Checked permissions to the file, all good, and finally checked permissions to the folder the private key was in. It had permissions r——–, so no execute! Changing this to r-xr-x— (ug=rx,o=) fixed the problem, and the log message is also absent!

        After this I reinstalled the newest version (1.7.8), and the problem still is fixed. Feels like my good old days of *nix tweaking, when the problem was after many hours of troubleshooting, a permission problem.

        Hope this helps,
        Axel

    2. Javier Ortega Conde (Malkavian)

      I got it. Hope it helps you. I followed as you “Singularis” recommendations, and activated debug logging mode as “Someone” suggested. I have seen in the log:

      use domain(header) for signature: mysubdomain.subdomain.example.org
      final DKIM domain: example.org

      I search in google: “use domain(header) for signature” “final DKIM domain” and found
      this bug report: https://github.com/Mailu/Mailu/issues/435

      So I added this line in /etc/rspamd/local.d/dkim_signing.conf and (the copied) /etc/rspamd/local.d/arc.conf

      use_esld = false;

      Then service rspamd reload

      And profit!. Now messages go also with dkim signature!

  11. Rostislav Pokorný

    I have a problem with DKIM, when i use the command:

    “rspamadm dkim_keygen -d example.org -s string”

    folder “/ var / lib / rspamd / dkim” is empty.

    I want to look at the conf file “dkim_signing.conf”, but it also does not exist. At folder “/etc/rspamd/local.d/” i only see worker-controller.inc.

    Can you help me? Thank you in advance for your reply.

  12. Javier Ortega Conde (Malkavian)

    Some of the files created must be readable by rspamd so I needed to do:

    chmod a+r /etc/rspamd/dkim_selectors.map
    chmod a+r /etc/rspamd/local.d/dkim_signing.conf

  13. should this
    rspamadm dkim_keygen -d example.org -s 2018022301

    be this
    rspamadm dkim_keygen -d example.org -s 2018022301 -k example.org.2018022301.key

    ??

  14. May I Skip to put the DMARC TXT record in my DNS?

    it is because I’ve seen in cpanel configurations doesn’t have the DMARC record but the SPF yes…

    and I realize the mail is correctly delivered to every destinations I sent

  15. Florian Fritsch

    Hi Christoph,

    irgendwie steht ich (obwohl schon mehrfach gemacht) grad auf dem Schlauch.
    Der Mailserver hat die Domain mx.domain1.de
    Ich richte dort eine Adresse info@domain2.de ein und versuche einen DKIM Eintrag zu erstellen. Diesen hinterlege ich beim Domain Anbieter als TXT Eintrag mit:

    ._domainkey

    bei der Domain 2. Auch nach mehreren Stunden sagen mir diverese Testseiten dass die Mail nicht DKIM signiert sei. Steht ich grad aufm Schlauch und man braucht den DKIM Schlüssel nur für mx.domain1.de oder wo ist mein Fehler?

    Danke dir und viele Grüße

    Florian

    1. Florian Fritsch

      Mmmh. Er erwartet nicht

      /var/lib/rspamd/dkim/example.org.2018022301.key

      sondern

      /var/lib/rspamd/dkim/example.org.dkim.key

      Ändere ich aber den ersten Eintrag (anstatt Datum auf dkim.key) will rspamd nicht mehr restarten…

      Seltsam

  16. Florian Fritsch

    Hi Christoph,

    Javier hat Recht. Am besten im Tutorial noch ergänzen:

    chmod a+r /etc/rspamd/dkim_selectors.map
    chmod a+r /etc/rspamd/local.d/dkim_signing.conf

    Wenn die Datei root:root gehört mit den Standardrechten die vergeben werden, kann Rspamd diese nicht lesen.

    Gruß Florian

  17. Davide Marchi

    Hi Christoph and Friends,
    relating to the DKIM implementation, from my experience, the private key must NOT contain:
    —–BEGIN PRIVATE KEY—–
    and
    —–END PRIVATE KEY—–

    then, published the public key and set the private, for testing key matching you can use from “opendkim-tools” this command:

    opendkim-testkey -d example.org -s 2018022301 -vvv

    Davide

  18. Greetings, first of all excellent tutorial, at this point of the same I do not achieve that in my emails any DKIM record is added, my output from the raspamd.log file is as follows.

    2019-07-12 10:46:23 #2515(rspamd_proxy) ; proxy; proxy_accept_socket: accepted milter connection from 127.0.0.1 port 45680
    2019-07-12 10:46:23 #2515(rspamd_proxy) ; milter; rspamd_milter_process_command: got connection from 127.0.0.1:0
    2019-07-12 10:46:23 #2517(normal) ; task; accept_socket: accepted connection from ::1 port 0, task ptr: 00005635C337BB90
    2019-07-12 10:46:23 #2517(normal) ; task; rspamd_mime_parse_message: cannot find content-type for a message, assume text/plain
    2019-07-12 10:46:23 #2517(normal) ; task; rspamd_mime_part_get_cte: detected missing CTE for part as: base64
    2019-07-12 10:46:23 #2517(normal) ; task; rspamd_message_parse: loaded message; id: ; queue-id: ; size: 362; checksum:
    2019-07-12 10:46:23 #2517(normal) ; task; rspamd_url_text_extract: got empty text part

    2019-07-12 10:46:23 #2517(normal) ; task; spf_symbol_callback: skip SPF checks for local networks and authorized users
    2019-07-12 10:46:23 #2517(normal) ; task; dkim_symbol_callback: skip DKIM checks for local networks and authorized users
    2019-07-12 10:46:23 #2517(normal) ; lua; once_received.lua:95: Skipping once_received for authenticated user or local network
    2019-07-12 10:46:23 #2517(normal) ; lua; dmarc.lua:573: skip DMARC checks for local networks and authorized users
    2019-07-12 10:46:24 #2517(normal) ; lua; arc.lua:611: cannot read key from /var/lib/rspamd/arc/mi dominio.com.arc.key: No existe el fichero o el directorio

  19. Dear Christoph, Thanks for this wonderful tutorial. Works perfectly, also on Buster. Instead of editing config files for rspamd, I simply ran the wizard (`rspamadm configwizard`). Very convenient as it also creates the keys and put everything in place for you. (It repeats the question for multiple domains.)

    One issue I had: I want to send emails from several aliases. And these may be on different domains. I added `allow_username_mismatch = true;` in the config file `/etc/rspamd/local.d/dkim_signing.conf`. After this it worked fine.

  20. Paul Morris

    Hi Christoph, also thanks for the great tutorial for Buster; got a working mail server up and running – something I would never have been able to achieve with my own research from scratch.

    Quick query however – all the other examples I’ve seen of the [selector]._domainkey TXT record start with the “v=DKIM1; k=rsa…” rather than simply the “p=…” as shown in your 2018022301._domainkey example above. For one example, see https://mediatemple.net/community/products/dv/115003098072/how-do-i-add-a-dkim-txt-record-to-my-domain

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top