E-MailRelay

E-Mail Relay

The following diagrams are what this document will accomplish. The challenge is to obtain and keep a good reputation that other E-Mail handlers around the world will accept. Otherwise your messages will be dumped in the trash can (SPAM) or sent back to you (bounced).


Table of Contents

Overview

E-Mail Relay is a combination of:

  • IP Address Reputation
  • DNS assignment of an E-Mail name to that IP Address
  • Certificates for Authentication and Encryption
  • Login protection against Open Spam Relays

A VPS (Virtual Private Server) is a way to obtain a good IP address reputation, and it will stay the same number over time. There are many to choose from, some already have bad reputations and constant streams of hackers knocking on the network, while others have a good reputation and just a few random hackers on your doorstep. Choose wisely!

  • MUA - Mail User Agent; Thunderbird, Evolution - Read, send, user interface
  • MDA - Mail Delivery Agent; Dovecot - File and organize mail, authorize user accounts
  • MTA - Mail Transport Agent; Postfix - Move messsages from one network stop to another

Outgoing: Relay from Inside Home

Send Mail from Home

Outgoing: Relay from Outside Home

Send Mail outside Home

Incoming: Transport from Internet

Recieve Mail

This document will use:

  • your-domain.org : The E-Mail relay we are setting up in this document (VPS_Postfix)
  • your-domain.com : The E-Mail server set up in the prior document (Home_Postfix)

Recommendation:

  • [ ] Bring up a host on a VPS somewhere, and use the Setup Server instructions to secure it.
  • [ ] Get a domain name and certificate set up and working.
  • [ ] Install postfix/dovecot combo and relay to your main E-Mail host. Test sending out mail too.
  • [ ] Install and configure SPF Policy Agent. Test it and make sure all is well.
  • [ ] Install and configure OpenDKIM to sign your E-Mails. Ensure it works good.

VPS

Create a VPS Cloud Server, less than $10 month for 1GB RAM, 30GB Disk, 1 CPU, 2TB Bandwidth month.

Criteria:

  1. IP address reputation. May have to test drive to determine IP address. Lookup tools:
  2. https://github.com/nitefood/asn
  3. https://www.ipqualityscore.com/ip-reputation-check
  4. Working control panel. Check online reviews, or test drive. Make sure every button works. Extra points if they allow firewall changes and creating a PTR record.
  5. Current OS release. Check references below.
  6. Support availability and response agreements. Test creating a support ticket. Check references below.
  7. Low cost, check references below.

  8. https://cloud.ionos.com/servers/vps#packages

  9. https://www.hostwinds.com/vps/unmanaged-linux
  10. https://www.inmotionhosting.com/cloud-vps
  11. https://www.kamatera.com/Products/201/Cloud_Servers

Secure VPS on your-domain.org

Change your root password IMMEDIATELY. Hackers know the algorithm and expliot it from creation time to change time.

Change the ssh port from 22 (File: /etc/ssh/sshd_config). Hackers know that port and constantly attack it.

Check Network

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Network Check

Update Package Repository

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Update Packages

Create New User(s)

The Linux mail user can be \<name>@example.com, to keep things clear.

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * New Users

Set Host and Domain

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Host and Domain

Set Date and Time

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Date and Time Settings

Monitor crack attempts

Install firewall and fail2ban on your-domain.org

Be sure the system firewall is installed and also the "Block Bad Actors" firewall.sh script.

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Firewall

Add rules for E-Mail smtp and smtps.

  • Debian:
$ sudo apt-get install fail2ban mailutils
  • RedHat:
$ sudo dnf install fail2ban mailx

Make sure firewall rules open port smtp(25) and smtps(465):

  • Debian
$ sudo ufw allow 25
$ sudo ufw allow 465
$ sudo ufw status numbered

     To                         Action      From
     --                         ------      ----
[ 1] 22                         ALLOW IN    Anywhere                  
[ 2] 25                         ALLOW IN    Anywhere                  
[ 3] 465                        ALLOW IN    Anywhere                  
[ 4] 22 (v6)                    ALLOW IN    Anywhere (v6)             
[ 5] 25 (v6)                    ALLOW IN    Anywhere (v6)  
  • RedHat
$ sudo firewall-cmd --add-service=smtp
 success
$ sudo firewall-cmd --add-service=smtps
 success
$ sudo firewall-cmd --list-services
  smtp smtps ssh
$ firewall-cmd --runtime-to-permanent
 success
$ firewall-cmd --reload
 success

Configure fail2ban

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser:

Secure postfix

File: /etc/fail2ban/jail.d/postfix.local

[postfix]
enabled  = true
maxretry = 3
bantime = 1d
port     = smtp,465,submission

[postfix-sasl]
enabled  = true
maxretry = 3
bantime = 1d
port     = smtp,465,submission,imap,imaps,pop3,pop3s

File: /etc/fail2ban/jail.d/dovecot.local

[dovecot]
enabled = true
port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = /var/log/maillog
findtime = 1200
bantime = 1d
Secure ssh

File: /etc/fail2ban/jail.d/sshd.local

[sshd]
port = XXXX
enabled = true
maxretry = 3
bantime = 1d

Log Monitors on your-domain.org

Install Logwatch

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Logwatch

Install Logcheck:

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser: * Logcheck

LogWatcher

Create

Put this script in the /root directory, and install the dependencies listed.

#!/bin/bash
##############################################################################
#
# File: logwatcher.sh
#
# Purpose: Watch for interesting new things in log files and e-mail them
#
# Dependencies: 
#  * Debian:
#   apt-get install git clang zlib1g-dev
#  * RedHat:
#   dnf install git clang zlib-devel 
#
#   git clone https://github.com/mbucc/retail
#
# Author     Date     Description
# ---------- -------- --------------------------------------------------------
# D. Cohoon  Feb-2023 Created
##############################################################################
MAILTO=root
DIR=/root
OS=$(/usr/bin/hostnamectl|/usr/bin/grep 'Operating System'|/usr/bin/cut -d: -f2|/usr/bin/awk '{print $1}')
cd ${DIR}
#--------------
log_check () {
  OFFSET=${1}
  LOGFILE=${2}
  FILTER=${3}
  OUTPUT=$(/usr/bin/mktemp)
  /root/retail/retail -o ${OFFSET} ${LOGFILE} | ${FILTER} >${OUTPUT}
  if [ -s ${OUTPUT} ]; then
    /bin/cat ${OUTPUT} | /usr/bin/mail -s "Logwatcher.sh: ${OFFSET}" ${MAILTO} 2>/dev/null
  fi
  rm -rf ${OUTPUT}
}
#
#--------------
case ${OS} in
    AlmaLinux) 
        FAIL2BAN_LOG=/var/log/fail2ban.log
        POSTFIX_LOG=/var/log/maillog
        AUTH_LOG=/var/log/secure 
        ;;
    Ubuntu|Debian) 
        FAIL2BAN_LOG=/var/log/fail2ban.log
        POSTFIX_LOG=/var/log/syslog
        AUTH_LOG=/var/log/auth.log
        ;;
