HARDENING POSTFIX

SPF OUTBOUND

setup your MX and SPF DNS records accordingly

SYSTEM-WIDE SETUP

give a name to your root account (something that helps identify the system)

vipw

root@xc

proceed with system-wide mail setup (BSD)

cp -pi /etc/mail/aliases /etc/mail/aliases.dist
#cp -pi /etc/aliases /etc/aliases.dist
vi /etc/mail/aliases
#vi /etc/aliases

note the abuse mail alias should be defined by default

root:           REAL-USER
#root:          REAL-EMAIL@DOMAIN.TLD
abuse:          root
postmaster:     root
hostmaster:     root
www:            root
webmaster:      root

and apply

newaliases
tail -F /var/log/maillog
#tail -F /var/log/mail.log
date | mail -s `uname -n` root

START CLEAN

cd /etc/postfix/

#sed '/^#/d; /^$/d' main.cf.proto > main.cf
mv -i main.cf main.cf.dist
sed '/^#/d; /^$/d' main.cf.dist > main.cf
sed '/^#/d; /^$/d' main.cf.dist > main.cf.dist.clean

##sed '/^#/d; /^$/d' master.cf.proto > master.cf
#mv -i master.cf master.cf.dist
#sed '/^#/d; /^$/d' master.cf.dist > master.cf
#sed '/^#/d; /^$/d' master.cf.dist > master.cf.dist.clean

WARNING

always check the configuration manual for accuracy of the features. those merely depend on the exact Postfix version you are using. we are talking Postfix 3.1.0, 3.1.4, 3.3.0 here.

postconf -d | grep version
man 5 postconf

if you are unsure about some restriction, you can evaluate it even on production with

        warn_if_reject,

and always check the configuration syntax before restart

postfix check && echo ok

SUPPORTING FILES

NETWORK

cat > /etc/postfix/access.network <<-EOF
compute.amazonaws.com   REJECT too much SPAM from compute.amazonaws.com
.compute.amazonaws.com  REJECT too much SPAM from compute.amazonaws.com
EOF
postmap /etc/postfix/access.network

EHLO

cat > /etc/postfix/access.helo.regexp <<-EOF
/^malabar\.nethence\.com$/     550 you are not me
/^xc\.nethence\.com$/          550 you are not me
/^mx\.nethence\.com$/          550 you are not me
/^nethence\.com$/              550 you are not me
EOF
cat /etc/postfix/access.helo.regexp 

MAIL FROM

cat > /etc/postfix/access.sender <<-EOF
#securityfocus.com       OK
online.net              OK
ovh.com                 OK
EOF
postmap /etc/postfix/access.sender

DEFAULTS

vi /etc/postfix/main.cf

we are starting with those defaults w/ netbsd8/3.1.4

compatibility_level = 2
smtputf8_enable=no
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/db/postfix
mail_owner = postfix
inet_protocols = all
unknown_local_recipient_reject_code = 550
debug_peer_level = 2
debugger_command =
         PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
         ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
setgid_group = maildrop
html_directory = /usr/share/doc/html/postfix
manpage_directory = /usr/share/man
sample_directory = /usr/share/examples/postfix
readme_directory = /usr/share/examples/postfix

we are fixing those

html_directory = no
sample_directory = no
readme_directory = no

and adding those

shlib_directory = no
meta_directory = /etc/postfix

or those default w/ ubuntu/bionic/3.3.0

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

MAIN CONFIG & RELAY

eventually add space-separated CIDRs to mynetworks e.g. for Docker (172.17.0.0/16) or local subnets

#defaults to myhostname
myorigin = nethence.com
#defaults to FQDN minus the first component
mydomain = nethence.com
myhostname = xc.nethence.com
mydestination = nethence.com
mynetworks = 127.0.0.1/32

#w/o permit_sasl_authenticated, we use a dedicated port for that
smtpd_relay_restrictions = permit_mynetworks, reject_unauth_destination

CASUAL

we are now adding casual settings, nothing fancy so far

#25MiB
message_size_limit = 26214400
#home_mailbox = Maildir/
#defaults to $myhostname ESMTP $mail_name
smtpd_banner = $myhostname ESMTP
biff = no
append_dot_mydomain = no
strict_rfc821_envelopes = yes
disable_vrfy_command = yes
smtpd_delay_reject = yes

NETWORK

smtpd_soft_error_limit = 5 
smtpd_error_sleep_time = 3s
smtpd_hard_error_limit = 10

smtpd_client_restrictions = permit_mynetworks,
        reject_unknown_client_hostname,
        check_client_access hash:/etc/postfix/access.network,
        check_policy_service unix:private/policy,
        reject_rbl_client bl.spamcop.net,
        reject_rbl_client cbl.abuseat.org,
        reject_rbl_client b.barracudacentral.org,
        reject_rbl_client zen.spamhaus.org,
        reject_unauth_pipelining

# this is too restrictive
#       reject_rhsbl_sender dsn.rfc-clueless.org,

# apews is blocking online.net ip range
#       reject_rbl_client l2.apews.org,

# sarbl.org not found
#       reject_rbl_client public.sarbl.org,

#deprecated: policy_time_limit = 3600
smtpd_policy_service_request_limit = 1
#http://www.postfix.org/SMTPD_POLICY_README.html

