Setup Email Server From Scratch Debian #2 - 10 Blocking Spam

09 Virtual Domains <- Intro -> 11 SpamAssassin

We believe in data independence, and support others who want data independence.
Debian Email From Scratch version 2 finished 2025-07-30.

We are still adding to it but it all works!

#################
# Blocking Spam #
#################

# Change your smtpd banner to provide less information about your mail service

nano /etc/postfix/main.cf
# --- change this --
smtpd_banner = $myhostname ESMTP           
# ---

# Reject email from hosts with invalid A Record or no PTR Record
# reject_unknown_sender_domain : no MX or A Record
# reject_unknown_client_hostname : no client A Record
# reject_unknown_reverse_client_hostname : NO PTR IPADDRESS -> NAME 

nano /etc/postfix/main.cf
# --- edit at bottom of file
policyd-spf_time_limit = 3600

smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   check_policy_service unix:private/policyd-spf

smtpd_sender_restrictions =
   permit_mynetworks
   permit_sasl_authenticated
   reject_unknown_sender_domain
   reject_unknown_reverse_client_hostname
   reject_unknown_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

# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:opendkim/opendkim.sock,unix:opendmarc/opendmarc.sock
non_smtpd_milters = $smtpd_milters
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

# Pass bounces to milters so bounce messages also get DKIM signed are are not rejected
internal_mail_filter_classes = bounce

# ---

nano /etc/postfix/helo_access
# ---
# whitelist legitimate servers that don't conform to helo
optimus-webapi-prod-2.localdomain      OK
va-massmail-02.rakutenmarketing.com    OK
goodhost1.domain1.com	OK
goodhost1.domain2.com	OK
# ---

postmap /etc/postfix/helo_access
systemctl restart postfix

# Enable Greylisting in Postfix

# 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."

apt install postgrey
systemctl enable postgrey
systemctl start postgrey
systemctl status postgrey
netstat -lnpt | grep postgrey

tcp    0   0   127.0.0.1:10023    0.0.0.0:*   LISTEN      3861/postgrey --ine 
tcp6   0   0   ::1:10023          :::*        LISTEN      3861/postgrey --ine 

# Add check_policy_service inet:127.0.0.1:10023 to smtpd_recipient_restrictions

nano /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 
# ---

nano /etc/defaults/postgrey
# ---
POSTGREY_OPTS="--inet=127.0.0.1:10023 --delay=1"
POSTGREY_TEXT="4.7.1 Greylisted"
# ---

# 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.okdeb.com		0
MX mail.okdeb.com	10

systemctl restart postfix

# View postgrey logs, see what is being blocked, to see if new entries need to 
# be added to whitelist.

journalctl -u postgrey.

# Postgrey default whitelist files are located in 

# /etc/postgrey/whitelist_clients
# /etc/postgrey/whitelist_recipients

# Restart postgrey chaning postgrey whitelists

systemctl restart postgrey

# Real Time Blacklists - add the after check_policy_service inet:127.0.0.1:10023

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,
   reject_rbl_client zen.spamhaus.org
# ---

# You can override the blacklists by adding domains to the rbl_override file.

nano /etc/postfix/rbl_override
# ---
domain1.com	OK // ignore rbl for domain1.com
domain2.com	OK // ignore rbl for domain2.com
# ---

postmap /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
# ---

# Get Postfix Log Reports

apt install pflogsumm mutt

# test it
/usr/bin/journalctl --no-pager --since=yesterday -u postfix@-.service | /usr/sbin/pflogsumm -d yesterday

# Setup a crontab to send a report at 12:00am.

export EDITOR /usr/bin/nano
crontab -e
# ---
5 0 * * * /usr/bin/journalctl --no-pager --since=yesterday -u postfix@-.service | /usr/sbin/pflogsumm -d yesterday | mutt -s "Postfix log summary" -- postmaster@okdeb.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, make sure your 'myhostname' from postfix/main.cf
# is included in /etc/opendmarc.conf as TrustedAuthservIDs, mine is mx.okdeb.com.

grep myhostname /etc/postfix/main.cf
myhostname = mx.okdeb.com

nano /etc/opendmarc.conf
# ---
TrustedAuthservIDs mx.okdeb.com
# ---

nano /etc/opendmarc/ignore.hosts
# ---
127.0.0.1
147.135.65.9
2604:2dc0:202:300::3645
::1
localhost
# ---


# Dont DKIM check your own hosts
nano /etc/opendkim/trustedhosts
# ---
127.0.0.1
::1
localhost
15.204.113.148
2604:2dc0:202:300::3645
mx.okdeb.com
mx.coragarden.com
mail.okdeb.com
mail.coragarden.com
okdeb.com
coragarden.com
# ---

systemctl restart opendkim opendmarc postfix dovecot

# Check everything works

# If everything works, back it up.

09 Virtual Domains <- Intro -> 11 SpamAssassin