esac
#           Offset  Log File               Filter
#          -------- ---------------------  -------------------------
log_check .fail2ban "${FAIL2BAN_LOG}"      ${DIR}/filter_fail2ban.sh
#
log_check .postfix  "${POSTFIX_LOG}"       ${DIR}/filter_postfix.sh
#
log_check .sshd     "${AUTH_LOG}"          ${DIR}/filter_ssh.sh
#
log_check .dovecot  "${AUTH_LOG}"          ${DIR}/filter_dovecot.sh

Schedule

# cat /etc/cron.d/logwatcher 
# /etc/cron.d/logwatcher: crontab entries for the logwatcher.sh script

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

@reboot         root   /root/logwatcher.sh 
2 * * * *       root   /root/logwatcher.sh 

# EOF

Filters

File: filter_fail2ban.sh

/usr/bin/grep "Ban"

File: filter_postfix.sh

/usr/bin/grep "postfix"|/usr/bin/grep 'disconnect from unknown'

File: filter_ssh.sh

/usr/bin/grep "ssh" | /usr/bin/egrep "Failed|invalid format"

File: filter_dovecot.sh

/usr/bin/grep "dovecot" | /usr/bin/grep "authentication failure"

Make the Scripts Executable

$ chmod 755 *.sh

Reference:

Apache install (enable) on your-domain.org

Click on this heading, then refer to these instructions, then come back here with the Back Arrow on the Browser:

Apache Web Server

Test it on:

$ curl http://<domain.name>

Add SSL

  • Debian
$ sudo ufw allow 443/tcp
  • RedHat
$ sudo firewall-cmd --add-service=https
  success
$ sudo firewall-cmd --list-services
  http https smtp smtps ssh
$ sudo firewall-cmd --runtime-to-permanent
  success
$ sudo firewall-cmd --reload
  success

Change the default landing page to blank

File: /var/www/html/index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  </head>
  <body>
    <div class="main_page">
    </div>
  </body>
</html>

DNS Registrar (your-domain.org)

Register your own name.

DNS Updates

Create Advanced DNS records, using IP Address of VPS server:

HOST

Type       Host        Value               TTL
---------- ----------- ------------------- ----
A Record   @           <IP Address>        Auto
A Record   mail        <IP Address>        Auto
TXT Record @           v=spf1 mx -all      Auto

MAIL

Type       Host        Value               Priority TTL
---------- ----------- ------------------- -------- ----
MX Record  @           <Domain Name>       10       Auto

Lookup status via dig -t <Type> <Domain>

$ dig -t a +short <Domain Name>
123.123.123.123
$ dig -t mx +short <Domain Name>
10 <Domain Name>.

To install dig: $ sudo apt-get install dnsutils $ sudo dnf install bind-utils

Create PTR Record

Using the Control Panel on the VPS, update the PTR record. If they do not allow this, create a support ticket, they will do it then, just trying to limit spammers.

Test your PTR record. Using the IP Address, it should show your domain, proving you have control over the IP Address.

dig -x 1.2.3.4
;; ANSWER SECTION:
1.2.3.4.in-addr.arpa. 86400 IN  PTR mail.<Domain Name>.

certbot - Certificate Management for Let's Encrypt

To create and maintain LetsEncrypt certificates using Apache web server

Install

  • The Debian Way
$ sudo systemctl unmask apache2
$ sudo systemctl enable apache2
$ sudo systemctl start apache2
$ sudo apt-get install certbot
$ sudo apt-get install python3-certbot-apache
$ sudo systemctl unmask httpd
$ sudo systemctl enable httpd
$ sudo systemctl start httpd
$ sudo dnf install certbot
$ sudo dnf install python3-certbot-apache
$ sudo certbot  plugins

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* apache
Description: Apache Web Server plugin
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: apache = certbot_apache._internal.entrypoint:ENTRYPOINT

* standalone
Description: Spin up a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot._internal.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Configure

Be sure to get certificates for the domain and all subdomains (hosts)

$ certbot  --apache -d your-domain.org -d mail.your-domain.org
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): you@your-domain.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
Account registered.
No names were found in your configuration files. Please enter in your domain
name(s) (comma and/or space separated)  (Enter 'c' to cancel): your-domain.org
Requesting a certificate for your-domain.org
Performing the following challenges:
http-01 challenge for your-domain.org
Enabled Apache rewrite module
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/apache2/sites-available/000-default-le-ssl.conf
Enabled Apache socache_shmcb module
Enabled Apache ssl module
Deploying Certificate to VirtualHost /etc/apache2/sites-available/000-default-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/000-default-le-ssl.conf
Enabled Apache rewrite module
Redirecting vhost in /etc/apache2/sites-enabled/000-default.conf to ssl vhost in /etc/apache2/sites-available/000-default-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://your-domain.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Subscribe to the EFF mailing list (email: you@your-domain.org).

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/your-domain.org/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/your-domain.org/privkey.pem
   Your certificate will expire on 2023-05-08. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again with the "certonly" option. To non-interactively
   renew *all* of your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Apache (disable)

Apache is not needed, so disable it to reduce threat footprint.

$ sudo systemctl stop apache2
$ sudo systemctl disable apache2
$ sudo systemctl mask apache2
$ sudo ufw status numbered
# -> ufw delete <n> for ports 80 & 443
$ sudo systemctl stop httpd
$ sudo systemctl disable httpd
$ sudo systemctl mask httpd
$ sudo  firewall-cmd --remove-service=https
  success
$ sudo firewall-cmd --list-services
  http smtp smtps ssh
$ sudo  firewall-cmd --remove-service=http
  success
$ sudo firewall-cmd --list-services
  smtp smtps ssh
$ sudo firewall-cmd --runtime-to-permanent
  success

When the Let's Encrypt Certificate expires, you will need to enable it again and open up ports.

