So, really, this is just a log of what I’ve done, as I could not find this info anywhere in either the wiki or the forums. Maybe my google-fu wasn’t the best, but, I have all green checks on a received message, so that’s good.
- It’s beyond the scope of this little document to explain how these things work. There are a ton of resources available online.
- You are running the freepbx distro
- Your pbx has a routable IP (there are ways around this, you can totally send mail without one, but RDNS can get interesting this way. It also usually implies your behind someone else’s NAT, and getting any of the big ISPs to publish RDNS can be fun)
- You are sending mail from freepbx (not through another SMTP relay - particularly if you are just sending through a gmail account, they take care of most of this for you)
- You have set up DNS and RDNS (RDNS is critical for SPF)
No on site config is necessary, assuming you have set DNS and RDNS appropriately, add an a: record to your existing SPF. i.e.
mydomain.com. TXT "v=spf1 a:freepbx.mydomain.com include:_spf.google.com ~all"
In my case, I use google domain apps for most of my email.
You’ll need CLI access for this.
$ yum install opendkim $ cd /etc/opendkim/keys
mydomain should be your domain, myselector can be any alpha-numeric string. I used freepbx.
$ opendkim-genkey -d mydomain.com -s myselector
Don’t forget to change the ownership of the private key, or opendkim will not start
$ chown opendkim:opendkim myselector.private
$ vim /etc/opendkim.conf
## Selects operating modes. Valid modes are s (sign) and v (verify). Default is v. ## Must be changed to s (sign only) or sv (sign and verify) in order to sign outgoing ## messages. Mode sv ## Create a socket through which your MTA can communicate. Socket inet:8891@localhost ## Selects the canonicalization method(s) to be used when signing messages. Canonicalization relaxed/simple ## Domain(s) whose mail should be signed by this filter. Mail from other domains will ## be verified rather than being signed. Uncomment and use your domain name. ## This parameter is not required if a SigningTable is in use. Domain mydomain.com ## Defines the name of the selector to be used when signing messages. Selector myselector ## Gives the location of a private key to be used for signing ALL messages. This ## directive is ignored if KeyTable is enabled. KeyFile /etc/opendkim/keys/myselector.private
Put these all the way at the bottom. If for some reason you changed the listening host or port of the socket, make sure you reflect that here (for some reason an ubuntu install I have used a different port - make sure to match them)
$ vim /etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:8891 non_smtpd_milters = $smtpd_milters milter_default_action = accept
Add the DNS record
You will like your life better if you add the DNS TXT record before sending your first test, as most of the big email services cache the results for a good while. The full record is located in:
$ cat /etc/opendkim/keys/myselector.txt
It’s an exercise for the reader to understand how to update their DNS records, reload and propegate them. But you can check that it is in there with something like:
$ dig -t txt myselector._domainkey.mydomain.com @184.108.40.206
Start and enable opendkim, restart postfix:
$ systemctl start opendkim ; systemctl enable opendkim ; systemctl restart postfix
If everything is working, you’ll see something like this in /var/log/maillog:
Oct 7 10:30:19 freepbx opendkim: OpenDKIM Filter v2.11.0 starting (args: -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid)
OpenDKIM signing a message:
Oct 7 10:32:15 freepbx opendkim: 754A6602F3B0: DKIM-Signature field added (s=myselector, d=mydomain.com)
If it works, and you have gmail, clicking on “show original” will give you the SPF / DKIM / DMARC results. A “good” result looks something like this, pardon the redactions.
This document doesn’t really touch on how this bit works - there are too many much better resources out there that do a far better job than I could, and it does not require anything done on the freepbx system itself.
Questions / Comments
I welcome any questions or comments, but this is really meant to be a log of what I did to get this to work - I am by no means an expert - for specific error messages, I suspect google will be more useful than I will be, but I’ll do my best as I can.