Using DKIM in my server for multiple domains (websites)
Good! I figured this out from the post mentioned in the question. I made a kind of mix between the answer itself and the links provided in it. Specially the fourth link is the one I used.
So the thing goes like this. Suppose you've got a server or VPS and make one of your domains to be the main domain and be used as the server name (in my example: mydomain.com).
So, first of all, we'll change to root to make things easier, but you can skip this step and use sudo
before every command.
sudo su
Now, we install OpenDKIM:
apt-get install opendkim opendkim-tools
Let's fix the configuration file. We're opening /etc/opendkim.conf
for editing. I use nano, but it's the same with other editor.
nano /etc/opendkim.conf
Once opened, make it look like this. If you feel comfortable, you can change some options, but the Domain
, KeyFile
and Selector
must remain commented.
# This is a basic configuration that can easily be adapted to suit a standard
# installation. For more advanced options, see opendkim.conf(5) and/or
# /usr/share/doc/opendkim/examples/opendkim.conf.sample.
#
#Domain example.com
#KeyFile /etc/opendkim/201205.private
#Selector 201205
#
# Commonly-used options
Canonicalization relaxed/simple
Mode sv
SubDomains yes
# Log to syslog
Syslog yes
LogWhy yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask 022
UserID opendkim:opendkim
#
KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
#
Socket inet:8891@localhost
#EOF
Next, we create some of the folder and files that will hold information about what should OpenDKIM use and process. For now, the TrustedHosts
file. We create and edit it:
mkdir /etc/opendkim
nano /etc/opendkim/TrustedHosts
We must put into this file a list of trusted addresses: localhost and 127.0.0.1, and your server name and IP:
127.0.0.1
localhost
192.99.34.121
mydomain.com
Now we edit OpenDKIM config file.
nano /etc/default/opendkim
And add these lines at the end of the file. They'll tell OpenDKIM in which port it should expect signing requests:
SOCKET="inet:8891@localhost"
We open the Postfix config file.
nano /etc/postfix/main.cf
And add these lines to the end of the file. They'll tell Postfix that it should send e-mails to be signed and where.
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
If you're not adding domains right now, you can restart everything, so the configuration takes effect.
/etc/init.d/opendkim restart
/etc/init.d/postfix reload
/etc/init.d/postfix restart
Done! The server is ready to work with DKIM. Now, you need to add your domains to this system. The following process is the same for all the domains you want to add. I'll use otherdomain.com for the example, replace it with your own.
Remember I was root from before, but if you're not, run sudo su
or precede your commands with the keyword sudo
.
sudo su
First, we create a directory for our domain and go inside of it:
mkdir -p /etc/opendkim/keys/otherdomain.com
cd /etc/opendkim/keys/otherdomain.com
Now we generate a key for the domain:
opendkim-genkey -r -d otherdomain.com
We give the OpenDKIM user ownership of the newly created file:
chown opendkim:opendkim default.private
And we open the KeyTable
file to add our new key for our new domain:
nano /etc/opendkim/KeyTable
We add it to the end of the file (after all other domains we may have here):
default._domainkey.otherdomain.com otherdomain.com:default:/etc/opendkim/keys/otherdomain.com/default.private
We open the SigningTable
file.
nano /etc/opendkim/SigningTable
And append at the end of the file (again, we'll have one line for each domain):
otherdomain.com default._domainkey.otherdomain.com
This SigningTable lists all mails which get signed. Just by adding a domain name, all mails from that domain will be signed.
I'm not sure of the necessity to do the next step, but I just did it, just in case... We open the TrustedHosts
file.
nano /etc/opendkim/TrustedHosts
And add at the end of the file:
otherdomain.com
One last thing: we show the contents of the file /etc/opendkim/keys/otherdomain.com/default.txt
.
cat /etc/opendkim/keys/otherdomain.com/default.txt
And add the information between the quotes to a TXT
record in the DNS Zone of the domain, and we must also use default._domainkey
as the name of the record. NOTE: "between the quotes" is the text that starts with "v=DKIM1;k=rsa; p=WIGfM...
".
If we're done adding domains (by now), we restart everything to apply the changes.
/etc/init.d/opendkim restart
/etc/init.d/postfix reload
/etc/init.d/postfix restart
Done!
This script automates the part after "Done! The server is ready to work with DKIM"
To help automate this process a little I created this bash script. Just add one 'domain.com' per line inside the domains=() array.
First create the files and directories if they do not already exist
/etc/opendkim/keys/
/etc/opendkim/KeyTable
/etc/opendkim/SigningTable
/etc/opendkim/TrustedHosts
/etc/opendkim/spfs.txt
spfs.txt file will contain all the spf records you need to add to your DNS records for each domain.
NOTE: do not run more than once, it does not check to see if a domain already exists. Script also needs to be run as root.
#!/bin/bash
domains=(
'domain.com'
)
for domain in "${domains[@]}"
do
keydir="/etc/opendkim/keys/$domain"
if [ -d "$keydir" ]
then
cd $keydir
else
mkdir $keydir
cd $keydir
fi
opendkim-genkey -r -d $domain
chown opendkim:opendkim default.private
echo "default._domainkey.$domain $domain:default:$keydir/default.private" >> /etc/opendkim/KeyTable
echo "$domain default._domainkey.$domain" >> /etc/opendkim/SigningTable
echo "$domain" >> /etc/opendkim/TrustedHosts
echo "$(cat $keydir/default.txt)" >> spfs.txt
done
This script automates the part after "Done! The server is ready to work with DKIM"
To help automate this process a little I created this bash script. Just add one domain like 'example.com' per line inside the domains=() array.
This script creates the files for you and checks if a line is already in the file
Spfs.txt is removed and recreated everytime its run and checks the 2nd line of default.txt against spfs.txt before appending
You must place your servers ipv4 and ipv6 (if you have them) in the variables provided. It checks if they arent empty
you can run this file multiple times thanks to the checks added.
#!/bin/bash
# List of domains
domains=(
'example.com'
)
# file paths and directories
dkim="/etc/opendkim"
keys="$dkim/keys"
keyfile="$dkim/KeyTable"
signfile="$dkim/SigningTable"
trustfile="$dkim/TrustedHosts"
spffile="$dkim/spfs.txt"
# Set Ipv6 and Ipv4 addresses for the server here
ipv4=""
ipv6=""
# loopback addresses for the server
loop=( localhost 127.0.0.1 )
function loopback {
for back in "${loop[@]}"
do
if ! grep -q "$back" "$trustfile"; then
echo "$back" >> "$trustfile"
fi
done
}
# Check for files and create / write to them if they dont exist
if [ ! -d "$keys" ]; then
mkdir "$keys"
fi
if [ ! -f "$keyfile" ]; then
touch "$keyfile"
fi
if [ ! -f "$signfile" ]; then
touch "$signfile"
fi
if [ ! -f "$trustfile" ]; then
touch "$trustfile"
loopback
else
loopback
fi
if [ ! -f "$spffile" ]; then
touch "$spffile"
else
rm -rf "$spffile"
touch "$spffile"
fi
if [ ! -z "$ipv6" ]; then
if ! grep -q "$ipv6" "$trustfile"; then
echo "$ipv6" >> "$trustfile"
fi
fi
if [ ! -z "$ipv4" ]; then
if ! grep -q "$ipv4" "$trustfile"; then
echo "$ipv4" >> "$trustfile"
fi
fi
# Generate keys and write the spfs records we need for each domain to one file
for domain in "${domains[@]}"
do
keydir="$keys/$domain"
default="$keydir/default.txt"
if [ ! -d "$keydir" ]; then
mkdir $keydir
fi
cd $keydir
opendkim-genkey -r -d $domain
chown opendkim:opendkim default.private
key="default._domainkey.$domain $domain:default:$keydir/default.private"
sign="$domain default._domainkey.$domain"
trust="$domain"
spf="$(cat $default)"
# Check only the last line against the spf file as the first line is always the same
spflast="$(tail -1 $default)"
if ! grep -q "$key" "$keyfile"; then
echo "$key" >> "$keyfile"
fi
if ! grep -q "$sign" "$signfile"; then
echo "$sign" >> "$signfile"
fi
if ! grep -q "$trust" "$trustfile"; then
echo "$trust" >> "$trustfile"
fi
if ! grep -q "$spflast" "$spffile"; then
echo "$spf" >> "$spffile"
fi
done