MX - Mail Exchange Servers

Postfix Logo

Postfix is a free and open-source mail transfer agent (MTA) that routes and delivers electronic mail on a Linux system. It is estimated that around 26% of public mail servers on the internet run Postfix.

Prerequisites

Install Software

$ sudo apt-get install postfix postfix-mysql

On Ubuntu server 20.04 (focal) the installed version is Postfix version 3.4.13, released on June 14, 2020.

Main Configuration

Postfix uses a number of different configuration files, with the /etc/postfix/main.cf being the most important.

The documentation website has a page dedicated to main.cf which includes every possible configuration paramter.

The whole file, as presented below, is also provided for download at /server/config-files/etc/postfix/main-mx.cf here.

General Mail Server Setttings

15# General Mail Server Setttings
16# ------------------------------------------------------------
17
18# Disable backwards-compatibility safety net
19compatibility_level = 2
20
21# What is my domainname?
22mydomain = example.net
23
24# What is my hostname (FQDN)?
25myhostname = maeve.${mydomain}
26
27# What characters in a recipient address separate users from extensions?
28recipient_delimiter = +-
29
30# Should I refuse mails with non-standard FROM or RCPT address formats?
31strict_rfc821_envelopes = yes
32
33# What domains do I receive mail for?
34mydestination =
35
36# What trouble do I need to report to a human (postmaster)?
37notify_classes = bounce, 2bounce, data, delay, resource, software
38
39# After how long should I notify if mail-delivery is delayed?
40delay_warning_time = 6h
41confirm_delay_cleared = yes
42
43# Do I need to notify local users of new mail?
44biff = no
45
46# What is the maximum message size (in bytes)?
47# 25 Mebibytes = 26,214,400 Bytes
48message_size_limit = 26214400
49
50# Whats the size limit of mailboxes?
51mailbox_size_limit = 0
52
53
54# ------------------------------------------------------------

Trusted Networks Maps

55# Trusted (allowed to relay) Networks Maps
56# ------------------------------------------------------------
57
58# Which clients do I trust and will relay mail to other domains?
59mynetworks = cidr:${config_directory}/mynetworks.cidr
60
61
62# ------------------------------------------------------------

Local & Virtual Domains and Aliases Maps

63# Local & Virtual (Relay) Domains and Aliases Maps
64# ------------------------------------------------------------
65
66local_recipient_maps =
67
68# Where do I forward local system messages?
69alias_maps = $alias_database
70
71# How do I lookup alias of local mail addresses?
72virtual_alias_maps = hash:${config_directory}/virtual
73
74# How can I lookup virtual mail-domains to relay?
75relay_domains = mysql:${config_directory}/sql/relay_domains_maps.cf
76
77# How do I lookup individual mailbox addresses of virtual mail-domains to relay?
78relay_recipient_maps = mysql:${config_directory}/sql/relay_mailbox_maps.cf
79                       mysql:${config_directory}/sql/relay_alias_maps.cf
80
81
82# ------------------------------------------------------------

Relayed and Outgoing Mail Transport Maps

83# Relayed and Outgoing Mail Transport Maps
84# ------------------------------------------------------------
85
86local_transport = error:local mail delivery is disabled
87
88# How do I relay mail for allowed (virtual) domains?
89transport_maps = mysql:${config_directory}/sql/relay_transport_maps.cf
90
91
92# ------------------------------------------------------------

TCP/IP Protocols Settings

 93# TCP/IP Protocols Settings
 94#
 95# Changes made here need a full server restart:
 96#     'sudo systemctl restart postfix.service'
 97# ------------------------------------------------------------
 98
 99# On which interfaces / IP addresses do I listen for inbound connections?
100inet_interfaces =
101
102    # Localhost
103    127.0.0.1, [::1],
104
105    # maeve.example.net
106    198.51.100.7,
107    2001:db8:48d1::1,
108
109    # maeve.vpn.example.net
110    10.195.171.142,
111    fdc1:d89e:b128:6a04::7de4
112
113# Digital Ocean blocks SMTP traffic over IPv6 at their network level.
114#smtp_address_preference = ipv4
115
116
117# ------------------------------------------------------------