postfix - E-Mail Transport Agent

Install postfix MTA and remove exim4, if it is installed. Postfix is more mature and full-featured.

TLS http://www.postfix.org/TLS_README.html

Install on your-domain.org

$ sudo apt-get remove exim4-base
$ sudo apt-get install postfix
$ sudo dnf remove exim
$ sudo dnf install postfix

Configure on your-domain.org

  • smtp -> outgoing mail
  • smtpd <- incoming mail (daemon)

Complete main.cf file contents

~
mydomain = your-domain.org
myorigin = $mydomain
#myorigin = /etc/mailname
~

Also in RedHat: Log is in /var/log/maillog

File main.cf

#.........................................................................
#
# * smtpd <- incoming mail (daemon)
#
smtpd_tls_cert_file = /etc/letsencrypt/live/your-domain.org/fullchain.pem
smtpd_tls_key_file  = /etc/letsencrypt/live/your-domain.org/privkey.pem
smtpd_use_tls = yes
smtpd_tls_security_level=may
smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#
# Enforce TLSv1.3 or TLSv1.2
#  smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
#  smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
#  smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
#  smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
#
# Sending relays allowed only if:
# -> you are on mynetworks
# -> you are logged in
#  all others are deferred (temp error 4.x.x), 
#   like a permanent failure that won't go away
#   until 1) added to mynetworks, or 2) sasl authenticated
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination

# Sending sasl auth from Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

# I am a relay to the world
relayhost = 

#.........................................................................
#
# * smtp  -> outgoing mail 
#
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# Receiving transport table specifies a mapping from email addresses to 
#  message delivery  transports  and  next-hop  destinations. 
# (relay forwarding back out)
transport_maps = hash:/etc/postfix/transport
relay_domains = your-domain.com

# .org host
myhostname = mail.your-domain.org
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname

# Accept final destination mail for mail.your-domain.org, your-domain.org, or locals
mydestination = $myhostname, your-domain.org, localhost.your-domain.org, localhost
#.........................................................................

# Allow my host and the .com host to send (relay out)
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128  5.6.7.8
inet_interfaces = all
inet_protocols = ipv4

# Message restrictions
mailbox_size_limit = 0
message_size_limit = 52428800
header_size_limit = 4096000
recipient_delimiter = +

#compatibility_level = 2

Complete relay contents of master.cf

No spaces between = sign

File: master.cf

~
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd
smtps     inet  n       -       y       -       -       smtpd
    -o syslog_name=postfix/smtps
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# The preceeding 4 lines require SSL login for relay to internet (.com -> .org -> internet)
#  need cert for mail.your-domain.org, your-domain.org; 
#  and sasl_passwd for mail.your-domain.org unix login on www.your-domain.com
~
:wq

Reload Config

$ sudo postfix reload

Definitions of master fields

Proxy Postfix using Transport Maps for Incoming Mails on your-domain.org

A postfix transport(5) table allows one domain to transfer incoming SMTP messages to another domain. For instance the .org domain will transfer all .com messages to the .com domain automatically.

Repeated postfix file contents from above to clarify this is for transporting from .org to .com

Configure

File: /etc/postfix/main.cf:

~
    transport_maps = hash:/etc/postfix/transport
~

Set postfix to accept mails for the .com addresse.

Repeated postfix file contents from above to clarify this is for transporting from .org to .com

File: /etc/postfix/main.cf:

~
    relay_domains = example.com
~

Transport Definitions

Create a transport table to redirect all mail for one domain as well as mail for "user@mydomain.org" to another domain. You can also specify another port, to bypass port 25 restrictions.

File: /etc/postfix/transport

    example.com          smtp:[example.com]:10025
    user@mydomain.org   smtp:[example.com]:10025

Make it a database

Create a postmap database from the flat ascii file.

$ sudo postmap /etc/postfix/transport

Reload Config

Finally, reload the postfix configuration files.

$ sudo postfix reload

Reference:

Proxy Postfix Relay for SMTP Outgoing Mails

To send mails from a non-standard port, use a .com domain to relay to a .org domain, with the .org relay set to = (basically null) and the .com relay = ...org.

Change MX records in no-ip.com from mail1.no-ip.com to mail.your-domain.org

Log into noip.com, go to DNS and select *.your-domain.com. At the bottom of the page you can change the mail1.no-ip.com record to mail.your-domain.org.

Don't forget to save and lookup the new value using dig -t MX your-domain.com.

Change TXT spf record in no-ip.com from noip, to:

For your-domain.com domain:

Type Host Value Priority TTL
MX Record @ your-domain.org 10 Auto
TXT Record @ v=spf1 mx a include:your-domain.org ~all Auto

SPF tools: https://www.dynu.com/en-US/NetworkTools/SPFGenerator# https://mxtoolbox.com/spf.aspx

  • Try not to add more than required, you might create a potential infinite loop. 8

On the DNS for .com, create a TXT record like this

"v=spf1 mx a include:<Domain of .org> ~all"

Basically is says "In the DNS TXT record for email destination you@your-domain.com, validate the MX IP Address of DNS record for domain your-domain.com" for ~all; When an SPF record includes ~all (softfail qualifier), receiving servers typically accept messages from senders that aren't in your SPF record, but mark them as suspicious.

Reference: http://www.open-spf.org/FAQ/Common_mistakes/#list-domains

Test e-mail results from google:

