Reverse proxy
This is not something that you can configure on your own server because it needs to be done by your isp. In order to be compliant you can only have one reverse lookup so this is the fqdn of your mail server rather than any of the domains that you host mail for, say:
mail.myhost.com
which needs to be set to your public ip address by your isp. The forward lookup is set in the usual way using your domain name providers standard dns settings. This is also true for the MX record. Getting this set varies from isp to isp and most of the time they know nothing about it, but with perseverance you can usually get it set (if not then simply change ISP).
To put some perspective on this, getting the reverse proxy is perhaps the easiest bit of this debacle, setting up and configuring DMARC is so thrown together that it is hardly worth documenting. At the time of writing I have configured 2 servers (a powerpc running Jessie and an intel box running stretch) and both configurations were different.
DON’T TRY TO DO ANY OF THIS WITHOUT FIRST ENSURING YOU HAVE A FULLY WORKING EMAIL SERVER; IT IS COMPLEX AND INCREDIBLY FLAKY AT BEST. ADDITIONALLY MAKE SURE THAT YOU HAVE BIND CONFIGURED AS DESCRIBED IN THIS MANUAL, THE FOLLOWING STEPS ARE DEPENDENT ON IT.
The following section has mostly been ripped from a web page but has one or two amendments which deal with slightly more extensive testing and configuration problems that I have encountered.
SPF (Sender Policy Framework) is a system that identifies to mail servers what hosts are allowed to send email for a given domain. Setting up SPF helps to prevent your email from being classified as spam.
DKIM (DomainKeys Identified Mail) is a system that lets your official mail servers add a signature to headers of outgoing email and identifies your domain’s public key so other mail servers can verify the signature. As with SPF, DKIM helps keep your mail from being considered spam. It also lets mail servers detect when your mail has been tampered with in transit.
DMARC (Domain Message Authentication, Reporting & Conformance) allows you to advertise to mail servers what your domain’s policies are regarding mail that fails SPF and/or DKIM validations. It additionally allows you to request reports on failed messages from receiving mail servers.
The DNS instructions for setting up SPF, DKIM and DMARC are generic. The instructions for configuring the SPF policy agent and OpenDKIM into Postfix should work on any distribution after making respective code adjustments for the package tool, and identifying the exact path to the Unix socket file.
Publishing an SPF DNS record without having the SPF policy agent configured within Postfix is safe; however, publishing DKIM DNS records without having OpenDKIM working correctly within Postfix can result in your email being discarded by the recipient’s email server.
Install the packages
apt-get install opendkim opendkim-tools postfix-policyd-spf-python postfix-pcre
If you have spamassassin installed then you may also need to install libmail-dkim-perl. When I carried out my installations I had one server that needed it and one that didn’t. The worst thing that can happen is that you will receive a warning that it is already installed so you might as well better be safe than sorry.
apt-get install libmail-dkim-perl
Add user postfix to the opendkim group so that Postfix can access OpenDKIM’s socket when it needs to:
adduser postfix opendkim
Set up SPF and create the DNS records
The value in an SPF DNS record will look something like the following examples. The full syntax is at the SPF record syntax page.
Example 1 Allow mail from all hosts listed in the MX records for the domain:
v=spf1 mx -all
Example 2 Allow mail from a specific host:
v=spf1 a:mail.example.com -all
The v=spf1 tag is required and has to be the first tag.
The last tag, -all, indicates that mail from your domain should only come from servers identified in the SPF string. Anything coming from any other source is forging your domain. An alternative is ~all, indicating the same thing but also indicating that mail servers should accept the message and flag it as forged instead of rejecting it outright. -all makes it harder for spammers to forge your domain successfully; it is the recommended setting. ~all reduces the chances of email getting lost because an incorrect mail server was used to send mail. ~all can be used if you don’t want to take chances.
The tags between identify eligible servers from which email to your domain can originate.
mx is a shorthand for all the hosts listed in MX records for your domain. If you’ve got a solitary mail server, mx is probably the best option. If you’ve got a backup mail server (a second MX record), using mx won’t cause any problems. Your backup mail server will be identified as an authorized source for email although it will probably never send any.
The “a” tag lets you identify a specific host by name or IP address, letting you specify which hosts are authorized. You’d use a if you wanted to prevent the backup mail server from sending outgoing mail or if you wanted to identify hosts other than your own mail server that could send mail from your domain (e.g., putting your ISP’s outgoing mail servers in the list so they’d be recognized when you had to send mail through them).
The complexities of this are such that I am going to provide a real world example here. All our mail servers at the moment are using the intrasec.uk domain, We are currently administering 3 of them which are
intrasec.uk
acacia.intrasec.uk
intrasec.uk
I will only give one example of a domain that we are administering as it is easy enough to scale this up should it be necessary. That domain is
usermaildomain.co.uk
One of the big problems that we had here was that the DNS setup at names.co.uk would not allow us to have zones and while we did manage to get one added in the end, we ended up configuring our own DNS servers and telling the names.co.uk servers to forward requests to them. NOTE: This is now documented in the Bind setup in this document.
Ok, so assuming that our mail server is mail.intrasec.uk then we need to make sure we have an MX record pointing to that server.
In the instance of your user domains rather than your service domains, it is likely that DNS will be managed by your domain provider. I do however usually like to set up a test domain that uses the TLD of the server (this is handy to perform tests on the server without having an email address whose domain name may belong to somebody else.
If your domain’s dns is with your provider then you will leave the host name blank, give the record a priorty (ususally 10) and the result will be intrasec.uk in our example.
The SPF record will be a TXT record where once again the name will be blank the record type will be TXT and the value will be “v=spf1 a mx ~all“. This tells other servers that the server in the MX record is permitted to send email on behalf of our domain. As discussed earlier the “~all” tells other mail servers to accept mail even if it is forged but flag it. In reality once you are sure you have everything set up correctly you may want to change this to “-all” because you don’t want people receiving email on your behalf if it is being sent by a different mail server.
If you are using bind then, because you cannot delete all the spaces TXT records, you have to put the string in inverted commas: In bind the record looks like
@ IN TXT “v=spf1 a mx ~all”
Don’t forget to update to update the serial number and reload the zone.
rndc reload mydomain.co.uk
or if you have views set up
rndc reload mydomain.co.uk IN myview
You may have to “freeze” and “thaw” the zone (same commands different verb).
Postfix SPF
That allows other servers to lookup the SPF record to determine whether the email is likely to be forged, but if you would also like to return the favour and check that the emails you are receiving are from valid sources then you need to configure postfix to perofrm the checks.
Just to recap here; Postfix both sends and receives mail (it is in essence a mail hub); Dovecot is basically the sorting office, it takes the mail from the hub and delivers it to the right address.
So what do we need to do to get postfix to validate the incoming messages against an SPF record? As it happens it is reasonably simple, we have already installed postfix-policyd-spf-python so we just need to edit the config files; first master.cf
vi /etc/postfix/master.cf
Add the following at the bottom of the file:
policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf
NOTE THE TWO SPACES ON THE BOTTOM LINE, It will not load without them
Now save the file and move on to main.cf
First we want to prevent Postfix from aborting the agent if transactions run a little slow by setting
policyd-spf_time_limit = 3600
Now we need to exit smtpd_recipient_restrictions (this may or may not be already present in the file, if not then create it)smtpd_recipient_restrictions = check_policy_service unix:private/policyd-spf. If the directive is already present, make sure that any entry is after a reject_unauth_destination eg.
smtpd_recipient_restrictions = reject_unauth_destination, check_policy_service unix:private/policyd-spf
If there is no smtpd_recipient_restrictions record containing a reject_unauth_destination entry then there is no need to add one (it will be set elsewhere).
That’s it, restart postfix and all should be working (you can check by looking at the email headers for the header Received-SPF which should say something like:
Pass (sender SPF authorized) identity=mailfrom; client-ip….
Setup openDKIM
WARNING: ALL the open dkim config files are fussy (makefile style), any stray invisible characters in it and it will not parse properly. You are advised to place a single tab as a delimiter and a single return at the end of the line. If you are using vim as your editor you can “set list” to show invisibles (use set nolist to change back to normal mode) in order to be certain you don’t have any stray invisibles.
First things first: check the server is sending and receiving emails before going any further, if all is okay then we can move on to DKIM. We will start with opendkim.conf which is located diretly in the /etc directory.
vi /etc/opendkim.conf
The sample configuration file is documented to explain what some of the directives do, but I would say it is best to create a new file due to the flaky way in which it is parsed. (The one below uses a single tab as a separator, but be careful if you copy it as it may have some invisibles in it that are not meant to be there.
We use the special “refile:” directive on the signing table instructs opendkim to replace the wildcard (‘*’) when it attempts to determine which emails it should be signing (see signing.tab configuration below)
Syslog yes SyslogSuccess yes LogWhy yes Canonicalization relaxed/simple OversignHeaders From Mode sv SubDomains yes UserID opendkim:opendkim UMask 002 Socket inet:8891@localhost PidFile /run/opendkim/opendkim.pid TrustAnchorFile /usr/share/dns/root.key KeyTable /etc/opendkim/key.tab SigningTable refile:/etc/opendkim/signing.tab ExternalIgnoreList /etc/opendkim/trusted.hosts InternalHosts /etc/opendkim/trusted.hosts
If you set list in vim it should look like
Syslog^Iyes$ SyslogSuccess^Iyes$ LogWhy^Iyes$ ....
Now ensure that the file permissions are set correctly
chmod u=rw,go=r /etc/opendkim.conf
Next we need to create the directories for the configuration files and set their permissions.
mkdir /etc/opendkim mkdir /etc/opendkim/keys chown -R opendkim:opendkim /etc/opendkim chmod go-rw /etc/opendkim/keys
Now you need to create the signing table and add an entry. The signing table needs to have the same name as is set in /etc/opendkim.conf
touch /etc/opendkim/signing.tab
Next you need to edit the signing table to add an entry for a domain that your mail server is providing mail services for. The entry is fairly simple as for each domain it is (in our example we are using usermaildomain.co.uk)
*@usermaildomain.co.uk UMD1806
Assuming that the ‘*’ is a wildcard, the first part is self explanatory, the second part is simply an alias.
Save the file and exit or add additional records as is your want. Once again be careful about the formatting, for it to work correctly it needs to follow the same formatting as the configuration file
We can now move on to the key table.
touch /etc/opendkim/key.tab
The keytable uses the alias from the signing table followed by a string that requires futher explanation (again, be careful with the formatting).
UMD1806 usermaildomain.co.uk:UMD1806:/etc/opendkim/keys/UMD1806.private
The first section is the domain name for which the key is used. (usermaildomain.co.uk)
The second section is a selector used when looking up key records in DNS. This selector can technically be anything, but it should reflect the domain and the date that it was created (the theory being that you should change the keys every so often to prevent them being hacked)
NOTE: Do not use ‘_’ underscore characters in your Selector as it will cause errors when checking with checkauth later on
The third section is the path for the file containing the signing key for the domain.
Now create the trusted hosts file
touch /etc/opendkim/trusted.hosts
This should contain a list of the hosts that our server knows it can trust (every name that our server may be known by)
127.0.0.1 ::1 localhost myhostname myhostname.example.com example.com
When creating the file, change myhostname to the name of your server and replace example.com with your own domain name. We’re identifying the hosts that users will be submitting mail through and should have outgoing mail signed, which for basic configurations will be your own mail server.
Make sure the ownership and permissions on /etc/opendkim and it’s contents are correct (opendkim should own everything, the keys directory should only be accessible by the owner) by running the following commands:
chown -R opendkim:opendkim /etc/opendkim chmod -R go-rwx /etc/opendkim/keys
Now generate the keys.
cd /etc/opendkim/keys opendkim-genkey -b 2048 -h rsa-sha256 -r -s UMD1806 -d usermaildomain.co.uk -v
UMD1806 is the unique identifier (the selector) and usermaildomain.co.uk is the domain that the key is intended for (you will be using this later in your DNS record)
Now set the file permissions on the keys you have just generated
chown -R opendkim:opendkim /etc/opendkim chmod -R go-rw /etc/opendkim/keys
and restart opendkim
service opendkim restart
followed by
service opendkim status
to check for error messages. If there are any errors check the syslog for further information
cat /var/log/syslog |grep opendkim
Setting up DNS for DKIM
As with SPF, DKIM uses TXT records to hold information about the signing key for each domain. You need to make a TXT record for the host UMD1806._domainkey for each domain you handle mail for (don’t worry about the domainkey bit for now). Its value can be found in the “.txt” file for the domain (in our example /etc/opendkim/keys/UMD1806.txt) The file should look like this:
_domainkey IN TXT ( "**v=DKIM1; h=rsa-sha256; k=rsa; s=email; " "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu5oIUrFDWZK7F4thFxpZa2or6jBEX3cSL6b2TJdPkO5iNn9vHNXhNX31nOefN8FksX94YbLJ8NHcFPbaZTW8R2HthYxRaCyqodxlLHibg8aHdfa+bxKeiI/xABRuAM0WG0JEDSyakMFqIO40ghj/h7DUc/4OXNdeQhrKDTlgf2bd+FjpJ3bNAFcMYa3Oeju33b2Tp+PdtqIwXR" "ZksfuXh7m30kuyavp3Uaso145DRBaJZA55lNxmHWMgMjO+YjNeuR6j4oQqyGwzPaVcSdOG8Js2mXt+J3Hr+nNmJGxZUUW4Uw5ws08wT9opRgSpn+ThX2d1AgQePpGrWOamC3PdcwIDAQAB**" ) ; ----- DKIM key 201806 for usermaildomain.co.uk
Depending on whether this is going on your providers server (usual) or your own bind server (usually only for the test domain) depends on what you do with it next. If it is going on your own server then the easiest thing to do is to copy the whole “.txt” file across to /var/named on the DNS server that is master for the zone and then simply include it in your zone file:
cp /etc/openvpn/keys/ UMD1806.txt /var/named chown bind:bind /var/named/ UMD1806.txt
Now edit the zone file (in our example it would be usermaildomain.co.uk) and add the directive $INCLUDE UMD1806.txt. I usually like to place it under the SPF record but this is not strictly necessary.
…… @ IN MX 10 mail IN TXT “v=spf1 a mx –all” $INCLUDE UMD1806.txt
Now edit /var/named/ INCLUDE UMD1806.txt to change h=rsa-sha256 to h=sha256.
If you are adding a record to your providers DNS server then it will probably be a little different. You need to create a TXT record with the name UMD1806._domainkey. The value of the key will be the entire region from (but not including) the double-quote before v=DKIM1 on up to (but not including) the final double-quote before the closing parentheses. Then edit out the double-quotes within the copied text and the whitespace between them. Also change h=rsa-sha256 to h=sha256.
From the above file the result would be:
v=DKIM1; h=sha256; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu5oIUrFDWZK7F4thFxpZa2or6jBEX3cSL6b2TJdPkO5iNn9vHNXhNX31nOefN8FksX94YbLJ8NHcFPbaZTW8R2HthYxRaCyqodxlLHibg8aHdfa+bxKeiI/xABRuAM0WG0JEDSyakMFqIO40ghj/h7DUc/4OXNdeQhrKDTlgf2bd+FjpJ3bNAFcMYa3Oeju33b2Tp+PdtqIwXRZksfuXh7m30kuyavp3Uaso145DRBaJZA55lNxmHWMgMjO+YjNeuR6j4oQqyGwzPaVcSdOG8Js2mXt+J3Hr+nNmJGxZUUW4Uw5ws08wT9opRgSpn+ThX2d1AgQePpGrWOamC3PdcwIDAQAB
Testing
Now you should be able to test your configuration. If everything works as planned then you shoud get a result by simply typing:
opendkim-testkey –d usermaildomain.co.uk –s UMD1806 -vvv
the results should look something like:
opendkim-testkey: using default configfile /etc/opendkim.conf opendkim-testkey: checking key ' _domainkey.acacia.inplico.uk' opendkim-testkey: key not secure opendkim-testkey: key OK
GREAT EH? WELL NO, not really because if simply run
opendkim-testkey -vvv
It may very well fail (if it does it will also fail when hooked up to postfix)
opendkim-testkey: using default configfile /etc/opendkim.conf opendkim-testkey: record 0 for '/etc/opendkim/key.tab' retrieved opendkim-testkey: checking key '/etc/opendkim/key.tab' opendkim-testkey: dkim.c:2875: dkim_get_key: Assertion `sig->sig_selector != NULL' failed.
If this happens then chances are you have a stray character in one of your files. A good result will look something like:
opendkim-testkey: using default configfile /etc/opendkim.conf opendkim-testkey: record 0 for 'UMD1806' retrieved opendkim-testkey: checking key 'UMD1806' opendkim-testkey: key UMD1806: OK opendkim-testkey: key UMD1806 not secure opendkim-testkey: 1 key checked; 1 pass, 0 fail
If for some reason this does not work you may have a problem with your DNS or your configuration. To check your DNS record use:
dig UMD1806._domainkey.nesm.inplico.uk TXT
NOTE “_domainkey” is automatically appended to the selector when opendkim-keygen generates the public key. You can see this by looking in the UMD1806.txt file (or whatever you have named it).
Hooking OpenDKIM into Postfix
If all is well then you can go on to edit /etc/postfix/main.cf
At the bottom of the file (or wherever you like really) you need to add some directives, but first you need to look for smtpd_milters and non_smtpd_milters directives. There is likely to be an smtpd_milters directive containing an entry for spamassassin (unix:spamass/spamass.sock). You need to edit this line to add the opendkim socket. Change it from
smtpd_milters = unix:spamass/spamass.sock
to (all on one line):
smtpd_milters = unix:spamass/spamass.sock, inet:localhost:8891
NOTE: This is the port set in /etc/opendkim.conf
There probably isn’t a non_smtpd_milters directive so you should add one as follows:
non_smtpd_milters = inet:localhost:8891
Now add the line:
milter_default_action = accept
and set the milter protocol. The milter_protocol is entirely dependent on the version of postfix you are running, if it is older than version 2.6 then you should set the value to 2, otherwise set it to 6.
milter_protocol = 6
The addition should look like this:
#milters milter_protocol = 6 milter_default_action = accept smtpd_milters = unix:spamass/spamass.sock, inet:localhost:8891 non_smtpd_milters = inet:localhost:8891
Now you can restart postfix and opendkim, check for errors and then verify everything is working by sending a test email to check-auth@verifier.port25.com using an email client configured to submit mail to the submission port on your mail server. It will analyze your message and mail you a report indicating whether your email was signed correctly or not. It also reports on a number of other things such as SPF configuration and SpamAssassin flagging of your domain. If there’s a problem, it’ll report what the problem was.
You can also check that your server is signing emails with a DKIM key by inspecting the header of an email that you have sent from your configured domain in thunderbird.
You should have a DKIM signature directive that looks a little like
v=1; a=rsa-sha256; c=simple/simple; d=jtek.co.uk; s=201806; t=1528581912; bh=UtQ5SCud0QWpwfwa6a5bMkX1lqNpc=; ………
https://www.dmarcanalyzcom/dkim/dkim-check/ is another useful little tester for DKIM recods.
DMARC
Once you have everything set up you can add a DMARC record to your DNS server. This is a fairly simple task, just edit your zone file and add another TXT record with the name _dmarc.
_dmarc IN TXT v=DMARC1;p=quarantine;sp=quarantine;adkim=r;aspf=r
This requests mail servers to quarantine (do not discard, but separate from regular messages) any email that fails either SPF or DKIM checks. No reporting is requested. Very few mail servers implement the software to generate reports on failed messages, so it is often unnecessary to request them. If you do wish to request reports, the value would be similar to this example, added as a single string:
v=DMARC1;p=quarantine;sp=quarantine;adkim=r;aspf=r;fo=1;rf=afrf;rua=mailto:user@example.com
Replace user@example.com in the mailto: URL with your own email or an email address you own dedicated to receiving reports (an address such as dmarc@example.com). This requests aggregated reports in XML showing how many messages fell into each combination of pass and fail results and the mail server addresses sending them.
Recent Comments