General TLS Settings

118# General TLS Settings
119#
120# Ciphers suites to use in different situations.
121# Note: While using non-mandatory opportunistic encryption,
122# its preferable to use bad encryption, then no encrpytion
123# at all.
124# ------------------------------------------------------------
125
126# Generated 2020-12-13, Mozilla Guideline v5.6,
127# Postfix 3.4.13, OpenSSL 1.1.1f, old configuration
128# https://ssl-config.mozilla.org/
129tls_low_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA
130
131# What ciphers suites do I use for mandatory ecnryption?
132# Generated 2020-12-13, Mozilla Guideline v5.6,
133# Postfix 3.4.13, OpenSSL 1.1.1f, intermediate configuration
134tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
135
136# What ciphers suites do I use when I am high?
137# The Postfix built-in defaults are okay here.
138#tls_high_cipherlist = aNULL:-aNULL:HIGH:@STRENGTH
139
140# Let the server select the used cipher, to possibly avoid the bad ones, which
141# we support but would like to avoid.
142tls_preempt_cipherlist = yes
143
144# What OpenSSL options do I enable?
145tls_ssl_options = NO_COMPRESSION
146                  NO_RENEGOTIATION
147                  NO_SESSION_RESUMPTION_ON_RENEGOTIATION
148
149
150# ---------------------------------------------------------

SMTP TLS Client Settings

151# SMTP TLS Client Settings
152# ---------------------------------------------------------
153
154# What DNS lookup methods do I use for outgoing SMTP sessions?
155smtp_dns_support_level = dnssec
156
157# Which default TLS policy applies when connecting to other SMTP servers?
158smtp_tls_security_level = dane
159
160# Which default TLS policy applies when the hostname of a domain was received by
161# insecure DNS MX query?
162smtp_tls_dane_insecure_mx_policy = dane
163
164# Where do I lookup domain specific TLS policies when sending mail?
165smtp_tls_policy_maps =
166    mysql:${config_directory}/sql/tls-policy.cf
167    socketmap:inet:127.0.0.1:8461:postfix
168
169# Which TLS protocols do I use for opportunistic TLS policies?
170# ("may", "dane")?
171smtp_tls_protocols = !SSLv2, !SSLv3
172
173# Which cipher list do I use for opportunistic TLS policies?
174# ("may", "dane")
175smtp_tls_ciphers = medium
176
177# Which ciphers I have to exclude for opportunistic TLS policies?
178# ("may", "dane")
179smtp_tls_exclude_ciphers = aNULL, eNULL, EXPORT, RC4, DES, SSLv2, MD5
180
181# Which TLS protocols do I use for mandatory TLS policies?
182# ("encrypt", "dane-only", "verify", "secure")
183smtp_tls_mandatory_protocols = $smtp_tls_protocols, !TLSv1, !TLSv1.1
184
185# Which cipher list do I use for mandatory TLS policies?
186# ("encrypt", "dane-only", "verify", "secure")
187smtp_tls_mandatory_ciphers = medium
188
189# Which ciphers I have to exclude for mandatory TLS policies?
190# ("encrypt", "dane-only", "verify", "secure")
191smtp_tls_mandatory_exclude_ciphers = ${smtp_tls_exclude_ciphers}, SHA1
192
193# Where are CA files stored to verify TLS certificates?
194smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
195
196# Where do I find trusted CA certificates to verify SMTP server certificates?
197smtp_tls_CApath = /etc/ssl/certs
198
199# Files containing TLS private keys, certificates and issueing intermediate CA
200smtp_tls_chain_files =
201     /etc/letsencrypt/live/${myhostname}-ecdsa/keycertchain.pem
202     /etc/letsencrypt/live/${myhostname}-rsa/keycertchain.pem
203
204# Where do I cache outgoing SMTP TLS sessions?
205smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
206
207# Should I make a note if I encounter servers who offer encryption?
208smtp_tls_note_starttls_offer = yes
209
210# How much of the outgoing TLS transactions should I log?
211smtp_tls_loglevel = 1
212
213
214# ---------------------------------------------------------