~
ARC-Authentication-Results: i=1; mx.google.com;
       spf=pass (google.com: domain of you@your-domain.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=you@your-domain.com
Received: from mail.your-domain.org (mail.your-domain.org. [1.2.3.4])
        by mx.google.com with ESMTPS id o6-20020a0dcc06000000b005363cf948basi2222119ywd.61.2023.02.25.05.45.43
        for <you.name@gmail.com>
        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
        Sat, 25 Feb 2023 05:45:44 -0800 (PST)
Received-SPF: pass (google.com: domain of you@your-domain.com designates 1.2.3.4 as permitted sender) client-ip=1.2.3.4;
Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of you@your-domain.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=you@your-domain.com
Received: from www.your-domain.com (unknown [5.6.7.8])
    by mail.your-domain.org (Postfix) with ESMTPSA id 9071FD3C93
    for <you.name@gmail.com>; Sat, 25 Feb 2023 13:45:43 +0000 (UTC)
~

Change your-domain.com postfix/main.cf relay to your-domain.org

File: /etc/postfix/main.cf

relayhost = [mail.your-domain.org]:465

Add your-domain.org unix login on host your-domain.com

File: /etc/postfix/sasl/sasl_passwd

[mail.your-domain.org]:465 you:********

Create a postfix DB from flat file

$ sudo postmap /etc/postfix/sasl/sasl_passwd

Enable TLS on your-domain.org

TLS requires certificate(s) and SASL login verification.

The logon verification is done by Docevot using the userdb setting pam[1], while the postfix SASL verification uses a unix pipe /var/spool/postfix/private/auth to talk to Dovecot.

The encryption is enabled by Let's Encrypt certificates (one for the domain, another for each subdomain), over the smtps (post 465) network socket to the client. The master.cf file -o settings override the main.cf settings, ensuring a connection is only accepted if:

OR

Plugable Authentication Module (PAM) is the Linux login method for users

Two Steps:

  1. install dovecot

  2. The Debian Way

$ sudo apt-get install dovecot-core
$ sudo dnf install dovecot

Add login to dovecot auth

File: /etc/dovecot/conf.d/10-auth.conf

~
     auth_mechanisms = plain login
~
:wq

Set the certificates to letsencrypt, require ssl and prefer server of the ciphers

File: /etc/dovecot/conf.d/10-ssl.conf

~
    ssl = required
~
    ssl_cert = </etc/letsencrypt/live/your-domain.org/fullchain.pem
    ssl_key = </etc/letsencrypt/live/your-domain.org/privkey.pem
~
    # Comment out default certs
~
    ssl_prefer_server_ciphers = yes
~
:wq

Set up a local unix pipe for dovecot and postfix to communicate this authorization data, under the service_auth set of brackets.

File: /etc/dovecot/conf.d/10-master.conf

~
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0660
    user = postfix
  }
~
:wq
  1. Set the receiving certificates in Postfix, require TLS using Dovecot.

Repeated postfix file contents from above to clarify this is for relaying TLS on .org to the Internet

File: /etc/postfix/main.cf

~
#smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_cert_file = /etc/letsencrypt/live/your-domain.org/fullchain.pem
smtpd_tls_key_file  = /etc/letsencrypt/live/your-domain.org/privkey.pem
smtpd_use_tls = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_security_level=may

~

# sasl auth from Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

~
:wq

Repeated postfix file contents from above to clarify this is for relaying TLS on .org to the Internet

File: /etc/postfix/master.cf

~
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd
smtps     inet  n       -       y       -       -       smtpd
    -o syslog_name=postfix/smtps
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# The preceeding 4 lines require SSL login for relay to internet (.com -> .org -> internet)
#  need cert for mail.your-domain.org, your-domain.org; 
#  and sasl_passwd for mail.your-domain.org unix login on www.your-domain.com
~
:wq

Open on localhost

# nmap -sT -O localhost
Starting Nmap 7.70 ( https://nmap.org ) at 2023-02-19 16:46 EST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00019s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 992 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh   <-
25/tcp  open  smtp  <-
80/tcp  open  http  <-
110/tcp open  pop3
143/tcp open  imap
443/tcp open  https <-
465/tcp open  smtps <-
993/tcp open  imaps
995/tcp open  pop3s

RedHat 9 /etc/services shows port 465 as urd, so I switched the urd and alias smtps.

# grep smtps /etc/services
smtps           465/tcp           urd   # URL Rendesvous Directory for SSM / SMTP over SSL (TLS)

Now ss looks better:

# ss -ltap
State        Recv-Q    Send-Q        Local Address:Port            Peer Address:Port     Process                                                   
LISTEN       0         128                 0.0.0.0:ssh                  0.0.0.0:*         users:(("sshd",pid=1314,fd=3))                           
LISTEN       0         100                 0.0.0.0:smtp                 0.0.0.0:*         users:(("master",pid=23736,fd=13))                       
LISTEN       0         100                 0.0.0.0:imaps                0.0.0.0:*         users:(("dovecot",pid=23599,fd=41))                      
LISTEN       0         100                 0.0.0.0:pop3s                0.0.0.0:*         users:(("dovecot",pid=23599,fd=23))                      
LISTEN       0         100                 0.0.0.0:pop3                 0.0.0.0:*         users:(("dovecot",pid=23599,fd=21))                      
LISTEN       0         100                 0.0.0.0:imap                 0.0.0.0:*         users:(("dovecot",pid=23599,fd=39))                      
LISTEN       0         100                 0.0.0.0:smtps                0.0.0.0:*         users:(("master",pid=23736,fd=17))                       
ESTAB        0         52            1.2.3.4:ssh                   5.6.7.8:44958     users:(("sshd",pid=2402,fd=4),("sshd",pid=2278,fd=4))    
LISTEN       0         128                    [::]:ssh                     [::]:*         users:(("sshd",pid=1314,fd=4))                           
LISTEN       0         100                    [::]:imaps                   [::]:*         users:(("dovecot",pid=23599,fd=42))                      
LISTEN       0         100                    [::]:pop3s                   [::]:*         users:(("dovecot",pid=23599,fd=24))                      
LISTEN       0         100                    [::]:pop3                    [::]:*         users:(("dovecot",pid=23599,fd=22))                      
LISTEN       0         100                    [::]:imap                    [::]:*         users:(("dovecot",pid=23599,fd=40))   

Open to internet

$ sudo firewall-cmd --list-services
  http https smtp smtps ssh

Clients Mail User Agents (MUA)

These are the programs where a human interface resides, and where everybody reads, sends, deletes, and manages their E-Mail. Names such as: Thunderbird, Evolution, Mutt, Gmail, Outlook, etc.

Unix pipe for postfix to dovecot authenication of clients.

$ sudo ls -l /var/spool/postfix/private/auth
srw-rw---- 1 postfix postfix 0 Feb 10 10:21 /var/spool/postfix/private/auth

Port 587, aka: submission, is purposely ommited because it is a partial encryption called STARTTLS. This is deemed un-secure and not recommended.

MUA Connection Definitions

Read Mail

Send Mail

Debug

If mail queues up to send/resend, you can check and clear to queue

List mail queue
mailq
Look at message
postcat -vq DCE2182DEA
Flush queue
postsuper -d ALL deferred
or
postqueue -f

Cache files (send/receive) are in data_directory (/var/lib/postfix) as Berkley Databasees

Install a Mail User Agent for ssh

mutt is a nice local mail reader, for times when the network mail may not work, at least the local mail will.

$ sudo apt-get install mutt
$ sudo dnf install mutt

Install a nice ssh capable log reader

I like lnav. Just run lnav and by default it will read the syslog. Or run lnav /var/log/mail.log.

$ sudo apt-get install lnav
$ sudo dnf install lnav

Install a package marking tool

Debian only: apt-clone will create a nice bundle of all your current packages. Save this off in case you have to re-build your server.

$ sudo apt-get install apt-clone

Certificate Expiration Check

Run this every week/day in cron /root/cert_expire.sh 2 to E-Mail you reminders before it expires.

File: ~/cert_expire.sh

#!/bin/bash
# ----------------------------------------------------------------------
#
# File: cert_expire.sh
#
# Purpose: See what the expiration date is for Let's Encrypt Certificate
#
#
#  s_client : The s_client command implements a generic SSL/TLS client
#              which connects to a remote host using SSL/TLS.
#  -servername $DOM : Set the TLS SNI (Server Name Indication) extension
#                      in the ClientHello message to the given value.
#  -connect $DOM:$PORT : This specifies the host ($DOM) and optional
#                         port ($PORT) to connect to.
#  x509 : Run certificate display and signing utility.
#  -noout : Prevents output of the encoded version of the certificate.
#  -dates : Prints out the start and expiry dates of a TLS or SSL certificate.
#
# Don Cohoon - Jan 2023
# ----------------------------------------------------------------------
#
#
if [ $# -gt 0 ]; then
  A=${1}
else
  /usr/bin/echo "1) E-Mail"
  /usr/bin/echo "2) File"
  /usr/bin/echo "3) Web"
  /usr/bin/echo "4) Local"
  read A
fi
case ${A}
 in
   1)
    /usr/bin/echo "REMINDER: Restart postfix and dovecot to enable new certs"
    /usr/bin/echo "=> E-Mail Certificate: CTRL-C to exit"
    #/usr/bin/openssl s_client -connect mail.your-domain.org:25 -starttls smtp 2>/dev/null|/usr/bin/openssl x509 -noout -dates
    /usr/bin/openssl s_client -connect mail.your-domain.org:465  2>/dev/null|/usr/bin/openssl x509 -noout -dates
    ;;
   2)
    /usr/bin/echo "=> File Certificate"
    sudo /usr/bin/openssl x509 -enddate -noout -in /etc/letsencrypt/live/your-domain.org/fullchain.pem
    ;;
   3)
    /usr/bin/echo "REMINDER: Restart apache2 and nginx to enable new certs"
    /usr/bin/echo "=> www.your-domain.org Certificate: CTRL-C to exit"
    /usr/bin/openssl s_client -servername your-domain.org -connect www.your-domain.org:443 2>/dev/null | /usr/bin/openssl x509 -noout -dates
    ;;
   4)
    /usr/bin/echo "REMINDER: Restart apache2 and nginx to enable new certs"
    /usr/bin/echo "=> Local Web Certificate: CTRL-C to exit"
    /usr/bin/openssl s_client -connect localhost:443 | /usr/bin/openssl x509 -noout -dates
    ;;
