This module checks DKIM signatures for emails scanned.
DKIM signatures can establish that this specific message has been signed by a trusted
relay. For example, if a message comes from gmail.com then a valid DKIM signature
means that this message was definitely signed by gmail.com (unless gmail.com private
key has been compromised, which is not a likewise case).
Rspamd can deal with many types of DKIM signatures and messages canonicalisation.
The major difficulty with DKIM are line endings: many MTA treat them differently which
leads to broken signatures. Basically, rspamd treats all line endings as CR+LF that
is compatible with the most of DKIM implementations. From the version 1.3, Rspamd DKIM module also supports signing of messages.
DKIM module has several useful configuration options:
dkim_cache_size (or expire) - maximum size of DKIM keys cachewhitelist - a map of domains that should not be checked with DKIM (e.g. if that domains have totally broken DKIM signer)domains - a map of domains that should have more strict scores for DKIM violationstrict_multiplier - multiply the value of symbols by this value if received from domains maptrusted_only - do not check DKIM signatures for all domains but those which are from the domains mapSince version 1.3, Rspamd can also add DKIM signatures to messages. This could be used, for example, to sign outbound messages with some key. To use this ability, there is an option called sign_condition which defines Lua script that is intended to analyze a task object and return signing params if a signature is desired:
key: path to private key for the domainselector: DKIM selector valuedomain: domain used for signingIf no signature is required, then this function should return nil or false. Here is an example of learn_condition script that is intended to sign messages that come from example.com domains:
# local.d/dkim.conf
sign_condition =<<EOD
return function(task)
local from = task:get_from('smtp')
if from and from[1]['addr'] then
if string.find(from[1]['addr'], '@example.com$') then
return {
key = "/etc/dkim/example.com",
domain = "example.com",
selector = "test"
}
end
end
return false
end
EOD;
Multiple domains signing example:
sign_condition =<<EOD
return function(task)
local rspamd_logger = require "rspamd_logger"
local domains = {
'example.com',
'example1.com',
'example2.com'
}
local from = task:get_from('smtp')
if from and from[1]['addr'] then
for _,d in ipairs(domains) do
if string.match(from[1]['addr'], '@(.+)$') == d then
local ip = task:get_ip()
if not task:get_user() and not (ip and ip:is_local()) then
rspamd_logger.infox(task, "skip DKIM signing for unauthorized user from non-local network")
return false
end
-- Keys are searched in `/usr/local/etc/dkim/domain.dkim.key`
-- You can generate them using the following command:
-- rspamadm dkim_keygen -s 'dkim' -d 'example.com' -k /usr/local/etc/dkim/example.com.dkim.key
return {
key = "/usr/local/etc/dkim/" .. d .. ".dkim.key",
domain = d,
selector = "dkim"
}
end
end
end
return false
end
EOD;
Alternatively, you can use maps in this code, for example, to limit signing policy to some network:
# local.d/dkim.conf
sign_condition =<<EOD
-- Closure
local dkim_ip_map = rspamd_config:add_map({
url = '/etc/rspamd/dkim_ip.map',
type = 'radix',
description = 'dkim sign map'
})
-- Callback function
return function(task)
local ip = task:get_ip()
if ip and dkim_ip_map and dkim_ip_map:get_key(ip) then
return {
key = "/etc/dkim/example.com",
domain = "example.com",
selector = "test"
}
end
end
EOD;
You need to ensure that Rspamd can open signing keys, so they should be accessible for the user _rspamd in the most of the cases.
There is also convenience setting since Rmilter 1.10.0 to enable DKIM signing via Rspamd. Your dkim section should look like the following one in this case:
dkim {
rspamd_sign = yes;
}
From Rspamd 1.6, this is not applied, use Milter support in Rspamd.
Rspamd always use relaxed/relaxed encoding with rsa-sha256 signature algorithm. This selection seems to be the most appropriate for all cases. Rspamd adds a special element called DKIM-Signature to the output when signing has been done. Rmilter can use this header out of the box. Other integration methods cannot recognize this header so far.
You can also generate DKIM keys for your domain using rspamadm dkim_keygen utility:
rspamadm dkim_keygen -s 'test' -d example.com
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
test._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGJAoGBALBrq9K6yxAXHwircsTnDTsd2Kg426z02AnoKTvyYNqwYT5Dxa02lyOiAXloXVIJsyfuGOOoSx543D7DGWw0plgElHXKStXy1TZ7fJfbEtuc5RASIKqOAT1iHGfGB1SZzjt3a3vJBhoStjvLulw4h8NC2jep96/QGuK8G/3b/SJNAgMBAAE=" ) ;
The first part is DKIM private key (that should be saved to some file) and the second part is DNS record for the public part that you should place in your zone’s file. This command can also save both private and public parts to files.