SMTPD TLS Server Settings

215# SMTPD TLS Server Settings
216# ---------------------------------------------------------
217
218# Is TLS encryption required for incoming connections?
219smtpd_tls_security_level = may
220
221# Do I refuse password authentication over unencrypted connections?
222smtpd_tls_auth_only = yes
223
224# Which TLS protocols do I accept for opportunistic TLS policies?
225# ("may")
226smtpd_tls_protocols = $smtp_tls_protocols
227
228# Which cipher list do I accept for opportunistic TLS policies?
229# ("may")
230smtpd_tls_ciphers = $smtp_tls_ciphers
231
232# Which ciphers I don't accept for opportunistic TLS policies?
233# ("may")
234smtpd_tls_exclude_ciphers = $smtp_tls_exclude_ciphers
235
236# Which TLS protocols do I use for mandatory TLS policies?
237# ("encrypt")
238smtpd_tls_mandatory_protocols = $smtp_tls_mandatory_protocols
239
240# Which cipher list do I accept for mandatory TLS policies?
241# ("encrypt")
242smtpd_tls_mandatory_ciphers = $smtp_tls_mandatory_ciphers
243
244# Which ciphers I don't accept for mandatory TLS policies?
245# ("encrypt")
246smtpd_tls_mandatory_exclude_ciphers = $smtp_tls_mandatory_exclude_ciphers
247
248# What security grade do I use for ephemeral elliptic-curve Diffie-Hellman
249# (EECDH) key exchange?
250smtpd_tls_eecdh_grade = ultra
251
252# Where are CA files stored to verify TLS certificates?
253smtpd_tls_CAfile = $smtp_tls_CAfile
254
255# Where do I find trusted CA certificates to verify SMTP server certificates?
256smtpd_tls_CApath = $smtp_tls_CApath
257
258# Where do I get Diffie-Hellmann key-exchange (DHE) parameters from?
259# (for perfect forward secrecy)
260# https://github.com/internetstandards/dhe_groups
261# not actually 1024 bits, this applies to all DHE >= 1024 bits
262smtpd_tls_dh1024_param_file = /etc/ssl/dhe_groups/ffdhe4096.pem
263
264# Files containing TLS private keys, certificates and issueing intermediate CA
265smtpd_tls_chain_files = ${smtp_tls_chain_files}
266
267# Where do I cache incoming SMTP TLS sessions?
268smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
269
270# How long do I cache incoming TLS sessions?
271smtpd_tls_session_cache_timeout = 24h
272
273# Should I ask connecting clients for their own certificate?
274smtpd_tls_ask_ccert = yes
275
276# Should I include protocol and cipher used in the "Received:" message headers?
277smtpd_tls_received_header = yes
278
279# How much of the incoming TLS transactions should I log?
280smtpd_tls_loglevel = 1
281
282
283# ------------------------------------------------------------

SMTPD Server Relay Restrictions

284# SMTPD Server Relay Restrictions
285# ------------------------------------------------------------
286
287# What message digest algorithm do I use to verify relay client certificates?
288smtpd_tls_fingerprint_digest = sha256
289
290# Where do I lookup public-key fingerprints of allowed relay client certificates?
291relay_clientcerts = hash:${config_directory}/relay_clientcerts
292
293# What restrictions apply to relayed mails?
294smtpd_relay_restrictions =
295    permit_mynetworks
296    reject_unauth_destination
297
298
299# ------------------------------------------------------------

SMTPD Server Restrictions

