Setup Email Server From Scratch On FreeBSD - 09 Blocking Spam
08 Create Virtual Domains <- Intro -> 25 IMAPSYNC
This tutorial is partially complete 2025-05-14
Postfix, Dovecot, & PostfixAdmin work with MySQL and virtual accounts
can be created with PostfixAdmin and used with an email client. SPF, OpenDKIM,
and DMARC milters, Roundcube with sieve filters and password plugins all work.
Roundcube kolab calendar works (2025-05-20)
#################
# Blocking Spam #
#################
nano /etc/postfix/main.cf
# Reject if no A Record
# Reject email from hosts with invalid A Record or no PTR Record
# sender MX or A
# client A
# reverse PTR
smtpd_sender_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unknown_sender_domain
reject_unknown_client_hostname
reject_unknown_reverse_client_hostname
# Reject invalid HELO/EHLO
smtpd_helo_required = yes
smtpd_helo_restrictions =
permit_mynetworks
permit_sasl_authenticated
check_helo_access hash:/etc/postfix/helo_access
reject_invalid_helo_hostname
reject_non_fqdn_helo_hostname
reject_unknown_helo_hostname
nano /etc/postfix/helo_access
# ---
goodhost1.domain1.com OK
goodhost1.domain2.com OK
# ---
postmap /etc/postfix/helo_access
service postfix restart
# PostGrey
# Quote from linuxbabe "As required by the SMTP protocol, any legitimate SMTP
# client must be able to re-send email if delivery fails. (By default, Postfix
# is configured to resend failed emails many times before it informs the sender
# that the message could not be delivered.) Many spammers usually just send once
# and would not retry."
# To prevent postgrey from slowing down legitimate mails, use to 2 DNS entries so the
# mail server will first try the entry with priority 0 then after 1 second try the
# entry with priority 10, eg a resend and less likely to be spam.
# To prevent greylisting delay add 2 mx records to your DNS, like this.
MX mx.okbsd.com 0
MX mail.okbsd.com 10
# Install PostGrey and enable and set the 1 second delay in /etc/rc.conf
pkg install postgrey
sysrc postgrey_enable="YES"
sysrc postgrey_flags=" --inet=10023 --delay=1 --greylist-text='greylisted'"
service postgrey start
service postgrey status
# Check if it is listening
sockstat | grep postgrey
postgrey perl 24350 4 dgram -> /var/run/log
postgrey perl 24350 5 tcp6 ::1:10023 *:*
postgrey perl 24350 6 tcp4 127.0.0.1:10023 *:*
# Add Postgrey port 10023 to postfix/main.cf
nano /usr/local/etc/postfix/main.cf
# ---
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service unix:private/policyd-spf,
check_policy_service inet:127.0.0.1:10023
# ---
# Postgrey default whitelist files are located in
# /usr/local/etc/postfix/postgrey_whitelist_clients
# /usr/local/etc/postfix/postgrey_whitelist_recipients
service postfix restart
# Real Time Blacklists
nano /usr/local/etc/postfix/main.cf
# ---
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service unix:private/policyd-spf,
check_policy_service inet:127.0.0.1:10023,
check_client_access hash:/usr/local/etc/postfix/rbl_override,
reject_rhsbl_helo dbl.spamhaus.org,
reject_rhsbl_reverse_client dbl.spamhaus.org,
reject_rhsbl_sender dbl.spamhaus.org,
reject_rbl_client zen.spamhaus.org
# ---
# You can override the blacklists
nano /usr/local/etc/postfix/rbl_override
# ---
domain1.com OK // ignore rbl for domain1.com
domain2.com OK // ignore rbl for domain2.com
# ---
postmap /usr/local/etc/postfix/rbl_override
# Use a Public Whitelist
nano /usr/local/etc/postfix/main.cf
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service unix:private/policyd-spf,
check_policy_service inet:127.0.0.1:10023,
check_client_access hash:/etc/postfix/rbl_override,
reject_rhsbl_helo dbl.spamhaus.org,
reject_rhsbl_reverse_client dbl.spamhaus.org,
reject_rhsbl_sender dbl.spamhaus.org,
permit_dnswl_client list.dnswl.org=127.0.[0..255].[1..3],
permit_dnswl_client swl.spamhaus.org,
reject_rbl_client zen.spamhaus.org
# Postfix Log Reports
pkg install pflogsumm
pkg install mutt
# test it
pflogsumm /var/log/maillog -d today /var/log/maillog
# Setup a crontab to send a report at 12:30am. Initially I used maillog but it rotates
# by default at 12am so yesterday has been rotated by the time we read the log. So read
# the last compressed rotation and pipe that to pflogsumm and send the report.
crontab -e
# ---
30 0 * * * bzcat /var/log/maillog.0.bz2 | pflogsumm -d yesterday | /usr/local/bin/mutt -s "Postfix log summary" -- admin@okbsd.com
# ---
# Make sure you are not an open relay
nano /usr/local/etc/postfix/main.cf
# ---
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
# ---
# We setup DMARC in a prevous page, but make sure your myhostname in postfix/main.cf
# is included in TrustedAuthservIDs, mine is mx.okbsd.com
nano /usr/local/etc/mail/opendmarc.conf
# ---
TrustedAuthservIDs localhost,mx.okbsd.com,mail.okbsd.com
# ---
nano /usr/local/etc/mail/ignore.hosts
# ---
127.0.0.1
147.135.65.9
2604:2dc0:100:1261::10
::1
localhost
mx.obsd.com
# ---
# Dont DKIM check your own hosts
nano /usr/local/etc/mail/trustedhosts
# ---
127.0.0.1
localhost
147.135.65.97
2604:2dc0:100:1261::10
*.okbsd.com
okbsd.com
*.coragarden.com
coragarden.com
# ---
service postfix restart
# Check everything works
# If everything works back it up with tar like we did before.
# unbound
drill -k /usr/local/etc/unbound/root.key -S okbsd.com @127.0.0.1