Postfix Spam Protection Improvements
Overview
Implemented multi-layer spam protection for mail server at mail.keisanki.net.
1. Fixed SpamAssassin Milter Socket
Problem: SpamAssassin milter socket path was incorrect, causing spam filtering to fail.
Solution: Created proper systemd service and fixed socket path.
File: /etc/systemd/system/spamass-milter.service
[Unit]
Description=SpamAssassin Milter
After=network.target spamd.service
[Service]
Type=simple
ExecStart=/usr/sbin/spamass-milter -u spamass-milter -i 127.0.0.1 -r 15 -p /var/spool/postfix/spamass/spamass.sock
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
File: /etc/postfix/main.cf
smtpd_milters = unix:/var/spool/postfix/spamass/spamass.sock, unix:/var/spool/postfix/opendkim/opendkim.sock
File: /etc/postfix/master.cf (submission port)
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_milters=
-o non_smtpd_milters=
2. Enabled Postscreen
Purpose: Early connection screening before SMTP handshake.
File: /etc/postfix/master.cf
smtp inet n - y - 1 postscreen
smtpd pass - - y - - smtpd
dnsblog unix - - y - 0 dnsblog
tlsproxy unix - - y - 0 tlsproxy
File: /etc/postfix/main.cf
postscreen_dnsbl_sites = zen.spamhaus.org*3
bl.spamcop.net
b.barracudacentral.org*2
postscreen_dnsbl_action = enforce
postscreen_greet_action = enforce
postscreen_blacklist_action = enforce
3. Added DNSBL Checks to Recipient Restrictions
Purpose: Second layer DNSBL checking during SMTP transaction.
File: /etc/postfix/main.cf
smtpd_recipient_restrictions =
permit_sasl_authenticated,
permit_mynetworks,
reject_invalid_helo_hostname,
reject_non_fqdn_helo_hostname,
reject_unknown_recipient_domain,
reject_unauth_destination,
reject_unauth_pipelining,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client bl.spamcop.net,
check_policy_service unix:private/policyd-spf,
permit
4. Enabled SPF Verification
Purpose: Verify SPF records for incoming mail.
Installation:
apt install -y postfix-policyd-spf-python
File: /etc/postfix/master.cf
policyd-spf unix - n n - 0 spawn
user=policyd-spf argv=/usr/bin/policyd-spf-perl
File: /etc/postfix/main.cf
smtpd_recipient_restrictions =
...
check_policy_service unix:private/policyd-spf,
permit
5. Fixed SpamAssassin Learning Script
Problem: Script didn't use --mbox flag for mbox format mailboxes.
File: /root/scripts/sa_learn_vmail.sh
if [ -d "$PATH_TO_MAIL" ]; then
# Directory (Maildir style)
log "INFO" "Training $TYPE_LABEL for user $USER from directory $PATH_TO_MAIL"
sa-learn $SA_LEARN_ARGS "$PATH_TO_MAIL" >>"$LOG_FILE" 2>&1
elif [ -f "$PATH_TO_MAIL" ]; then
# Single file (mbox style)
log "INFO" "Training $TYPE_LABEL for user $USER from mbox file $PATH_TO_MAIL"
sa-learn $SA_LEARN_ARGS --mbox "$PATH_TO_MAIL" >>"$LOG_FILE" 2>&1
Timer: sa-learn-vmail.timer runs daily at 03:30
6. Enabled Daily Rule Updates
Purpose: Keep SpamAssassin rules current via sa-update.
Command:
systemctl enable --now spamassassin-maintenance.timer
Timer: spamassassin-maintenance.timer runs daily around 06:00
Current Spam Protection Stack
- Postscreen - Early connection screening (DNSBL, greet pause, protocol tests)
- SMTP Restrictions - HELO validation, DNSBL checks
- SPF Verification - policyd-spf-python
- DKIM Verification - OpenDKIM (already configured)
- SpamAssassin - Content filtering via milter
- Bayesian Learning - Daily training from Junk/Sent folders
- Rule Updates - Daily sa-update
Verification
Check postscreen is blocking spam:
tail -f /var/log/mail.log | grep postscreen
Check SpamAssassin is filtering:
systemctl status spamass-milter
Manual training:
sa-learn --spam --mbox /var/vmail/oib/mail/Junk
sa-learn --ham --mbox /var/vmail/oib/mail/INBOX
- Log in to post comments