esac

Configuring SPF Policy Agent

We also need to tell our Postfix SMTP server to check for SPF record of incoming emails. This doesn’t help ensure outgoing email delivery but help with detecting forged incoming emails.

Install required packages:

sudo apt install postfix-policyd-spf-python
sudo dnf install pypolicyd-spf

Test SPF

If you know the sender, recipient, and client_address, you can test them before turning SPF on in postfix.

Must have blank line as last input for policyd-spf

# Python Site Packages = /usr/lib/python3.9/site-packages/
# Source = /usr/lib/python3.9/site-packages/spf_engine/*
/usr/libexec/postfix/policyd-spf <<EOF
 request=smtpd_access_policy
 protocol_state=RCPT
 protocol_name=SMTP
 helo_name=ccpub6
 queue_id=hv8rp02v1sso
 instance=12345.6789
 sender=foo
 recipient=bar
 client_address=1.2.3.4
 client_name=bubba

EOF

Configure SPF

Add the following lines at the end of the file, which tells Postfix to start the SPF policy daemon when it’s starting itself.

File: /etc/postfix/master.cf

policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

File: /etc/postfix/master.cf

policyd-spf  unix  -       n       n       -       0       spawn
    user=nobody argv=/usr/libexec/postfix/policyd-spf

Append the following lines at the end of the file. The first line specifies the Postfix policy agent timeout setting. The following lines will impose a restriction on incoming emails by rejecting unauthorized email and checking SPF record.

File: /etc/postfix/main.cf

policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   check_policy_service unix:private/policyd-spf

Restart Postfix.

sudo systemctl restart postfix

Next time, when you receive an email from a domain that has an SPF record, you can see the SPF check results in the raw email header. The following header indicates the sender sent the email from an authorized host.

Received-SPF: Pass (sender SPF authorized).

Debug SPF

Config file, debug setting:

File: /etc/python-policyd-spf/policyd-spf.conf

~
# level 1 is default
debugLevel = 5
~
:wq
man policyd-spf.conf

check_policy_service Unix pipe:

File: /var/spool/postfix/private/policyd-spf

srw-rw-rw-. 1 postfix postfix 0 Feb 25 14:37 /var/spool/postfix/private/policyd-spf

Block Domains and E-Mail Addresses using Postfix access

The following example uses an indexed file, so that the order of table entries does not matter.

File: /etc/postfix/main.cf:

 smtpd_client_restrictions =
   check_client_access hash:/etc/postfix/access

The example permits access by the client at address 1.2.3.4 but rejects all other clients in 1.2.3.0/24.

File: /etc/postfix/access:

1.2.3   REJECT
1.2.3.4 OK
aol.com REJECT

Create hash map of ascii file, and restart postfix

$ sudo postmap  /etc/postfix/access
$ sudo systemctl restart postfix

Reference: * http://www.open-spf.org/FAQ/Common_receiver_mistakes/ * https://www.mankier.com/5/policyd-spf.conf * http://www.postfix.org/access.5.html

Setting up DKIM

OpenDKIM is an open source implementation of the DKIM (Domain Keys Identified Mail) sender authentication system proposed by the E-mail Signing Technology Group (ESTG), now standardized by the IETF (RFC6376). It also includes implementations of the RFC5617) Vouch By Reference (VBR, RFC5518) proposed standard and the experimental Authorized Third Party Signatures protocol (ATPS, RFC6541).

