summaryrefslogtreecommitdiff
path: root/articles/mail-server.html
diff options
context:
space:
mode:
Diffstat (limited to 'articles/mail-server.html')
-rw-r--r--articles/mail-server.html723
1 files changed, 723 insertions, 0 deletions
diff --git a/articles/mail-server.html b/articles/mail-server.html
new file mode 100644
index 0000000..12a3264
--- /dev/null
+++ b/articles/mail-server.html
@@ -0,0 +1,723 @@
1<!DOCTYPE html>
2<html lang=en>
3<head>
4<title></title>
5<meta charset="utf-8"/>
6<link rel="shortcut icon" href="favicon.ico"/>
7<link rel='stylesheet' href='../style.css'/>
8<meta name="viewport" content="width=device-width, initial-scale=1">
9</head>
10<body>
11<header><h1>Postfix and Dovecot Mail Server</h1></header>
12<main>
13
14<p>Postfix and dovecot will be the two primary pieces of our mail sever.
15Postfix is the mail transport agent that handles the sending and
16receiving of mail and dovecot is the IMAP server that will allow us to
17access our mail from a mail client such as mutt. The server will also
18have several other supporting components, a complete list of which is:</p>
19
20<ul>
21 <li><em>SpamAssassin</em> for spam filtering</li>
22 <li><em>OpenDKIM</em> for DKIM verification and signing</li>
23 <li><em>Postgrey</em> for greylisting</li>
24 <li><em>Policyd-SPF</em> for SPF verification</li>
25 <li><em>OpenDMARC</em> for DMARC verification</li>
26</ul>
27
28<p>You can use <a href=https://git.chudnick.com/mail-tools/tree/server/deploy-server>
29this script</a> I have written to automate this process, but I would
30recommend that you run through the tutorial first to understand
31what is being done.</p>
32
33<p>Please note that this tutorial is loosely intended for small personal mail
34servers. Using PAM for authentication, as is done here, is not a scalable solution
35for working with a large number of users. I do plan on covering Dovecot LDAP
36authentication at some point which would be a better solution in an enterprise
37setting.</p>
38
39<h2>Install Packages</h2>
40<p>Let's start by installing the required packages. Note that if you already
41have Apache installed on the server, replace <em>python3-certbot-nginx</em>
42with <em>python3-certbot-apache</em>.</p>
43<pre><code>apt install postfix dovecot-imapd dovecot-sieve opendkim opendkim-tools spamassassin gnupg postgrey postfix-policyd-spf-python opendmarc dbconfig-no-thanks certbot python3-certbot-nginx</code></pre>
44<p>During the installation of Postfix you will get a Debconf prompt in which
45you need to select "Internet Site" and then provide your domain name,
46<strong>example.com</strong>.</p>
47
48<h2>Get a certificate</h2>
49<p>Now we'll use Certbot to get a certificate for our server. If you are
50using Apache replace <em>nginx</em> with <em>apache2</em>.</p>
51
52<pre><code>systemctl stop nginx
53certbot certonly --standalone -d <strong>mail.example.com</strong>
54systemctl start nginx</code></pre>
55
56<h2>Postfix Main Configuration</h2>
57<p>In this section we will be doing the bulk of the postfix configuration.
58The postconf command used throughout appends (or changes)
59the specified configuration item in /etc/postfix/main.cf</p>
60
61<h3>Network Configuration</h3>
62
63<p>Let's start by configuring some network and domain information.</p>
64
65<pre><code>postconf -e "myorigin = <strong>example.com</strong>"
66postconf -e "mydestination = \$myhostname, \$mydomain, localhost"
67postconf -e "mynetworks = 127.0.0.0/8 [::1]/128"
68postconf -e "myhostname = <strong>mail.example.com</strong>"
69</code></pre>
70
71<p>Next, point postfix to the cerbot key and certificate, as well as the distro's
72CA certificates.</p>
73
74<pre><code>postconf -e "smtpd_tls_key_file=/etc/letsencrypt/live/<strong>mail.example.com</strong>/privkey.pem"
75postconf -e "smtpd_tls_cert_file=/etc/letsencrypt/live/<strong>mail.example.com</strong>/fullchain.pem"
76postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
77</code></pre>
78
79<p>Harden the TLS configuration by forcing strong
80protocols and ciphers, and requiring that authentication occur only over an
81encrypted session.</p>
82<pre><code><em># Require authentication over TLS and optionally use it for sending and receiving mail</em>
83postconf -e "smtpd_tls_auth_only = yes"
84postconf -e "smtpd_tls_security_level = may"
85postconf -e "smtp_tls_security_level = may"
86
87<em># Force the use of TLSv1.2 or TLSv1.3</em>
88postconf -e 'smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
89postconf -e 'smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
90postconf -e 'smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
91postconf -e 'smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
92
93<em># Prefer server ciphers</em>
94postconf -e "tls_preempt_cipherlist = yes"
95
96<em># Force strong ciphers</em>
97postconf -e "smtpd_tls_ciphers = high"
98postconf -e "smtpd_tls_mandatory_ciphers = high"
99postconf -e "smtp_tls_ciphers = high"
100postconf -e "smtp_tls_mandatory_ciphers = high"
101postconf -e "smtpd_tls_exclude_ciphers = aNULL, eNULL, EXP, LOW, MEDIUM, PSK, SRP, SHA1, kRSA, CAMELLIA, ARIA, DSS, RSA+AES, ADH, AECDH"
102postconf -e "smtp_tls_exclude_ciphers = aNULL, eNULL, EXP, LOW, MEDIUM, PSK, SRP, SHA1, kRSA, CAMELLIA, ARIA, DSS, RSA+AES, ADH, AECDH"
103</code></pre>
104
105<h3>Local Recipients and Aliases</h3>
106
107<p>Here we configure the bulk of the postfix built-in security settings which are
108structured as a series of access restrictions. Do not edit these settings without
109first reading the Postfix documentation as an incorrect change could inadvertently
110make your server an open relay.</p>
111
112<pre><code>postconf -e "smtpd_helo_required = yes"
113postconf -e "smtpd_sender_login_maps = proxy:hash:/etc/postfix/login_maps"
114postconf -e "smtpd_helo_restrictions = reject_unknown_helo_hostname, reject_non_fqdn_helo_hostname"
115postconf -e "smtpd_sender_restrictions = reject_sender_login_mismatch, reject_non_fqdn_sender, reject_unknown_sender_domain"
116postconf -e "smtpd_recipient_restrictions = reject_non_fqdn_recipient, reject_unknown_recipient_domain, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/postgrey, check_policy_service unix:private/policyd-spf, reject_rbl_client zen.spamhaus.org"
117postconf -e "smtpd_relay_restrictions = permit_sasl_authenticated, reject_unauth_destination"
118postconf -e "smtpd_data_restrictions = reject_unauth_pipelining"
119
120<em># Disable VRFY command to prevent harvesting of user accounts on system</em>
121postconf -e "disable_vrfy_command = yes"
122
123<em># Change smptd banner (hide distribution)</em>
124postconf -e "smtpd_banner = \$myhostname ESMTP \$mail_name"</code></pre>
125
126<p>Now, configure the local mail recipients and some aliases. We'll create
127an account called <strong>mailadmin</strong> to receive mail addressed to
128several other accounts. This is to keep <em>administrative</em> mail separate, but
129you can certainly alias these to your main account later if you would prefer to see
130it there.</p>
131
132<pre><code><em># Set a custom local_recipient_maps here in order to avoid accepting mail for all local accounts</em>
133postconf -e "local_recipient_maps = proxy:hash:/etc/postfix/local_maps \$alias_maps"
134
135<em># You will need to manually set a password later to login as mailadmin</em>
136adduser --disabled-login --shell /usr/sbin/nologin --gecos "" mailadmin
137echo "# postfix aliases
138postmaster: mailadmin
139root: mailadmin
140dmarc: mailadmin
141" &gt; /etc/aliases
142
143<em># Update address databases</em>
144echo "mailadmin@<em>mail.example.com</em> mailadmin" &gt; /etc/postfix/login_maps
145echo "mailadmin mailadmin" &gt; /etc/postfix/local_maps
146newaliases
147postmap /etc/postfix/login_maps
148postmap /etc/postfix/local_maps
149</code></pre>
150
151<h3>Mail Delivery</h3>
152
153
154<p>These commands configure our mail delivery preferences. Mail will be
155delivered inside a user's home folder with a maildir-style mailbox using
156dovecot.</p>
157
158<pre><code><em># Maildir delivery to $HOME/Mail/Inbox/</em>
159postconf -e "home_mailbox = Mail/Inbox/"
160<em># Deliver mail with Dovecot</em>
161postconf -e "mailbox_command = /usr/lib/dovecot/deliver"</code></pre>
162
163<h3>Header and Body Checks</h3>
164
165<p>Header and body checks allow for some simple content filtering within Postfix.
166This is done by scanning a message line by line for a configured regex string,
167nothing more. For example, the first header check listed will reject a message
168with an attachment of <em>ransomware.exe</em> but will not block it if sent with
169no extension. This is mostly a protection against uneducated users and poorly
170written mail clients. Other checks block vulnerabilities and improve privacy.</p>
171
172<p>Create a new file <strong>/etc/postfix/header_checks</strong>, then open it in a
173text editor and add the following</p>
174<pre><code><em># Block files with common executable extensions</em>
175/name=[^&gt;]*\.(exe|pif|com|dll|vbs|bat|sh|bash|so|zip|tar|gz|cpio)/ REJECT
176
177<em># Block message/partial vulnerability</em>
178/message\/partial/ REJECT
179
180<em># Remove Received string that is created when spamassassin reinjects message into postfix</em>
181<em># This is to prevent leaking the userid of the spamassassin user</em>
182/^Received:.*userid.*/ IGNORE
183
184<em># Remove User-Agent strings from headers</em>
185/^User-Agent: .*/ IGNORE</code></pre>
186
187<p>Create another new file <strong>/etc/postfix/body_checks</strong>, and add this</p>
188<pre><code><em># Block messages with iframes</em>
189/&lt;iframe/ REJECT" &gt; /etc/postfix/body_checks</code></pre>
190
191<p>And then run these commands to point postfix to the check files.</p>
192<pre><code>postconf -e "header_checks = regexp:/etc/postfix/header_checks"
193postconf -e "body_checks = regexp:/etc/postfix/body_checks"</code></pre>
194
195<h2>Postfix Master Configuration</h2>
196<h3>SMTP client</h3>
197<p>This simple command configures the SMTP client process that is responsible
198for sending your mail to other mail servers.</p>
199
200<pre><code>postconf -M "smtp/unix=smtp unix - - y - - smtp"</code></pre>
201
202<h3>Postscreen and SMTP Recipient</h3>
203<p>Postscreen is a kind of firewall that sits in front of the Postfix SMTPD
204process and receives all incoming traffic. Postscreen will drop connections
205from IPs on a DNS blacklst, or from clients that violate the SMTP protocol by
206speaking out of turn or sending non-SMTP commands. This adds up to less spam
207connections and therefore a much lighter workload for your server.</p>
208
209<pre><code>postconf -M "smtp/inet=smtp inet n - y - 1 postscreen"
210postconf -M "smtpd/pass=smtpd pass - - y - - smtpd"
211postconf -P "smtpd/pass/content_filter=spamassassin"
212postconf -M "tlsproxy/unix=tlsproxy unix - - y - 0 tlsproxy"
213postconf -M "dnsblog/unix=dnsblog unix - - y - 0 dnsblog"
214postconf -e "postscreen_dnsbl_sites = zen.spamhaus.org"
215postconf -e "postscreen_dnsbl_action = enforce"
216postconf -e "postscreen_greet_action = enforce"
217</code></pre>
218
219<h3>Submission over TLS (submissions)</h3>
220<p>Submission over TLS (aka submissions) is the process you will use to submit
221mail to your server from a mail client. These commands configure submissions to
222use a fully-encrypted session, as opposed to STARTTLS, and to only allow access
223to authenticated clients.</p>
224
225<pre><code>postconf -M "submissions/inet=submissions inet n - y - - smtpd"
226postconf -P "submissions/inet/smtpd_tls_wrappermode=yes"
227postconf -P "submissions/inet/smtpd_tls_security_level=encrypt"
228postconf -P "submissions/inet/smtpd_tls_auth_only=yes"
229postconf -P "submissions/inet/smtpd_sasl_auth_enable=yes"
230postconf -P "submissions/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
231postconf -P "submissions/inet/smtpd_helo_restrictions="
232postconf -P "submissions/inet/smtpd_sender_restrictions=reject_sender_login_mismatch"
233postconf -P "submissions/inet/smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject"
234postconf -P "submissions/inet/syslog_name=postfix/submissions"
235postconf -P 'submissions/inet/smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
236postconf -P 'submissions/inet/smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'</code></pre>
237
238<h3>OPTIONAL - submission with mandatory STARTTLS</h3>
239<p>Having configured submission over TLS on port 465 this step is optional.
240STARTTLS is considered by some to be less secure than full-session TLS and
241may be vulnerable to exploitation.</p>
242
243<pre><code>postconf -M "submission/inet=submission inet n - y - - smtpd"
244postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
245postconf -P 'submission/inet/smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
246postconf -P 'submission/inet/smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
247postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
248postconf -P "submission/inet/smtpd_tls_auth_only=yes"
249postconf -P "submission/inet/syslog_name=postfix/submission"
250postconf -P "submission/inet/smtpd_helo_restrictions="
251postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
252postconf -P "submission/inet/smtpd_helo_restrictions="
253postconf -P "submission/inet/smtpd_sender_restrictions=reject_sender_login_mismatch"
254postconf -P "submission/inet/smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject"
255</code></pre>
256
257<h3>SpamAssassin Configuration</h3>
258<p>Finally, this command tells Postfix how to interact with SpamAssassin.</p>
259
260<pre><code>postconf -M "spamassassin/unix=spamassassin unix - n n - - pipe user=debian-spamd argv=/usr/bin/spamc --socket=/var/run/spamd.sock -e /usr/sbin/sendmail -oi -f \${sender} \${recipient}" </code></pre>
261
262<h2>Dovecot Configuration</h2>
263<p>Dovecot configuration is usually split up into many different files under
264<strong>/etc/dovecot/conf.d/</strong> but here will be doing all of the
265configuration in the primary config file
266<strong>/etc/dovecot/dovecot.conf</strong>. Open that file with your editor
267of choice, clear all of its contents, and then replace it with the following.</p>
268
269<pre><code><em># /etc/dovecot/conf.d/10-auth.conf</em>
270disable_plaintext_auth = yes
271auth_username_format = %n
272auth_mechanisms = plain
273userdb {
274 driver = passwd
275}
276passdb {
277 driver = pam
278}
279
280<em># /etc/dovecot/conf.d/10-mail.conf</em>
281mail_location = maildir:~/Mail:INBOX=~/Mail/Inbox:LAYOUT=fs
282namespace inbox {
283 type = private
284 prefix =
285 separator = /
286 inbox = yes
287 subscriptions = yes
288 list = yes
289}
290
291<em># /etc/dovecot/conf.d/10-master.conf</em>
292service imap-login {
293# Run login processes in high-security mode (see: LoginProcess.txt in dovecot docs)
294service_count = 1
295# Disable unencrypted IMAP by setting port for plain IMAP to 0
296 inet_listener imap {
297 port = 0
298 }
299 inet_listener imaps {
300 port = 993
301 ssl = yes
302 }
303}
304
305<em># Allow postfix to use dovecot SASL</em>
306service auth {
307 unix_listener /var/spool/postfix/private/auth {
308 mode = 0660
309 user = postfix
310 group = postfix
311 }
312}
313
314<em># /etc/dovecot/conf.d/10-ssl.conf</em>
315ssl = required
316ssl_key = &lt;/etc/letsencrypt/live/<strong>mail.example.com</strong>/privkey.pem
317ssl_cert = &lt;/etc/letsencrypt/live/<strong>mail.example.com</strong>/fullchain.pem
318ssl_client_ca_dir = /etc/ssl/certs
319ssl_dh = &lt;/usr/share/dovecot/dh.pem
320
321<em># Mozilla intermediate compatibility</em>
322ssl_min_protocol = TLSv1.2
323ssl_cipher_list = ECDHE+ECDSA+AESGCM:ECDHE+aRSA+AESGCM:ECDHE+ECDSA+CHACHA20:ECDHE+aRSA+CHACHA20:DHE+aRSA+AESGCM:!aNULL:!eNULL
324
325ssl_prefer_server_ciphers = yes
326ssl_client_require_valid_cert = yes
327
328
329<em># /etc/dovecot/conf.d/15-lda.conf</em>
330protocol lda {
331 mail_plugins = \$mail_plugins sieve
332}
333
334<em># /etc/dovecot/conf.d/15-mailboxes.conf</em>
335namespace inbox {
336 mailbox Sent {
337 special_use = \Sent
338 auto = subscribe
339 }
340 mailbox Trash {
341 special_use = \Trash
342 auto = create
343 autoexpunge = 30d
344 }
345 mailbox Drafts {
346 special_use = \Drafts
347 auto = subscribe
348 }
349 mailbox Spam {
350 special_use = \Junk
351 auto = create
352 autoexpunge = 30d
353 }
354 mailbox Archive {
355 special_use = \Archive
356 auto = create
357 }
358}
359
360<em># /etc/dovecot/conf.d/20-imap.conf</em>
361imap_capability = +SPECIAL-USE
362
363<em># /etc/dovecot/conf.d/90-sieve.conf</em>
364plugin {
365 sieve = ~/.dovecot.sieve
366 sieve_default = /var/lib/dovecot/sieve/default.sieve
367 sieve_global = /var/lib/dovecot/sieve/
368}</code></pre>
369
370<p>Then create the default sieve filtering script at
371<strong>/var/lib/dovecot/sieve/default.sieve</strong></p>
372<pre><code>require ["fileinto", "mailbox"];
373/*
374* Discard mail that has a spam score greater than or equal to 10
375*/
376if header :contains "X-Spam-Level" "**********" {
377 discard;
378 stop;
379}
380/*
381* Discard messages marked as infected by a virus scanner
382*/
383if header :contains "X-Virus-Scan" "infected" {
384 discard;
385 stop;
386}
387/*
388* If message is marked as spam (and falls below discard threshold) put into spam mailbox
389*/
390if header :contains "X-Spam-Flag" "YES" {
391 fileinto "Spam";
392}</code></pre>
393
394<p>And compile the script</p>
395
396<pre><code>sievec /var/lib/dovecot/sieve/default.sieve</code></pre>
397
398
399<p>Finally, configure PAM authentication for dovecot at
400<strong>/etc/pam.d/dovecot</strong>. Append these changes leaving any include
401statements intact.</p>
402<pre><code>auth required pam_unix.so
403account required pam_unix.so</code></pre>
404
405<h2>OpenDKIM</h2>
406<p>DKIM is a mail-verification method that cryptographically signs mail
407to allow receivers to verify the authenticity of the sender. Our mail server
408will use DKIM to validate signatures on incoming mail and sign outgoing mail. DKIM
409requires a public key to be published via DNS, which will be done near the end of
410the guide.</p>
411
412<p>Start by generating the DKIM key</p>
413
414<pre><code>opendkim-genkey -D /etc/dkimkeys -d <em>example.com</em> -s mail
415chown opendkim: /etc/dkimkeys/*
416chmod 600 /etc/dkimkeys/*
417mv /etc/dkimkeys/mail.private /etc/dkimkeys/mail.pem</code></pre>
418
419<p>Here we make a directory for the opendkim socket inside the postfix chroot and
420make it accessible to the postfix user.</p>
421
422<pre><code>mkdir /var/spool/postfix/opendkim
423chmod 770 /var/spool/postfix/opendkim
424chown opendkim:opendkim /var/spool/postfix/opendkim
425usermod -aG opendkim postfix</code></pre>
426
427<p>Edit the configuration file at <strong>/etc/opendkim.conf</strong>
428to be as follows:</p>
429
430<pre><code>On-BadSignature reject
431On-Security reject
432Syslog yes
433SyslogSuccess yes
434LogResults yes
435Canonicalization simple
436Mode sv
437OversignHeaders From
438Domain <strong>example.com</strong>
439Selector mail
440KeyFile /etc/dkimkeys/mail.pem
441UserID opendkim
442UMask 007
443Socket local:/var/spool/postfix/opendkim/opendkim.sock
444PidFile /run/opendkim/opendkim.pid
445TemporaryDirectory /run/opendkim
446InternalHosts 127.0.0.1
447TrustAnchorFile /usr/share/dns/root.key
448RequireSafeKeys True
449AlwaysAddARHeader True
450</code></pre>
451
452<h2>OpenDMARC</h2>
453<p>DMARC is another mail-verification technology that provides verification of the
454address seen by end-users and either or both of SPF and DKIM.
455
456<p>Like with OpenDKIM, we need to make a directory inside the postfix chroot
457for the socket and assign proper permissions.</p>
458<pre><code>mkdir /var/spool/postfix/opendmarc
459chmod 770 /var/spool/postfix/opendmarc
460chown opendmarc:opendmarc /var/spool/postfix/opendmarc
461usermod -aG opendmarc postfix
462</code></pre>
463
464<p>Now we write the configuration file at <strong>/etc/opendmarc.conf</strong></p>
465
466<pre><code>PidFile /run/opendmarc/opendmarc.pid
467PublicSuffixList /usr/share/publicsuffix/public_suffix_list.dat
468RejectFailures True
469Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
470Syslog True
471SyslogFacility mail
472UMask 002
473UserID opendmarc
474HistoryFile /var/run/opendmarc/opendmarc.hist
475SPFIgnoreResults True
476SPFSelfValidate True
477</code></pre>
478
479<p>Then create the history file and set permissions.</p>
480
481<pre><code>touch /var/run/opendmarc/opendmarc.hist
482chown opendmarc:opendmarc /var/run/opendmarc/opendmarc.hist
483chmod 664 /var/run/opendmarc/opendmarc.hist
484</code></pre>
485
486<p>Now that both OpenDKIM and OpenDMARC are configured we can define them as milters
487in postfix. This will tell postfix to route mail through one or both of these milters
488depending on whether it is incoming or outgoing.</p>
489
490<pre><code>postconf -P "smtpd/pass/smtpd_milters=unix:opendkim/opendkim.sock,unix:opendmarc/opendmarc.sock"
491postconf -P "submissions/inet/smtpd_milters=unix:opendkim/opendkim.sock"
492<em># If you enabled submission on port 587 run this too</em>
493postconf -P "submission/inet/smtpd_milters=unix:opendkim/opendkim.sock"
494</code></pre>
495
496<h2>Postgrey</h2>
497<p>Postgrey implements a spam-filter technique known as greylisting, which
498always rejects mail on the first try and for a period of time afterwards known
499as the greylist period. The idea behind this being that legitimate senders will
500send the mail again later, while spammers, in a rush to send as many messages as
501possible before being blacklisted, will not.</p>
502
503<p>Postgrey ships with an extensive whitelist domains that are known
504to cause issues (mainly large providers that constantly send from different
505addresses). This whitelist file is located at
506<strong>/etc/postgrey/whitelist_clients</strong> and can be appended to include
507any domain you do not wish to be subject to greylisting.</p>
508
509<p>The configuration needed here is minimal, just open
510<strong>/etc/default/postgrey</strong> and make these changes</p>
511
512<pre><code>POSTGREY_OPTS="--unix=/var/spool/postfix/private/postgrey --privacy"
513POSTGREY_TEXT="Greylisted - see https://www.greylisting.org"</code></pre>
514
515<p>And then enable the service</p>
516
517<pre><code>systemctl enable --now postgrey</code></pre>
518
519<h2>Policyd-SPF</h2>
520<p>SPF is yet another mail-verification technology that uses DNS records to
521delegate specific servers as being authorized to send mail for the domain
522(and implicitly all other servers as unauthorized). Policyd-SPF will perform
523SPF checking of received mail and reject mail that fails SPF verfication.</p>
524
525<p>First, tell postfix how to access Policyd-SPF</p>
526
527<pre><code>postconf -e "policyd-spf_time_limit = 3600"
528postconf -M "policyd-spf/unix=policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf"</code></pre>
529
530<p>And then edit the configuration file at
531<strong>/etc/postfix-policyd-spf-python/policyd-spf.conf</strong></p>
532
533<pre><code>debugLevel = 1
534TestOnly = 1
535HELO_reject = Fail
536Mail_From_reject = Fail
537Header_Type = AR
538<em># These settings increase false-positive risk</em>
539<em># Comment them if you want to reduce that risk</em>
540PermError_reject = True
541TempError_Defer = True</code></pre>
542
543
544<h2>SpamAssassin</h2>
545<p>SpamAssassin is a spam-filter that will scan all received mail and assign
546a spam score based on configured rules. SpamAssassin is much heavier and more
547resource-intensive than any of the previous spam-filtering/verification programs
548we have configured. The postfix spam-filtering philosophy emphasizes the use
549of lightweight checks before passing to an external content filter such as
550SpamAssassin. Ideally, non-legitimate mail will have already been caught by one
551of the previous methods, and SpamAssassin will only have to operate on a much
552smaller subset of the mail that is sent to our server.</p>
553
554<p>We have actually already told postfix to use SpamAssassin as a content filter
555so in this section we just need to edit the configuration file
556<strong>/etc/spamassassin/local.cf</strong>.</p>
557
558<pre><code><em># Clearly indicate message is spam to user</em>
559rewrite_header Subject *****SPAM*****
560rewrite_header From *****SPAM*****
561
562<em># Set required score to be marked as spam, 5.0 is default.</em>
563<em># Lower to make policy more strict or raise to be more lenient.</em>
564required_score 5.0
565
566<em># Attach original messages as text/plain instead of message/rfc822 to spam reports</em>
567report_safe 2
568
569<em>Do not implicitly trust mail based on IP address except localhost</em>
570trusted_networks 127.0.0.1/32
571</code></pre>
572
573<p>And finally make a few changes to the defaults file at
574<strong>/etc/default/spamassassin</strong></p>
575
576<pre><code>OPTIONS="--listen /var/run/spamd.sock --max-children 5"
577PIDFILE=/var/run/spamd.pid
578CRON=1</code></pre>
579
580<h2>Wrapping Up</h2>
581<p>At this point we have done all of the necessary configuration of the mail
582server programs. We have just a few more minor tasks before your mail server
583is operational.</p>
584
585<h3>Configure Firewall</h3>
586<p>We need to open the proper ports in the firewall. This example uses UFW.</p>
587
588<pre><code>ufw allow 25 comment "smtp"
589ufw allow 465 comment "submission over TLS"
590<em># Run this next command only if you enabled submission on port 587</em>
591ufw allow 587 comment "mail submission"
592ufw allow 993 comment "IMAP over TLS"
593ufw reload</code></pre>
594
595<h3>Restart services</h3>
596<p>Now let's restart the services to pick up any configuration changes.</p>
597
598<pre><code>systemctl restart postfix
599systemctl restart dovecot
600systemctl restart opendkim
601systemctl restart opendmarc
602systemctl enable --now spamassassin
603systemctl restart spamassassin
604systemctl restart postgrey</code></pre>
605
606<h3>DNS Entries</h3>
607<p>Finally, we needs to set some required DNS records to enable mail flow and
608verification. Begin by logging into your registrar or DNS host and editing
609your DNS records.</p>
610
611<h3>A Record</h3>
612<p>If you did not set a wildcard A record earlier, you will need to set one now
613for <strong>mail</strong>.
614Alternatively, if you are running the mail server on the same server as your
615website, you may want to instead make a CNAME record pointing mail to www.</p>
616
617<h3>MX Record</h3>
618<p>MX records tell servers attempting to send you mail where to send it. Open the
619MX records section on your registrar and add a new record. An MX
620record consists of a priority and a destination. Set the priority to 10 and the
621destination to <strong>mail</strong>, or whatever your subdomain for this mail
622server is. The host value can be left blank or may need to be set to "@"
623depending on your registrar.</p>
624
625<h3>DKIM TXT Record</h3>
626<p>Now we will set the three TXT records we need. Open the TXT records tab on
627your registrar.</p>
628
629<p>We'll set the DKIM record first. The command we ran to
630generate our DKIM keys also generates a DNS record for us which will be helpful
631here. Print that to the screen with:</p>
632
633<pre><code>cat /etc/dkimkeys/mail.txt</code></pre>
634
635<p>You should get a lengthy output that looks something like the following. The
636bolded portion is the value.</p>
637
638<pre><code>mail._domainkey IN TXT ( <strong>"v=DKIM1; h=sha256; k=rsa; "
639 "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz50PSYL0Ob+OlF/0B77rwlzLe7zF6JKnxQNtMqcOCZ0Dar2FPhSUSz1FR0YmNuoShjMogdgKeojIzgRUqwK5GZ5Lz456qiXWkfAtLPc6UQ/WPoyEBGbJpRBYPGWdN4VoNcHkk/I4csvXW6MOI55ghPOwDmootPkCzNPR6gmNAXMe0duS4Lb+bIjy9QMOxGYVUaQ/b+7xar+fWw"
640 "bA3DjQa3jTLCydzzJpjEMfVaKqNhQ4N+ve7O2Mb3LF5k5B977mtok/6POjVG5HY8g6Pba+GzMFItR6nJO5EE2fyfv6cNbRLsZiM+WQmqvDBst5ejaeapy86F5PdJFlX/TUgXjtuwIDAQAB"</strong> ) ; ----- DKIM key mail for example.com</code></pre>
641
642<p>You can cleanup the spacing of the value as your registrar should automatically
643handle any needed splitting of the record. The parts you need to paste into your
644registrar's web interface should then look like this.</p>
645
646<pre><code><em># Name/Host</em>
647mail._domainkey
648<em># TXT Value</em>
649"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz50PSYL0Ob+OlF/0B77rwlzLe7zF6JKnxQNtMqcOCZ0Dar2FPhSUSz1FR0YmNuoShjMogdgKeojIzgRUqwK5GZ5Lz456qiXWkfAtLPc6UQ/WPoyEBGbJpRBYPGWdN4VoNcHkk/I4csvXW6MOI55ghPOwDmootPkCzNPR6gmNAXMe0duS4Lb+bIjy9QMOxGYVUaQ/b+7xar+fWwbA3DjQa3jTLCydzzJpjEMfVaKqNhQ4N+ve7O2Mb3LF5k5B977mtok/6POjVG5HY8g6Pba+GzMFItR6nJO5EE2fyfv6cNbRLsZiM+WQmqvDBst5ejaeapy86F5PdJFlX/TUgXjtuwIDAQAB"</code></pre>
650
651<h3>DMARC TXT Record</h3>
652<p>The DMARC record should be as follows:</p>
653
654<pre><code><em># Name/Host</em>
655_dmarc
656<em># Value</em>
657"v=DMARC1; p=reject; rua=mailto:dmarc@<strong>example.com</strong>; fo=1"
658</code></pre>
659
660<h3>SPF Record</h3>
661<p>Your SPF record will look like this. Remember to replace
662<strong>mail.example.com</strong> with your server name.</p>
663
664<pre><code><em># Name/Host</em>
665@
666<em># Value</em>
667"v=spf1 a:<strong>mail.example.com</strong> -all"
668</code></pre>
669
670<h3>PTR Record</h3>
671<p>Many mail servers rely on PTR records for verification purposes so we need
672to make sure our server's IP address resolves to the proper domain name. If
673your mail server is residing on a VPS, you will need to add this record on your
674VPS provider's interface, consult their documentation for details.</p>
675
676<h2>Creating your own Mail User</h2>
677<p>Your mail server is now up and running. Let's create an email for you to
678receive mail.</p>
679
680<pre><code>useradd --shell /usr/sbin/nologin --create-home --user-group <strong>user</strong>
681echo "<strong>user@example.com user</strong>" &gt;&gt; /etc/postfix/login_maps
682echo "<strong>user user</strong>" &gt;&gt; /etc/postfix/local_maps
683postmap /etc/postfix/login_maps
684postmap /etc/postfix/local_maps
685postfix reload
686</code></pre>
687
688<p>I have a script available for adding and removing users that you can find
689<a href=https://git.chudnick.com/mail-tools/tree/server/mailadm>here</a>.
690
691<h3>Connecting From a Mail Client</h3>
692<p>When connecting your account to a mail client you need to use these settings.</p>
693
694<ul>
695 <li>Username: <strong>user@example.com</strong> </li>
696
697 <li>Password: the password for <strong>user@example.com</strong> </li>
698
699 <li>Server name: <strong>mail.example.com</strong> </li>
700
701 <li>IMAP Port: 993</li>
702
703 <li>IMAP Connection: SSL/TLS</li>
704
705 <li>SMTP Port: 465</li>
706
707 <li>SMTP Connection Type: SSL/TLS</li>
708
709</ul>
710<p>
711<hr>
712Consider <a href=../donate.html>donating</a> if this article was useful.
713<a class=qr href=../images/bitcoin.png>[BTC]</a>
714</p>
715 </main>
716 <footer>
717 <a href=../kb.html>Knowledge Base</a>
718 <br>
719 <a href=../index.html>www.chudnick.com</a>
720 </footer>
721</body>
722</html>
723