diff --git a/content/blog/mail_server_alpine_postfix_dovecot_tutorial.md b/content/blog/mail_server_alpine_postfix_dovecot_tutorial/index.md similarity index 75% rename from content/blog/mail_server_alpine_postfix_dovecot_tutorial.md rename to content/blog/mail_server_alpine_postfix_dovecot_tutorial/index.md index 6e9394d..21240ea 100644 --- a/content/blog/mail_server_alpine_postfix_dovecot_tutorial.md +++ b/content/blog/mail_server_alpine_postfix_dovecot_tutorial/index.md @@ -782,6 +782,292 @@ With our setup, we are also able to use STARTTLS on port 143 (incoming) and 587 You should be able to send and receive emails as normal now. +# Set up SPF, DKIM, and DMARC + +SPF, DKIM, and DMARC records are TXT DNS records that +protect against people spoofing your domain. Having correctly configured SPF, DKIM, and DMARC records helps your mail +avoid getting caught by spam filters. + +SPF records indicate which hosts or IP addresses are allowed to send email from your domain. + +DKIM digitally signs emails with a private key to verify that they came from your server. If someone else without your +private key sends email from your domain, they wouldn't be able to produce a valid DKIM signature. DKIM public keys are +published in TXT DNS records, so that any other mail server can verify a signature of an email from your domain. + +DMARC records state that your domain uses SPF and DKIM, and that emails sent from your domain should pass SPF and DKIM +checks. + +## Sender Policy Framework + +Add a TXT record for your root domain with the contents `v=spf1 mx ~all`, like: + +```dns +revsuine.xyz. 900 IN TXT "v=spf1 mx ~all" +``` + +In your DNS manager, you would enter: + + + + + + + + + + + + + + + + + + + + +
Name@
TypeTXT
TTLDefault (mine is 900)
TXT datav=spf1 mx ~all
+ +This is assuming you're sending emails from `domain.com` instead of, e.g. `sub.domain.com`. If your email addresses are +like `user@sub.domain.com`, you would use `sub` as the name in the DNS record instead of `@`, which denotes the apex +domain. The same applies for all the DNS records in this section. + +Breaking down the TXT data: + + + + + + + + + + + + + + + + + + + + +
PartExplanation
v=spf1This is an SPF record, and the SPF record version is SPF1.
mxAll hosts listed in MX records are allowed to send emails from this domain.
~all + Emails from your domain should only come from hosts specified by your SPF record. Can also be + +all, -all, ?all, but those are rarely used. -all means + that emails not from SPF-approved hosts should be rejected; however, this option can cause valid emails to + be rejected if the recipient has multiple SMTP servers, and an email is relayed from one of their SMTP + servers to another, for instance if one SMTP server goes down and they have a backup server. +
+ +## DomainKeys Identified Mail + +### Configure OpenDKIM + +OpenDKIM is an open-source implementation of DKIM signing and authentication. You can install it with: + + # apk add opendkim opendkim-utils + +You may also want `opendkim-doc` for documentation. + +Add the `postfix` user to the `opendkim` group: + + # adduser postfix opendkim + +Edit your OpenDKIM config file at `/etc/opendkim/opendkim.conf`. Ensure the following is present (`Canonicalization` is +likely already there, so just change and uncomment things, and add lines where necessary): + +```conf +Canonicalization relaxed/simple +Mode sv +SubDomains no +AutoRestart yes +AutoRestartRate 10/1M +Background yes +DNSTimeout 5 +SignatureAlgorithm rsa-sha256 +``` + +Add the following to the config file: + +```conf +# OpenDKIM user +# Remember to add user postfix to group opendkim +UserID opendkim + +# 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 +``` + +Create a directory for OpenDKIM's keys at `/etc/opendkim/keys/`, and ensure the directory is owned by `opendkim` and +that no one else has read or write access to the keys directory: + + # mkdir /etc/opendkim/keys + # chown -R opendkim:opendkim /etc/opendkim + # chmod go-rw /etc/opendkim/keys + +Create `/etc/opendkim/signing.table` and set its contents to the following: + +``` +*@domain.com default._domainkey.domain.com +*@*.domain.com default._domainkey.domain.com +``` + +This tells OpenDKIM to use your domain's private key to sign any emails originating from `domain.com` and its +subdomains. Replace `domain.com` with your domain. + +Now create `/etc/opendkim/key.table` and set its contents to: + +``` +default._domainkey.domain.com domain.com:default:/etc/opendkim/keys/domain.com/default.private +``` + +Replacing `domain.com` with your domain. This tells OpenDKIM where your private key is stored. + +Create `/etc/opendkim/trusted.hosts` and set its contents to + +``` +127.0.0.1 +localhost + +.domain.com +``` + +Similarly, replace `domain.com` with your domain. + +### Generate your keys + +Create a directory for your domain's keys at `/etc/opendkim/keys/domain.com`. Use `opendkim-genkey` to generate your +keys: + + # opendkim-genkey -b 2048 -d domain.com -D /etc/opendkim/keys/domain.com -s default -v + +Replace `domain.com` with your domain. + +Set the owner and permissions of the private key so that only `opendkim` has read and write access to it: + + # chown opendkim:opendkim /etc/opendkim/keys/domain.com/default.private + # chmod 600 /etc/opendkim/keys/domain.com/default.private + +### Publish your public key in your DNS records + +Look at your public key: + + # cat /etc/opendkim/keys/domain.com/default.txt + +You'll see something like this: + +``` +default._domainkey IN TXT ( "v=DKIM1; k=rsa; " + "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu7QJxihVsEGhsZBLMxGKCVecIhjINp/zMGH0ExHN5QelxRIKdAHpJ33cZUBEsL0H27/4E8BK9RZ4AOaDMHfIGJ9FybyyD+gHhvKFFHzyts0QpkwLV+3bApsMqSR4ZsSzt3pZvRhQrXaoUds+9CyQBuEGx16PcA2O04/vWlvWhwStJrZWWHDYl2PX3QHfFFSsJaTsiFMwnMECvg" + "a6TdBTcsbcHwfedkoeMv5RQFlKisqCEiJkUYbJaczDA88fcZm21eGW8HiCSwq3324ExfWSwPGVsXAn1Blq/oKklpjXQIwwrphglK//G6AF7M3AAfqBdCvUbkAjs28fJwGqiVxaCwIDAQAB" ) ; ----- DKIM key default for revsuine.xyz +``` + +This is what your DNS record should look like. Copy **everything between the brackets** and add it to your DNS record: + + + + + + + + + + + + + + + + + + + + +
Namedefault._domainkey
TypeTXT
TTLDefault value (mine is 900)
TXT data + What you copied from between the brackets, with all double quotes and extra whitespace (beyond a single + space character) removed +
+ +So with the above public key, my DNS record is + +```dns +default._domainkey.revsuine.xyz. 900 IN TXT ( + "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQ" + "EFAAOCAQ8AMIIBCgKCAQEAu7QJxihVsEGhsZBLMx" + "GKCVecIhjINp/zMGH0ExHN5QelxRIKdAHpJ33cZU" + "BEsL0H27/4E8BK9RZ4AOaDMHfIGJ9FybyyD+gHhv" + "KFFHzyts0QpkwLV+3bApsMqSR4ZsSzt3pZvRhQrX" + "aoUds+9CyQBuEGx16PcA2O04/vWlvWhwStJrZWWH" + "DYl2PX3QHfFFSsJaTsiFMwnMECvg a6TdBTcsbcH" + "wfedkoeMv5RQFlKisqCEiJkUYbJaczDA88fcZm21" + "eGW8HiCSwq3324ExfWSwPGVsXAn1Blq/oKklpjXQ" + "IwwrphglK//G6AF7M3AAfqBdCvUbkAjs28fJwGqi" + "VxaCwIDAQAB" + ) +``` + +and what I entered into the data field of my DNS manager when adding the record was + +``` +v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu7QJxihVsEGhsZBLMxGKCVecIhjINp/zMGH0ExHN5QelxRIKdAHpJ33cZUBEsL0H27/4E8BK9RZ4AOaDMHfIGJ9FybyyD+gHhvKFFHzyts0QpkwLV+3bApsMqSR4ZsSzt3pZvRhQrXaoUds+9CyQBuEGx16PcA2O04/vWlvWhwStJrZWWHDYl2PX3QHfFFSsJaTsiFMwnMECvg a6TdBTcsbcHwfedkoeMv5RQFlKisqCEiJkUYbJaczDA88fcZm21eGW8HiCSwq3324ExfWSwPGVsXAn1Blq/oKklpjXQIwwrphglK//G6AF7M3AAfqBdCvUbkAjs28fJwGqiVxaCwIDAQAB +``` + +You can now test your DKIM key with: + + # opendkim-testkey -d domain.com -s default -vvv + +Don't worry about + +``` +opendkim-testkey: key not secure +``` + +This just means that DNSSEC isn't enabled for your domain name. + +### Use OpenDKIM with Postfix + +You can use a Unix socket for this, but I couldn't get the Unix socket to work, so I'll show you how to connect Postfix +to OpenDKIM using a TCP/IP socket on port 8891 instead. + +Edit your OpenDKIM config `/etc/opendkim/opendkim.conf`, and ensure that the following line is present: + +```conf +Socket inet:8891@localhost +``` + +Also make sure there are no other uncommented `Socket` lines. + +Now configure Postfix at `/etc/postfix/main.cf`, and add the following lines: + +```conf +milter_default_action = accept +milter_protocol = 6 +smtpd_milters = inet:127.0.0.1:8891 +non_smtpd_milters = $smtpd_milters +``` + +This uses the Milter extension, which is something that can be used to process mail; in this case, to add headers to +emails relating to DKIM. + + + +### Test SPF, DKIM, and DMARC + +You can use [mail-tester.com](https://www.mail-tester.com/) and send an email from your domain to check that SPF, DKIM, +and DMARC are all working for your server. + +![Screenshot of mail-tester.com authentication results passing all checks](mail-tester_auth_results.png) + [^server_trust]: This is only true to the extent that your server is not compromised. You could say there's an order of diff --git a/content/blog/mail_server_alpine_postfix_dovecot_tutorial/mail-tester_auth_results.png b/content/blog/mail_server_alpine_postfix_dovecot_tutorial/mail-tester_auth_results.png new file mode 100644 index 0000000..fc95125 Binary files /dev/null and b/content/blog/mail_server_alpine_postfix_dovecot_tutorial/mail-tester_auth_results.png differ