300# SMTPD Server Restrictions
301# ------------------------------------------------------------
302
303# What restrictins apply to connecting clients?
304smtp_client_restrictions =
305    permit_mynetworks
306    check_client_access hash:${meta_directory}/without_ptr
307    reject_unknown_client_hostname
308
309# Are connecting clients required to greet me properly before anything else?
310smtpd_helo_required = yes
311
312# What restrictins apply to SMTP HELO greetings
313smtpd_helo_restrictions =
314    permit_mynetworks
315    reject_invalid_helo_hostname
316    reject_non_fqdn_helo_hostname
317    reject_unknown_helo_hostname
318
319# What restrictins apply to any mail sender address?
320smtp_sender_restrictions =
321    permit_mynetworks
322    reject_unlisted_sender
323
324# What restrictins apply to any mail recipient address?
325smtpd_recipient_restrictions =
326    reject_non_fqdn_recipient
327    reject_unknown_recipient_domain
328
329# What restrictins apply to mail content?
330smtpd_data_restrictions = reject_unauth_pipelining
331
332
333# ---------------------------------------------------------

Spam Filter (Milter) and DKIM Mail Message Signing

334# Spam Filter (Milter) and DKIM Mail Message Signing
335# ---------------------------------------------------------
336
337# Milter (mail filter) application(s) for new mail arriving via SMTP.
338# Note: UNIX Socket files are relative to '/var/spool/postfix'
339smtpd_milters =
340    #inet:localhost:11332
341    unix:/rspamd/rspamd_proxy.sock
342
343# Milter (mail filter) application(s) for new mail injected locally.
344# Note: UNIX Socket files are relative to '/var/spool/postfix'
345non_smtpd_milters =
346    #inet:localhost:11332
347    unix:/rspamd/rspamd_proxy.sock
348
349milter_mail_macros =  i {mail_addr} {client_addr} {client_name} {auth_authen}
350
351# Default action when a Milter (mail filter) application is unavailable.
352milter_default_action = tempfail
353
354
355# ------------------------------------------------------------
356# SOFT BOUNCE - Set to while debugging delivery issues
357# ------------------------------------------------------------
358#
359# The soft_bounce parameter provides a limited safety net for
360# testing.  When soft_bounce is enabled, mail will remain queued that
361# would otherwise bounce. This parameter disables locally-generated
362# bounces, and prevents the SMTP server from rejecting mail permanently
363# (by changing 5xx replies into 4xx replies). However, soft_bounce
364# is no cure for address rewriting mistakes or mail routing mistakes.
365#
366#soft_bounce = no
367
368# -*- mode: ini; tab-width: 4; indent-tabs-mode:nil  -*-

Systemd Service Dependencies

Our Postfix MX depends on various other services, we want to ensure that Postfix is always able to connect to them while running:

  • Wireguard VPN network interface

  • MariaDB database server

  • Rspamd Spam Filter

  • ClamAV virus scanner

  • Postfix MTA-STS resolver

The Systemd services file for the Postfix server /lib/systemd/system/postfix@.service is created as part of the software package installation. The recommended method is to create a Systemd override-file and not change anything in the provided service file, as it would be lost on software package updates.

You can create a override file easily with the help of the systemctl command:

$ sudo systemctl edit postfix@.service

This will start your editor with an empty file, where you can add your own custom Systemd service configuration options.

[Unit]
After=sys-devices-virtual-net-wg0.device
After=mariadb.service rspamd.service clamav-daemon.service postfix-mta-sts-resolver.service
BindsTo=sys-devices-virtual-net-wg0.device mariadb.service

The configuration statement After=mariadb.service ensures that mariadb.service is fully started up before the postfix@.service is started.

The line BindsTo=mariadb.service ensures that if the Database service is stopped, the PowerDNS server will be stopped too.

After you save and exit of the editor, the file will be saved as /etc/systemd/system/postfix@.service.d/override.conf and Systemd will reload its configuration:

systemctl show postfix@.service |grep -E "After=|BindsTo="