Docu review done: Tue 17 Oct 2023 10:50:14 AM CEST
Table of content
General
In this documentation, we assue that you have already a running and working postgrey instance on your server.
Installation
First you need fo course the packages installed, for Debian, you can use the command below.
$ apt install opendkim opendkim-tools
Preperation
Next is to create the dircetories where you want to store your configurtion files and keys and set the correct owner and group + permissions.
mkdir -p /etc/opendkim/keys
chown -R opendkim:opendkim /etc/opendkim
chmod go-rw /etc/opendkim/keys
Assuming you have the above mentined packages already installed and running Debian (or a Debian based system), you should add the user
postgres
to the groupopendkim
.
Configuration
OpenDKIM Config
Now you need to configure your /etc/opendkim.conf
file.
This is how a configuration could look like:
# This is a basic configuration for signing and verifying. It can easily be
# adapted to suit a basic installation. See opendkim.conf(5) and
# /usr/share/doc/opendkim/examples/opendkim.conf.sample for complete
# documentation of available configuration parameters.
Syslog yes
SyslogSuccess yes
# Common signing and verification parameters. In Debian, the "From" header is
# oversigned, because it is often the identity key used by reputation systems
# and thus somewhat security sensitive.
Canonicalization relaxed/simple
Mode sv
SubDomains no
AutoRestart yes
AutoRestartRate 10/1M
Background yes
DNSTimeout 5
SignatureAlgorithm rsa-sha256
OversignHeaders From
# In Debian, opendkim runs as user "opendkim". A umask of 007 is required when
# using a local socket with MTAs that access the socket as a non-privileged
# user (for example, Postfix). You may need to add user "postfix" to group
# "opendkim" in that case.
UserID opendkim
UMask 007
# Socket for the MTA connection (required). If the MTA is inside a chroot jail,
# it must be ensured that the socket is accessible. In Debian, Postfix runs in
# a chroot in /var/spool/postfix, therefore a Unix socket would have to be
# configured as shown on the last line below.
Socket local:/var/spool/postfix/opendkim/opendkim.sock
PidFile /run/opendkim/opendkim.pid
# The trust anchor enables DNSSEC. In Debian, the trust anchor file is provided
# by the package dns-root-data.
TrustAnchorFile /usr/share/dns/root.key
# Map domains in From addresses to keys used to sign messages
KeyTable refile:/etc/opendkim/key.table
SigningTable refile:/etc/opendkim/signing.table
# Hosts to ignore when verifying signatures
ExternalIgnoreList /etc/opendkim/trusted.hosts
# A set of internal hosts whose mail should be signed
InternalHosts /etc/opendkim/trusted.hosts
Defaults for opendkim service
For Debian and Debian based systems, you should also configure the file /etc/defaults/opendkim
.
Sample:
# NOTE: This is a legacy configuration file. It is not used by the opendkim
# systemd service. Please use the corresponding configuration parameters in
# /etc/opendkim.conf instead.
#
# Previously, one would edit the default settings here, and then execute
# /lib/opendkim/opendkim.service.generate to generate systemd override files at
# /etc/systemd/system/opendkim.service.d/override.conf and
# /etc/tmpfiles.d/opendkim.conf. While this is still possible, it is now
# recommended to adjust the settings directly in /etc/opendkim.conf.
#
#DAEMON_OPTS=""
# Change to /var/spool/postfix/run/opendkim to use a Unix socket with
# postfix in a chroot:
RUNDIR=/var/spool/postfix/opendkim
#RUNDIR=/run/opendkim
#
# Uncomment to specify an alternate socket
# Note that setting this will override any Socket value in opendkim.conf
# default:
SOCKET=local:$RUNDIR/opendkim.sock
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Excludes for Signing
Sometimes you don’t want to sign a mail, e.g. if you are sending the mail only internal.
To do this, you have to add them into the file /etc/opendkim/trusted.hosts
or better say, in the file which you have configured within the option InternalHosts
.
10.0.0.0/8
127.0.0.1
::1
localhost
itgui.de
*.itgui.de
Key pairing
To configure which key should be use for which (sub)domain, you need to add this information into the file /etc/opendkim/signing.table
or better say, in the file which you have configured within the option SigningTable
like this:
*@itgui.de default._domainkey.itgui.de
If you have more keys for other (sub)domains, just add a new line and specify there the mapping.
Just make sure that you have only one mapping per line.
Next is to link the link now virtual name with the real flie.
This is done in the file /etc/opendkim/key.table
or better say, in the file which you have configured within the option KeyTable
like this:
default._domainkey.itgui.de itgui.de:default:/etc/opendkim/keys/itgui.de/default.privat
Kreating key pair
To create the key pair, you can use the command opendkim-genkey
, like this (+ ensure the permissions):
$ opendkim-genkey -b 2048 -d "itgui.de" -D "/etc/opendkim/keys/itgui.de" -s default
$ chown -R opendkim. /etc/opendkim/keys/itgui.de
$ chmod -R o-rw /etc/opendkim/keys/itgui.de
In general it is recommended to renew the keys every 4 months. But if you also look at the big players, they also keep sometimes the for years ;)
If you are rotating keys, keep in mind, mails can keep alive for very long times, so ensure that you have both keys (old and new one) available for quite some time in DNS records to ensure, that mails signed with old keys, can be still validated.
Placing the DNS record
Now you need to place your public key into your DNS as a TXT
record.
First you need the data what you want to place, basically it is everything which is between the breaks ( )
, but here is a oneline for it (just a sample output) :
$ echo "v=DKIM1; k=rsa; s=email; $(sed -E '/default._domain.*IN.*TXT.*DKIM/d;s/\t* *"//g;s/".*//g' "/etc/opendkim/keys/itgui.de/default.txt")"
v=DKIM1; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCA...73Qzl5Czna797955/zX7Bp10e/lATZbVtP6Qu6eC2TMpWx06bEDRZ...oAtNNuhQIDAQAB
If you are able to talk to your DNS via API, you can easily put that into an automation, like this for netcup.de DNS:
#!/bin/bash
dkim_domain="${1}"
dkim_pre="v=DKIM1; h=sha256; k=rsa;"
dkim_dns_record_id=$(/usr/local/scripts/ncdapi.sh -g "${dkim_domain}" | jq -r '.[] | select ( .destination | contains("DKIM")) | .id')
if grep -qE '[0-9]{8,}' <<<"${dkim_dns_record_id}" ; then
echo "Detected existing DKIM record (id: ${dkim_dns_record_id}), skipping process..."
exit 0
fi
dkim_key=$(sed -E '/default._domain.*IN.*TXT.*DKIM/d;s/\t* *"//g;s/".*//g' "/etc/opendkim/keys/${dkim_domain}/default.txt" | tr -d '\n')
if [ -z "${dkim_key}" ] || grep -vqE "^p=" <<<"${dkim_key}"; then
echo "Failed during parsing, skipping process..."
exit 1
fi
if /usr/local/scripts/ncdapi.sh -N default._domainkey "${dkim_domain}" TXT "${dkim_pre} ${dkim_key}" ; then
echo "DNS record added"
else
echo "Failed to insert DNS record"
exit 1
fi
If not, then create it with the following specs (adopted to your data of course):
- Host:
default._domainkey
- Domain:
itgui.de
- Type:
TXT
- Destination:
v=DKIM1; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCA...73Qzl5Czna797955/zX7Bp10e/lATZbVtP6Qu6eC2TMpWx06bEDRZ...oAtNNuhQIDAQAB
Restart systemd service
Now we have everything on the server in place and can finaly restart the opendkim
serivce
$ systemctl restart opendkim.serivce
Testing your setup
Of course you want to konw if it is working, and with the command opendkim-testkey
you can do that.
opendkim-testkey -d itgui.de -s default -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key 'default._domainkey.itgui.de'
opendkim-testkey: key not secure
opendkim-testkey: key OK
Dont worry about the key not secure
this is just that DNSSEC is not in use right now and you can continue to work with it.
Postfix setup
Now we want to enable it in postfix.
Before you enable it, set the option
soft_bounce=yes
in your/etc/postfix/main.cf
.By setting this option, you don’t loose any mails if something goes wrong in your setup and postfix will just respond with a 4xx error to the sender mail server, instead of 5xx error, which leads to, that the sender mail server will retry it in a couple of minutes again.
Inside the /etc/postfix/main.cf
you have to add the following to enable the opendkim:
# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters
If you have already something in your milter (e.g. spamassassin), then just add it like this:
smtpd_milters = unix:spamass/spamass.sock, local:/opendkim/opendkim.sock
non_smtpd_milters = local:/opendkim/opendkim.sock
Now you have to restart the postfix service like this for example systemctl restart postfix.serivce
.
Mailtest
Now you can try to send your self a mail, after that have a look at the mail headers and you should find something like this:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=itgui.de;
s=default; t=1479644038;
bh=g3zLYH4xKxcPrHOD18z9YfpQcnk/GaJedfustWU5uGs=;
h=To:From:Subject:Date:From;
b=VI6TIDLrzG8nAUYWwt5QasKJkkgU+Sv8sPGC1fynSEGo0GSULGgCjVN6KXPfx1rgm
1uX2sWET/oMCpxjBFBVUbM7yHGdllhbADa2SarzYhkoEuNhmo+yxGpXkuh0ttn4z7n
OmkLwjrdLafMOaqSBrXcTMg/593b/EQXtouEvHqOG59d0fubIGCJBF6DG5gcITS9CP
q9tiVwIDVuQqynL9Crodl+2IObcvl15MeK2ej322qrjrTij6vZOru9SeVno4LNTkQ7
tOT4s14BGLx8aRe5YXZj38AWsR6DxkT6OzM+3TnOhIfX3ZdkufMz8AUnTNuLhViZ1M
betE0x1iOi/HQ==
A nice test page for this is isnotspam, before testing, you should wait a bit till the DNS changes has propagaged throught the DNS servers over the wild.
Issues
Double sigend mail
If you are running postfix, spamassassin
and opendkim
for the same mail instance, then it can happen that you see that your outgoing mails are swinged twice by opendkim
.
The reason for that is, that they get signed before spamassassins
takes care about the mail and after it.
In the following logsample, you see the double signing.
May 4 13:37:42 my_mail_server postfix/smtpd[2240071]: connect from myhost[10.0.0.2]
May 4 13:37:42 my_mail_server postfix/smtpd[2240071]: Anonymous TLS connection established from myhost[10.0.0.2]: TLSv...
May 4 13:37:42 my_mail_server postfix/smtpd[2240071]: E242018B0000: client=myhost[10.0.0.2], sasl_method=xxxxx, sasl_username=myuser@itgui.de
May 4 13:37:42 my_mail_server postfix/cleanup[2240086]: E242018B0000: message-id=<a3cdd989-e554-8cc5-1c8d-1e1c5697ae9e@itgui.de>
May 4 13:37:42 my_mail_server opendkim[2240050]: E242018B0000: DKIM-Signature field added (s=default, d=itgui.de)
May 4 13:37:42 my_mail_server postfix/qmgr[3846771]: E242018B0000: from=<myuser@itgui.de>, size=1712, nrcpt=1 (queue active)
May 4 13:37:42 my_mail_server spamd[2644747]: spamd: connection from ::1 [::1]:57232 to port 783, fd 5
May 4 13:37:42 my_mail_server spamd[2644747]: spamd: setuid to spamassassin succeeded
May 4 13:37:42 my_mail_server spamd[2644747]: spamd: processing message <a3cdd989-e554-8cc5-1c8d-1e1c5697ae9e@itgui.de> for spamassassin:5000
May 4 13:37:42 my_mail_server postfix/smtpd[2240071]: disconnect from myhost[10.0.0.2] ehlo=2 starttls=1 auth=1 mail=1 rcpt=1 data=1 quit=1 commands=8
May 4 13:37:42 my_mail_server spamd[2644747]: spamd: clean message (-0.8/5.0) for spamassassin:5000 in 0.2 seconds, 2173 bytes.
May 4 13:37:42 my_mail_server spamd[2644747]: spamd: result: . 0 - ALL_TRUSTED,DKIM_INVALID,DKIM_SIGNED,URIBL_BLOCKED scantime=0.2,size=2173,user=spambro,uid=0000,required_score=5.0,rhost=::1,raddr=::1,rport=57232,mid=<a3cdd989-e554-8cc5-1c8d-1e1c5697ae9e@tgui.de>,autolearn=no autolearn_force=no
May 4 13:37:42 my_mail_server postfix/pickup[2021986]: 274A118B0005: uid=0000 from=<myuser@itgui.de>
May 4 13:37:42 my_mail_server postfix/pipe[2240087]: E242018B0000: to=<myuser@itgui.de>, orig_to=<my_second_user@itgui.de>, relay=spamassassin, delay=0.26, delays=0.08/0.01/0/0.18, dsn=2.0.0, status=sent (delivered via spamassassin service)
May 4 13:37:42 my_mail_server postfix/qmgr[3846771]: E242018B0000: removed
May 4 13:37:42 my_mail_server postfix/cleanup[2240086]: 274A118B0005: message-id=<a3cdd989-e554-8cc5-1c8d-1e1c5697ae9e@itgui.de>
May 4 13:37:42 my_mail_server opendkim[2240050]: 274A118B0005: DKIM-Signature field added (s=default, d=itgui.de)
May 4 13:37:42 my_mail_server postfix/qmgr[3846771]: 274A118B0005: from=<myuser@itgui.de>, size=2639, nrcpt=1 (queue active)
May 4 13:37:42 my_mail_server postfix/pipe[2240092]: 274A118B0005: to=<myuser@itgui.de>, relay=dovecot, delay=0.03, delays=0.01/0.01/0/0.02, dsn=2.0.0, status=sent (delivered via dovecot service)
To get rid of the issue, you have to perform a small change in the master.cf
of postfix.
Search in the master.cf
the line where you have spamassassin configured for the smtp service and add -o receive_override_options=no_milters
like this:
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - - - - smtpd
-o content_filter=spamassassin -o receive_override_options=no_milters
Now all you have to do is restarting postgres and your issue should be solved.