Email server: Dovecot and Postfix
Postfix configuration
Install the required software:
$ yum install postfix postgrey dovecot fail2ban spamassassin
spamass-milter-postfix opendkim
Create TLS certificate, key and CA authority (replace mail.domain.tld
with a valid domain name):
$ mkdir /etc/postfix/ssl
$ cd /etc/postfix/ssl
$ openssl genrsa -aes256 -out mail.domain.tld.key 4096
$ chmod 600 mail.domain.tld.key
$ openssl req -sha256 -new -key mail.domain.tld.key -out mail.domain.tld.csr
$ openssl x509 -sha256 -req -days 1825 -in mail.domain.tld.csr -signkey mail.domain.tld.key -out mail.domain.tld.crt
$ openssl rsa -in mail.domain.tld.key -out mail.domain.tld.key.nopass
$ mv mail.domain.tld.key.nopass mail.domain.tld.key
$ openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650 -sha256
$ chmod 600 mail.domain.tld.key
$ chmod 600 cakey.pem
$ openssl dhparam -out dhparams.pem 4096
$ chmod 600 dhparams.pem
Edit main.cf
file accordingly (the other lines should be ok by default).
No SQL database is used, for user authentication postfix relies on Linux users,
email data are stored in ~/Maildir
.
$ vi /etc/postfix/main.cf
---
myhostname = something.com
mydomain = something.com
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relay_domains = $mydestination
alias_maps = hash:/etc/postfix/aliases
alias_database = $alias_maps
home_mailbox = Maildir/
mynetworks = 127.0.0.0/24
milter_default_action = accept
smtpd_milters = inet:127.0.0.1:8891,
inet:127.0.0.1:8893,
unix:/run/spamass-milter/postfix/sock
non_smtpd_milters = $smtpd_milters
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
#smtpd_sasl_security_options = noanonymous,noplaintext
smtpd_recipient_restrictions = permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
# uncomment to enable domains blacklist check
#check_sender_access hash:/etc/postfix/blacklist,
# uncomment to enable postgrey
#check_policy_service unix:/var/spool/postfix/postgrey/socket
permit
#broken_sasl_auth_clients = yes
smtpd_tls_protocols = !SSLv2,!SSLv3
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
smtpd_tls_auth_only = yes
smtpd_tls_security_level = may
smtpd_tls_key_file = /etc/postfix/ssl/mail.domain.tld.key
smtpd_tls_cert_file = /etc/postfix/ssl/mail.domain.tld.crt
#smtpd_tls_CAfile = /etc/postfix/ssl/cacert.pem
smtpd_tls_loglevel = 3
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_eecdh_grade=ultra
smtpd_tls_mandatory_ciphers = high
smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dhparams4096.pem
smtpd_error_sleep_time = 1s
smtpd_soft_error_limit = 10
smtpd_hard_error_limit = 20
smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2,!SSLv3
smtp_tls_mandatory_protocols = !SSLv2,!SSLv3
smtp_tls_mandatory_ciphers = high
smtp_tls_loglevel = 1
lmtp_tls_security_level = may
lmtp_tls_mandatory_protocols = !SSLv2,!SSLv3
lmtp_tls_protocols = !SSLv2,!SSLv3
lmtp_tls_mandatory_ciphers = high
tls_random_source = dev:/dev/urandom
tls_ssl_options = NO_COMPRESSION
mailbox_size_limit = 500000000
message_size_limit = 50000000
mime_header_checks = regexp:/etc/postfix/smtp_header_checks
header_checks = regexp:/etc/postfix/smtp_header_checks
disable_vrfy_command = yes
Edit master.cf
accordingly to enable smtps
:
$ vi /etc/postfix/master.cf
---
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o tls_preempt_cipherlist=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
#-o tls_preempt_cipherlist=yes # force the client to use server's cipherlist
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
Configure spamassassin to filter incoming emails.
$ vi /etc/sysconfig/spamass-milter-postfix
---
SOCKET="/run/spamass-milter/postfix/sock"
SOCKET_OPTIONS="-g postfix"
$ vi /etc/sysconfig/spamassassin
---
SPAMDOPTIONS="-d -c -m5 -H"
Configure a manual blacklist, this can be useful in case we want to block spam
not filtered by spamassassin (edit /etc/postfix/main.cf
accordingly to enable
postgrey): remember to run postmap command and reload postfix service every time blacklist file is modified.
$ vi /etc/postfix/blackilist
---
certaing.address.something REJECT
$ postmap /etc/postfix/blacklist
Another important thing to do is tell postfix to strip some informations off email headers
.
To do so create the following file:
$ vi /etc/postfix/smtp_header_checks
---
/^Received:.*with ESMTPSA/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE
/^User-Agent:/ IGNORE
/^Mime-Version:/ IGNORE
Rebuild Postfix lookup tables using postmap
command:
$ postmap /etc/postfix/header_checks
Postfix should now be working correctly, enable the service and start it:
$ systemctl enable spamass-milter spamassassin postfix _postgrey_ && systemctl
start spamass-milter spamassassin postfix _postgrey_
Dovecot
Even for Dovecot no database is used. Copy sample config files:
$ cp /usr/share/doc/dovecot/example-config/dovecot.conf /etc/dovecot
$ cp -r /usr/share/doc/dovecot/example-config/conf.d /etc/dovecot
Generate TLS certificates:
### copy the config file
$ cp /etc/ssl/dovecot-openssl.cnf{.sample,} .
### edit the configuration
$ vi /etc/ssl/dovecot-openssl.cnf
### generate the certificate/key pair - /etc/ssl/certs/dovecot.pem and /etc/ssl/private/dovecot.pem
### /usr/lib/dovecot/mkcert.sh to generate the certificate.
$ mv /etc/ssl/certs/dovecot.pem /etc/ca-certificates/trust-source/anchors/dovecot.crt
$ trust extract-compat
Edit 10-mail.conf
:
$ vi /etc/dovecot/conf.d/10-mail.conf
---
mail_location = maildir:~/Maildir
namespace inbox {
inbox = yes
}
Edit 10-master.conf
:
$ vi /etc/dovecot/conf.d/10-master.conf
---
service auth {
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
}
Edit 10-ssl.conf
:
$ vi /etc/dovecot/conf.d/10-ssl.conf
---
ssl_cipher_list=ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
ssl_dh_parameters_length = 4096
Edit 10-auth.conf
to prevent downgrade attacks performed against STARTTLS:
$ vi /etc/dovecot/conf.d/10-auth.conf
---
disable_plaintext_auth = yes
ssl=required
SPF record
Set a SPF record to not get sent emails marked as spam.
Create a TXT record, put @
in the hostname field
and the following string
(replace xxx.xxx.xxx.xxx with and IP address) in the IP/url field.
v=spf1 a mx ip4:xxx.xxx.xxx.xxx -all
DKIM
Generate the keys for domain.tld
and edit opendkim configuration file:
$ opendkim-genkey -D /etc/opendkim/keys/ -d domain.tld -s default
$ chown -R opendkim:opendkim /etc/opendkim/keys/
$ restorecon -Rv /etc/opendkim/keys
$ vi /etc/opendkim.conf
---
Mode sv
Socket inet:8891@localhost
Canonicalization relaxed/simple
Domain domain.tld
#KeyFile /etc/opendkim/keys/default.private
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
SignatureAlgorithm rsa-sha256
Edit KeyTable
file and set the correct domain name:
$ vi /etc/opendkim/KeyTable
---
default._domainkey.domain.tld domain.tld:default:/etc/opendkim/keys/default.private
Edit SigningTable
file and set the correct domain name:
$ vi /etc/opendkim/SigningTable
---
*@domain.tld default._domainkey.domain.tld
Edit TrustedHosts
file and set the correct domain name:
$ vi /etc/opendkim/TrustedHosts
---
127.0.0.1
::1
domain.tld
mail.domain.tld
Use the content of /etc/opendkim/keys/default.txt
to create a new TXT record on the DNS.
Enable opendkim service:
$ systemctl enable opendkim && systemctl start opendkim
DMARC
Install and start opendmarc:
$ yum install opendmarc
$ systemctl enable opendmarc && systemct start opendmarc && systemctl restart postfix
Also add a new TXT DNS record:
TXT _dmarc v=DMARC1; aspf=r; p=quarantine; pct=100; rua=mailto:postmaster@domain.tld; ruf=mailto:postmaster@domain.tld 1800
Where:
TXT=record type (required)
v=Protocol version (required)
p=Policy for domain (required) - available options: "none", "quarantine", "reject"
aspf=Alignment mode for SPF (optional) - available options: "r" (relaxed) to allow subdomains and "s" (strict) to filter subdomains
pct=percentage of messages subjected to filtering (optional)
rua=Reporting URI of aggregate reports
ruf=tag for the distribution of forensic reports
For some reason namecheap knowledge base is wrong, when defining a TXT record for DMARC the host must be set to _dmarc
instead of _dmarc.domain.tld<.>
.
Fail2ban
Fail2ban is a useful tool capable of mitigating brute force attacks performed against a multitude of services (openssh, dovecot, postfix, etc).
Create a file named jail.local
.
$ cd /etc/fail2ban
$ vi jail.clocal
---
[DEFAULT]
ignoreip = 127.0.0.1/8
backend = systemd
[dovecot]
enabled = true
port = 25,143,465,587,993
action = iptables-multiport[name=dovecot, port="25,143,465,587,993", protocol=tcp]
logpath = /var/log/maillog
maxretry = 5
findtime = 7200
bantime = 7200
[postfix]
enabled = true
port = 25,143,465,587,993
action = iptables-multiport[name=postfix, port="25,143,465,587,993", protocol=tcp]
logpath = /var/log/maillog
maxretry = 5
findtime = 7200
bantime = 7200
[postfix-sasl]
enabled = true
port = 25,143,465,587,993
action = iptables-multiport[name=postfix-sasl, port="25,143,465,587,993", protocol=tcp]
logpath = /var/log/maillog
maxretry = 5
findtime = 7200
bantime = 7200
---
$ systemctl enable iptables fail2ban && systemctl restart iptables fail2ban
Add some custom rules to failregex line:
$ vi /etc/fail2ban/filter.d/postfix.conf
---
^%(__prefix_line)slost connection after AUTH from (.*)\[<HOST>\]$
^%(__prefix_line)slost connection after CONNECT from (.*)\[<HOST>\]$
^%(__prefix_line)slost connection after EHLO from (.*)\[<HOST>\]$
Iptables
Edit iptables.rules
and add:
$ systemctl stop iptables
$ vi /etc/iptables/iptables.rules
---
-A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 587 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
---
$ systemctl start iptables
This is it, if I didn’t got anything wrong the IMAP/SMTP services should be up and running and accesible from every client supporting TLS and IMAP.
I personally use K-9 mail on Android and Thunderbird on Linux computers.
Usefull links:
- test postfix encryption: checktls.com
- test email server capabilities: mail-tester.com
- test mail server for IP leak: emailipleak.com