Install OpenDKIM

sudo apt install opendkim opendkim-tools
# enable the CodeReady Linux Builder repository. You already have access to it; you just need to enable it.
dnf config-manager --set-enabled crb
# install the EPEL RPM
dnf install epel-release epel-next-release
# install
sudo dnf install opendkim opendkim-tools

Configure OpenDKIM

Add user postfix to group opendkim.

sudo gpasswd -a postfix opendkim

Check OpenDKIM main configuration file for Syslog, Logwhy.

Logwhy will generate more detailed logs for debugging.

File: /etc/opendkim.conf

Syslog               yes
Logwhy               yes

Set Canonicalization used when signing messages. The recognized values are relaxed and simple as defined by the DKIM specification. The default is simple. The value may include two different canonicalizations separated by a slash ("/") character, in which case the first will be applied to the header and the second to the body.

Set operating Modes. The string is a concatenation of characters that indicate which mode(s) of operation are desired. Valid modes are s (signer) and v (verifier). The default is sv except in test mode (see the opendkim(8) man page) in which case the default is v. When signing mode is enabled, one of the following combinations must also be set: (a) Domain, KeyFile, Selector, no KeyTable, no SigningTable; (b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector; (c) KeyTable, SetupPolicyScript, no Domain, no KeyFile, no Selector.

File: /etc/opendkim.conf

Canonicalization   relaxed/simple
Mode               sv

Add restart definitions to the end of the file.

File: /etc/opendkim.conf

AutoRestart       yes
AutoRestartCount  10
AutoRestartRate   10/1H

Reference: http://www.opendkim.org/opendkim.conf.5.html

Map Domains to Keys

The next two configuration items will create maps for E-Mail Domains in the From: header, to keys used to sign messages.

File: /etc/opendkim.conf

KeyTable        /etc/opendkim/KeyTable
SigningTable    refile:/etc/opendkim/SigningTable

KeyTable need "refile:"? (wildcards not allowed)

Hosts to ignore when verifying signatures

Identifies a set of "external" hosts that may send mail through the server as one of the signing domains without credentials as such. This has the effect of suppressing the "external host (hostname) tried to send mail as (domain)" log messages. Entries in the data set should be of the same form as those of the PeerList option below. The set is empty by default.

File: /etc/opendkim.conf

ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts

A set of internal hosts whose mail should be signed

Identifies a set internal hosts whose mail should be signed rather than verified. Entries in this data set follow the same form as those of the PeerList option below. If not specified, the default of "127.0.0.1" is applied. Naturally, providing a value here overrides the default, so if mail from 127.0.0.1 should be signed, the list provided here should include that address explicitly.

File: /etc/opendkim.conf

InternalHosts   refile:/etc/opendkim/TrustedHosts

Save and close the file.

Create Signing Table, Key Table and Trusted Hosts File

Check directory structure for OpenDKIM

$ sudo ls -lR /etc/opendkim*
-rw-r--r-- 1 root     root     5346 Mar  2 11:15 /etc/opendkim.conf

/etc/opendkim:
total 12
drwx--x--- 2 opendkim opendkim    6 Feb 24  2022 keys
-rw-r----- 1 opendkim opendkim  339 Feb 24  2022 KeyTable
-rw-r----- 1 opendkim opendkim 1221 Feb 24  2022 SigningTable
-rw-r----- 1 opendkim opendkim  378 Feb 24  2022 TrustedHosts

/etc/opendkim/keys:
total 0

If not the same, change the owner from root to opendkim and make sure only opendkim user can read and write to the keys directory.

sudo chown -R opendkim:opendkim /etc/opendkim

sudo chmod go-rw /etc/opendkim/keys

Create the signing table

Add two lines to the file.

The first line tells OpenDKIM that if a sender on your server is using a @your-domain.com address, then it should be signed with the private key identified by default._domainkey.your-domain.com.

The second line tells that your sub-domains will be signed by the private key also.

File: /etc/opendkim/SigningTable

*@your-domain.com    default._domainkey.your-domain.com
*@*.your-domain.com    default._domainkey.your-domain.com

Save and close the file.

Create the key table

Add the following line, defining the location of the private key.

File: /etc/opendkim/KeyTable

default._domainkey.your-domain.com     your-domain.com:default:/etc/opendkim/keys/your-domain.com/default.private

Save and close the file.

Create the trusted hosts file

Tell OpenDKIM if an email is from localhost or the same domain, then only sign the email, and not perform DKIM verification.

File: /etc/opendkim/TrustedHosts

127.0.0.1
localhost

.your-domain.com

Save and close the file.

Do not add an asterisk to the domain name like this: *.your-domain.com. Put only a dot before the domain name.

Generate Private/Public Keypair

DKIM is used to sign outgoing messages and verify incoming messages, so we need to generate a private key for signing and a public key for remote verifier. Only the public key will be published in DNS.

Create a separate folder for the domain.

sudo mkdir /etc/opendkim/keys/your-domain.com

Generate keys using opendkim-genkey tool.

You should rotate in new keys every once and a while for protection against private key leaks. Allow seven days before deleting the old keys for existing E-Mails to be delivered.

sudo opendkim-genkey -b 2048 -d your-domain.com -D /etc/opendkim/keys/your-domain.com -s default -v
opendkim-genkey: generating private key
opendkim-genkey: private key written to default.private
opendkim-genkey: extracting public key
opendkim-genkey: DNS TXT record written to default.txt

The above command will create 2048 bits keys. -d (domain) specifies the domain. -D (directory) specifies the directory where the keys will be stored and we use default as the selector (-s), also known as the name. Once the command is executed, the private key will be written to default.private file and the public key will be written to default.txt file.

Ensure opendkim is the owner of the private key.

sudo chown opendkim:opendkim /etc/opendkim/keys/your-domain.com/default.private

Also change the permission, so only the opendkim user has read and write access to the file.

sudo chmod 600 /etc/opendkim/keys/your-domain.com/default.private

Publish Your Public Key in DNS Records

Display the public key

sudo cat /etc/opendkim/keys/your-domain.com/default.txt
default._domainkey  IN  TXT ( "v=DKIM1; k=rsa; "
      "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAutisB7xnL1B1j88Er2VsEd6WuwifqSThKEcrnlkhnsVhs/UkCd2lHL+dZwivjbfH+4RXIP0LK9shGokPwaA2MHNH3GgAuWZ/Wb6ZrZwqDlmHy+H6Q0/cLsB2Py2HFthq1JUhHW31ZOIqa4qOn2suBntQdizGExHsuMMb1nJpu0lgFJLU848qPQO76QMTcC/TyssiCjLXXSQEsS"
      "Kx0UmeODJ43NKAAS0OqkGBD2UE7/SW54bVpESK32lTIfzk91OdW+zDMzX6myToJtEE9WgOkgD2evSTp02dhKBBRkQvGJ0SF7el34e/smeS+XvodjjOvP2f3qW5cLvrCRByIkFzRwIDAQAB" )  ; ----- DKIM key default for your-domain.com

The string after the p parameter is the public key, it spans two lines in the cat output because the limit per line is 256 characters. It really should be one big long string with no quotes.

In your DNS manager, * create a TXT record, * enter default._domainkey in the name field. * Copy everything between the parentheses and paste it into the value field of the DNS record. Delete all double quotes and white spaces in the value field. Join all the lines into one line.

For Example; look at a recent google e-mail:

X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20210112; t=1677769129;
        h=to:list-unsubscribe:user-agent:mime-version:subject:message-id:from
         :date:dkim-signature:dkim-signature:delivered-to:x-gm-message-state
         :from:to:cc:subject:date:message-id:reply-to;
        bh=V22zSr/CKU90o7uszazuWVoXgsouLolWaiMhbqvqG8Y=;
        b=FUH9YP2CWhupcc6eU3hVYigxSWJ2fVJHF1F3DrkJoMb1K3hf9O7vrTWDxqNIOvGmPS
         6sCsgvynVtQ+cccVgzc6vZLBYDg3XBdQF6u2hxiMIAAkyPGVUUrYpj/OreMj1WkGDkG0
         9yVxpp0UuIK8uyrfswX9zBWT/QORjQ4Lfh3KCbzaLX8DbfWoc3P907Ebc8cfvVGDu2wX
         oNBeYjEXb4sywHcVmuUNdg//O78sAY5CnSVZ3Gc/41/pFtNHdCCjQAWSQ/W/Czfsy2TY
         Ovuebwb71h3VlUpqDIqkaIMZ5rF9pWxqeQgHkIs8Ktgd8CnAhqnk77ZXWk0SR9Q8hkuQ
         +BQw==

The s and d tags are used to look up the DKIM record. s is the selector while d is the domain.

s=20210112 d=1e100.net

Together they form the DNS lookup string: 20210112._domainkey.1e100.net

$ dig +short txt 20210112._domainkey.1e100.net
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8Sabq+yC2d91PkWTEkjdH2AsaH31YzVJ8PKlQy2GZ9u8vtqfQM88nACYwWAbCQvLwUfCz7hbF/PyM3K/SPlDSk0HqKq89AQjv60br0pK90vWFmzt04ioNcf4QoiJjnnTWD6h5gOM" "ATz4WfdwCrQ9MRF0SjDHteEVeHCK4WKsWKdPshaSLiVfZxiGLv4SZkWye7Zh5iM66MUvYAr3x151AyCQroTNfJY9RN9RK2ZqLdcoulg7S/XMbnzY7EW0P8nPj2jqvMp0bcr13tOzBRnysYiQIu3cjrtyLNfAZobK6tlmy737vkVH27D0rsUrcABrFqvVox61h61JssaRYcwRpwIDAQAB"

Your key lookup should look like:

$ dig +short txt default._domainkey.your-domain.com
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAutisB7xnL1B1j88Er2VsEd6WuwifqSThKEcrnlkhnsVhs/UkCd2lHL+dZwivjbfH+4RXIP0LK9shGokPwaA2MHNH3GgAuWZ/Wb6ZrZwqDlmHy+H6Q0/cLsB2Py2HFthq1JUhHW31ZOIqa4qOn2suBntQdizGExHsuMMb1nJpu0lgFJLU848qPQO76QMTcC/TyssiCjLXXSQEsS" "Kx0UmeODJ43NKAAS0OqkGBD2UE7/SW54bVpESK32lTIfzk91OdW+zDMzX6myToJtEE9WgOkgD2evSTp02dhKBBRkQvGJ0SF7el34e/smeS+XvodjjOvP2f3qW5cLvrCRByIkFzRwIDAQAB"

Reference: https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/

Test DKIM Key

Test your key.

sudo opendkim-testkey -d your-domain.com -s default -vvv

You should see Key OK in the output.

opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key 'default._domainkey.your-domain.com'
opendkim-testkey: key secure
opendkim-testkey: key OK

Your DKIM record will take some time to propagate to the Internet.

To check, go to https://www.dmarcanalyzer.com/dkim/dkim-check/, use default as the selector your domain name to check DKIM record propagation.

Connect Postfix to OpenDKIM

Postfix can talk to OpenDKIM via a Unix socket file. It is a good idea to put it where all the other postfix socket files are.

Create the directory OpenDKIM for a socket file and limit is to the opendkim user and postfix group.

$sudo mkdir                  /var/spool/postfix/opendkim
$sudo chown opendkim:postfix /var/spool/postfix/opendkim

Set Socket to local

File: /etc/opendkim.conf

Socket    local:/var/spool/postfix/opendkim/opendkim.sock

Change the default file as well (if it exists):

Add openDKIM to Postfix main.cf

milter is a modifier filter

File: /etc/postfix/main.cf

# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

Restart opendkim and postfix service

$ sudo systemctl restart opendkim postfix

SPF and DKIM Check

Send a test email to another domain's account, and see if SPF and DKIM checks are passed in the message source.

Example:

Authentication-Results: dkim-verifier.icloud.com;
    dkim=pass (2048-bit key) header.d=your-domain.com header.i=@your-domain.com header.b=yn+tGP2N
Authentication-Results: spf.icloud.com; spf=pass (spf.icloud.com: domain of you@your-domain.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=you@your-domain.com

Your email server will also perform SPF and DKIM checks on other domains.

Example:

Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=1234:f8b0:5678:90::372; helo=mail-yw1-xc2d.google.com; envelope-from=someone@gmail.com; receiver=<UNKNOWN> 
Authentication-Results: you.your-domain.com;
    dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IsoKGudn";
    dkim-atps=neutral

Postfix Can’t Connect to OpenDKIM

Check the logs

$ vi /var/log/mail*
$ sudo journalctl -eu opendkim

If you see this:

connect to Milter service local:opendkim/opendkim.sock: No such file or directory

check the opendkim systemd service.

$ sudo systemctl status opendkim

If opendkim is running, it means Postfix can’t connect to OpenDKIM via the Unix domain socket (local:opendkim/opendkim.sock).

Check the socket file:

$ ls -l /var/spool/postfix/opendkim/opendkim.sock 
srwxrwxr-x 1 opendkim opendkim 0 Mar  2 15:09 /var/spool/postfix/opendkim/opendkim.sock

And postfix user:

$ id postfix
uid=89(postfix) gid=89(postfix) groups=89(postfix),12(mail),988(opendkim)

Be sure the postfix user has group opendkim.

If all else fails, you can configure OpenDKIM to use a TCP/IP socket instead of Unix local socket.

File: /etc/opendkim.conf

Socket     inet:8892@localhost

File: /etc/postfix/main.cf

smtpd_milters = inet:127.0.0.1:8892

Restart OpenDKIM and Postfix.

sudo systemctl restart opendkim postfix

Now Postfix will connect to OpenDKIM via the TCP/IP socket.

Configuration Error in Email Client

DKIM signing could fail if you do not use STARTTLS or SSL/TLS.

Type Port Encryption Password
SMTP 587 STARTTLS Normal
IMAP 143 STARTTLS Normal
SMTP 465 SSL/TLS Normal
IMAP 993 SSL/TLS Normal

Wrong Settings

Port 25 as the SMTP port in mail clients to submit outgoing emails. No encryption method was selected.

Testing Email Score and Placement

Visit Mail-Tester https://www.mail-tester.com and send an E-Mail to the unique email address displayed on the home page. They will analyze it and return a sender score.

GlockApps https://glockapps.com/ will show you where your emails are being delivered at Gmail, Outlook, & all major ISPs.

What is DMARC?

DMARC stands for Domain-based message authentication, reporting and conformance. DMARC is a protcol for protecting your Internet Domain from abuse.

It extends SPF and DKIM using another DNS entry.

Originators of Internet Mail need to be able to associate reliable and authenticated domain identifiers with messages, communicate policies about messages that use those identifiers, and report about mail using those identifiers. These abilities have several benefits: Receivers can provide feedback to Domain Owners about the use of their domains; this feedback can provide valuable insight about the management of internal operations and the presence of external domain name abuse.

Reference: https://datatracker.ietf.org/doc/html/rfc7489

Create DMARC Record

DMARC policies are published as a TXT record in DNS.

If the 3 domains are identical, then they are aligned.

If Return-Path: or DKIM d= uses a subdomain instead of the main domain name, then this is called relaxed alignment. If no subdomain is used and the main domain names are the same, it’s called strict alignment.

DMARC Record TXT

Domain Owner DMARC preferences are stored as DNS TXT records in subdomains named "_dmarc". For example, the Domain Owner of "example.com" would post DMARC preferences in a TXT record at "_dmarc.example.com".

In your Domain Registration DNS manager add a new TXT record.

Name field:

_dmarc

Value field:

v=DMARC1; p=none; pct=100; rua=mailto:dmarc-reports@your-domain.com

Definition:

There are 3 policies you can choose from:

Another option to consider is:

Try fo=1 at first for detailed DMARC failure reports. When you change to a more restrictive policy, use fo=0.

v=DMARC1; p=none; pct=100; fo=1; ruf=mailto:dmarc-reports@your-domain.com

If you have a domain name that will not send emails, use p=reject policy.

v=DMARC1; p=reject; pct=100;

DMARC Record Check

You can check your DMARC record from Linux terminal with the following command:

$ dig txt +short _dmarc.example.com
"v=DMARC1; p=none; pct=100; rua=mailto:postmaster@your-domain.com"

You can also install opendmarc-check that to check a DMARC record.

Install opendmarc package

sudo apt install opendmarc

It checks DNS and translates the DMARC record to a human readable form.

$ opendmarc-check your-domain.com
DMARC record for your-domain.com:
    Sample percentage: 100
    DKIM alignment: relaxed
    SPF alignment: relaxed
    Domain policy: none
    Subdomain policy: unspecified
    Aggregate report URIs:
        mailto:postmaster@your-domain.com
    Failure report URIs:
        (none)

DMARC Test E-Mail

Send an email from your domain to another domain's account. If DMARC is configured correctly then you will see dmarc=pass in the Authentication-Results: header.

Authentication-Results: dmarc.icloud.com; dmarc=pass header.from=your-domain.com
X-DMARC-Info: pass=pass; dmarc-policy=none; s=r1; d=r1; pdomain=your-domain.com
X-DMARC-Policy: v=DMARC1; p=none; pct=100; rua=mailto:postmaster@your-domain.com
Authentication-Results: dkim-verifier.icloud.com;
    dkim=pass (2048-bit key) header.d=your-domain.com header.i=@your-domain.com header.b=wVFZ+19t
Authentication-Results: spf.icloud.com; spf=pass (spf.icloud.com: domain of you@your-domain.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=you@your-domain.com
Received-SPF: pass (spf.icloud.com: domain of you@your-domain.com designates 1.2.3.4 as permitted sender) receiver=spf.icloud.com; client-ip=1.2.3.4; helo=mail.your-domain.org; envelope-from=you@your-domain.com

Interpret a DMARC Report

There are two kinds of DMARC reports.

Normally you only want to receive the aggregate (rua) report. The data that DMARC produces is invaluable for understanding what is going on for any given email domain. However, raw DMARC report data is super hard to read and understand.

Postmark offers a free service to process these reports. The nice part about Postmark is that you can tell receiving email servers to send XML reports directly to Postmark for processing. So instead of entering your email address in the DMARC record, you enter an email address of postmarkapp.com that is unique to you.

v=DMARC1; p=none; pct=100; fo=1; rua=mailto:unique-to-you@dmarc.postmarkapp.com;

You can also specify multiple email addresses, separated by commas.

v=DMARC1; p=none; pct=100; fo=1; rua=mailto:unique-to-you@dmarc.postmarkapp.com,mailto:dmarc-report@your-domain.com;

After your DMARC record has been verified by Postmark, you will receive a DMARC report weekly every Monday in your email inbox. You don’t need to register an account at Postmark.

Many other firms exist to create DMARC reports. If you are into a lot of E-Mail marketing, you should check some more out.

  1. https://datatracker.ietf.org/doc/html/rfc7489#appendix-C

Reference:

links

social