#reject_unknown_client_hostname --> unknown_client_reject_code
#reject_unknown_reverse_client_hostname --> unknown_client_reject_code
unknown_client_reject_code   = 554

#smtpd_client_port_logging = yes

EHLO

smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname,
        reject_unknown_helo_hostname,
        regexp:/etc/postfix/access.helo.regexp

#reject_unknown_helo_hostname --> unknown_hostname_reject_code
unknown_hostname_reject_code = 554

MAIL FROM

smtpd_sender_restrictions = permit_mynetworks,
        check_sender_access hash:/etc/postfix/access.sender,
        reject_non_fqdn_sender,
        reject_unknown_sender_domain

RCPT TO

smtpd_recipient_restrictions = permit_mynetworks,
        reject_non_fqdn_recipient,
        reject_unknown_recipient_domain

#reject_unknown_sender_domain --> unknown_address_reject_code
#reject_unknown_recipient_domain --> unknown_address_reject_code
unknown_address_reject_code  = 554

DATA

#client speaks too early
smtpd_data_restrictions = reject_unauth_pipelining

STARTTLS

see postfix-tls

CHROOT TIMEZOME

ls -lF /etc/localtime
ls -lF /var/spool/postfix/etc/localtime
diff /etc/localtime /var/spool/postfix/etc/localtime

no symlink inside the chroot

#cp -f /etc/localtime /var/spool/postfix/etc/localtime

READY TO GO & SPF INBOUND

now enable port 25 WITHOUT SASL and SPF inbound check

vi /etc/postfix/master.cf

smtp      inet  n       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=no

policy    unix  -       n       n       -       0       spawn
  user=nobody argv=/usr/pkg/bin/policyd-spf
#/usr/bin/policyd-spf

and see above smtpd_client_restrictions = check_policy_service unix:private/policy

OPERATIONS & ACCEPTANCE

finally operate the daemon and proceed with acceptance testing

ADDITIONAL NOTES

BACKUP MX

Warning: I start to consider that this is a bad practice, as it is just too painful to maintain two MXes at once (otherwise spams come through your seconday MX server)

Play with relay_domains, transport_maps and do NOT list example.com into mydestination. Here’s a minimal setup

#backup MX
smtpd_banner = ESMTP
relay_domains = nethence.com
myhostname = ssd.nethence.com
myorigin = ssd.nethence.com
mydestination = ssd.nethence.com
mynetworks = 127.0.0.1/32

You also have to enable outbound STARTTLS in case the primary MX enforces it. Otherwise you would get

530 5.7.0 Must issue a STARTTLS command first (in reply to MAIL FROM command)

Finally, on the other side (primary MX), eventually add the backup MX into mynetworks or fine tune everything to make sure the relaying works accordingly. SPF should pass through already, as long as you’ve setup the appropriate DNS record for the backup MX.

FAIL2BAN

eventually enable Fail2ban as an attempt to protect yourself from bot nets. but a parser going through logs is less than ideal – rather go for netbsd/blacklistd

TODO mariadb mappings

TODO memcache

Postfix memcache client Howto http://www.postfix.org/MEMCACHE_README.html

TODO dovecot director / LMTP vs direct storage

Director https://wiki2.dovecot.org/Director

Dovecot mailstore performance tuning https://dovecot.org/pipermail/dovecot/2014-July/097120.html

How To Configure a Mail Server Using Postfix, Dovecot, MySQL, and SpamAssassin https://www.digitalocean.com/community/tutorials/how-to-configure-a-mail-server-using-postfix-dovecot-mysql-and-spamassassin

Difference btw. Dovecot Director and Dovecot Proxy https://dovecot.org/pipermail/dovecot/2014-July/097112.html

vs

Postfix feature overview –> Postfix file system requirements http://www.postfix.org/features.html

RESOURCES

Wietse Zweitze Venema http://www.porcupine.org/wietse/ http://www.porcupine.org/forensics/wietse.pgp

Postfix Basic Configuration http://www.postfix.org/BASIC_CONFIGURATION_README.html

Postfix Configuration Parameters http://www.postfix.org/postconf.5.html

master - Postfix master process configuration file format http://www.postfix.org/master.5.html

Changing the Postfix maximum email size https://www.electrictoolbox.com/postfix-email-size-limit/

Increasing Attachment Size in Posfix https://easyengine.io/tutorials/mail/postfix-attachment-size/

hardening

RFC2 Realtime List http://rfc-clueless.org/

Hardening Postfix For ISPConfig 3 https://www.howtoforge.com/hardening-postfix-for-ispconfig-3

How To Fight Spam Using Your Postfix Configuration https://www.howtoforge.com/virtual_postfix_antispam

Postfix configure anti spam with blacklist https://www.cyberciti.biz/tips/postfix-spam-filtering-with-blacklists-howto.html

Blacklist & Whitelist with Postfix https://linuxlasse.net/linux/howtos/Blacklist_and_Whitelist_with_Postfix

Mimecast SMTP Error Codes https://community.mimecast.com/docs/DOC-1369

alternatives

atech/postal https://github.com/atech/postal/wiki


Nethence | Pub | Lab | Pbraun | SNE Russia | xhtml