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

08 Create Virtual Domains <- Intro -> 25 IMAPSYNC