Setup Email Server From Scratch On FreeBSD #2 - 10 Blocking Spam

09 Create Virtual Domains <- Intro -> 25 IMAPSYNC

We believe in data independence, and support others who want data independence.
This tutorial is partially complete 2025-08-07

This is version 2 and everthing works up to and including Roundcube.

#################
# 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 smtp.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 smtp.okbsd.com

nano /usr/local/etc/mail/opendmarc.conf
# ---
TrustedAuthservIDs localhost,smtp.okbsd.com,mail.okbsd.com
# ---

nano /usr/local/etc/mail/ignore.hosts
# ---
127.0.0.1
147.135.65.9
2604:2dc0:200:187::1
::1
localhost
smtp.okbsd.com
# ---

# Dont DKIM check your own hosts
nano /usr/local/etc/mail/trustedhosts
# ---
127.0.0.1
localhost
147.135.37.135
2604:2dc0:200:187::1
*.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

09 Create Virtual Domains <- Intro -> 25 IMAPSYNC