Post

MTA-STS Implementation Guide for Postfix + RSPAMD 3.4

MTA-STS Implementation Guide for Postfix + RSPAMD 3.4

Complete MTA-STS Implementation Guide for Postfix + RSPAMD 3.4

Overview

This guide provides a real-world tested approach to implementing MTA-STS (Mail Transfer Agent Strict Transport Security) with Postfix and RSPAMD 3.4, including complete troubleshooting based on actual deployment experience.

Important: This guide is based on successful deployment with RSPAMD 3.4, which has limited native MTA-STS support. MTA-STS works primarily through Postfix, DNS, and web infrastructure.

Prerequisites

  • Working Postfix mail server with TLS configured
  • RSPAMD 3.4 installed and running
  • Apache web server with SSL/TLS certificates
  • DNS control for your domains
  • Example domains used: testedbymatt.com and matthewdavidson.us

Phase 1: Infrastructure Setup

Step 1: Verify Postfix TLS Configuration

Ensure your existing Postfix TLS setup is working:

1
2
# Check main.cf has these essential settings
grep -E "(smtpd_tls_cert|smtpd_tls_key|smtpd_tls_security)" /etc/postfix/main.cf

Your main.cf should include:

1
2
3
4
5
6
7
8
9
# TLS for incoming connections
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
smtpd_tls_security_level=may
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

# TLS for outgoing connections
smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

Critical: Do NOT add smtp_tls_policy_maps lines - these cause errors in RSPAMD 3.4 setups.

Step 2: Test Mail Server TLS

1
echo "QUIT" | openssl s_client -connect mail.yourdomain.com:25 -starttls smtp 2>/dev/null | grep "Verify return code"

Expected: Verify return code: 0 (ok)

Step 3: Check MX Records

Critical Step: Your MTA-STS policy MUST exactly match your MX records.

1
2
dig MX yourdomain.com +short
dig MX anotherdomain.com +short

Document these results - you’ll need them for the policy files.

Phase 2: MTA-STS Policy Files

Step 1: Create Directory Structure

1
2
mkdir -p /var/www/mta-sts.yourdomain.com/.well-known/
mkdir -p /var/www/mta-sts.anotherdomain.com/.well-known/

Step 2: Create Policy Files

Critical: The mx: entries must EXACTLY match your MX records from Step 3 above.

/var/www/mta-sts.yourdomain.com/.well-known/mta-sts.txt:

1
2
3
4
version: STSv1
mode: enforce
mx: mail.yourdomain.com
max_age: 86400

If you have multiple MX records, list them ALL: /var/www/mta-sts.anotherdomain.com/.well-known/mta-sts.txt:

1
2
3
4
5
version: STSv1
mode: enforce
mx: mail.anotherdomain.com
mx: mail.yourdomain.com
max_age: 86400

Step 3: Configure Apache Virtual Hosts

Create /etc/apache2/sites-available/mta-sts.yourdomain.com.conf:

1
2
3
4
5
6
<VirtualHost *:80>
    ServerName mta-sts.yourdomain.com
    DocumentRoot /var/www/mta-sts.yourdomain.com
    RewriteEngine on
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Create /etc/apache2/sites-available/mta-sts.yourdomain.com-le-ssl.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName mta-sts.yourdomain.com
    DocumentRoot /var/www/mta-sts.yourdomain.com
    
    <Directory /var/www/mta-sts.yourdomain.com>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # Ensure .well-known directory is accessible
    <Directory "/var/www/mta-sts.yourdomain.com/.well-known">
        Require all granted
    </Directory>
    
    SSLCertificateFile /etc/letsencrypt/live/mta-sts.yourdomain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mta-sts.yourdomain.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
    
    ErrorLog ${APACHE_LOG_DIR}/mta-sts.yourdomain.com_error.log
    CustomLog ${APACHE_LOG_DIR}/mta-sts.yourdomain.com_access.log combined
</VirtualHost>
</IfModule>

Repeat for each domain, then:

1
2
3
a2ensite mta-sts.yourdomain.com
a2ensite mta-sts.yourdomain.com-le-ssl
systemctl reload apache2

Step 4: Test Policy File Access

1
2
curl -s https://mta-sts.yourdomain.com/.well-known/mta-sts.txt
curl -s https://mta-sts.anotherdomain.com/.well-known/mta-sts.txt

Both should return your policy content with HTTP 200.

Phase 3: DNS Configuration

Step 1: Add MTA-STS DNS Records

CRITICAL: DNS record formatting is crucial. Use EXACTLY this format:

_mta-sts.yourdomain.com. IN TXT "v=STSv1; id=20250809"
_mta-sts.anotherdomain.com. IN TXT "v=STSv1; id=20250809"

Common Error: Do NOT use escaped quotes like "\"v=STSv1; id=20250809\"" - this breaks external discovery.

Step 2: Verify DNS Records

1
2
dig TXT _mta-sts.yourdomain.com +short
dig TXT _mta-sts.anotherdomain.com +short

Both should return: "v=STSv1; id=20250809"

NOT: "\"v=STSv1; id=20250809\""

Step 3: Test DNS from Multiple Servers

1
2
3
4
# Test from different DNS servers to ensure propagation
dig @8.8.8.8 TXT _mta-sts.yourdomain.com +short
dig @1.1.1.1 TXT _mta-sts.yourdomain.com +short
dig @208.67.222.222 TXT _mta-sts.yourdomain.com +short

Phase 4: External Validation (CRITICAL)

This step is essential - internal testing doesn’t catch DNS formatting issues.

Step 1: Use External MTA-STS Validators

Test each domain with these external tools:

  1. Mailhardener: https://www.mailhardener.com/tools/mta-sts-validator
  2. EasyDMARC: https://easydmarc.com/tools/mta-sts-check
  3. MxToolbox: https://mxtoolbox.com/mta-sts.aspx

Step 2: Expected Validation Results

Success indicators:

  • “Record is valid”
  • “MTA-STS policy is published and served”
  • “Certificate is valid”
  • Mode shows “enforce”
  • MX records listed correctly

Failure indicators requiring fixes:

  • “MTA-STS DNS record not found” (usually DNS formatting issue)
  • “Policy file not accessible” (HTTPS/certificate issue)
  • “MX mismatch” (policy doesn’t match actual MX records)

Phase 5: RSPAMD Configuration (Optional)

RSPAMD 3.4 doesn’t have native MTA-STS modules, but you can add domain tracking.

Step 1: Create Multimap Configuration

/etc/rspamd/local.d/multimap.conf:

1
2
3
4
5
6
7
8
# MTA-STS domain tracking (optional)
MTA_STS_DOMAINS {
  type = "from";
  map = "/etc/rspamd/mta_sts_domains.map";
  description = "Domains with MTA-STS policies";
  score = 0.0;
  action = "no action";
}

Step 2: Create Domain Map

/etc/rspamd/mta_sts_domains.map:

1
2
yourdomain.com MTA_STS
anotherdomain.com MTA_STS

Step 3: Test and Restart

1
2
rspamadm configtest
systemctl restart rspamd

Look for MTA_STS(1.00){yourdomain.com;} in RSPAMD logs.

Phase 6: TLS Reporting Setup

Step 1: Create Report Email Addresses

Ensure these email addresses work:

  • tls-reports@yourdomain.com
  • tls-reports@anotherdomain.com

Step 2: Add TLS-RPT DNS Records

_smtp._tls.yourdomain.com. IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@yourdomain.com"
_smtp._tls.anotherdomain.com. IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@anotherdomain.com"

Step 3: Verify TLS-RPT Records

1
2
dig TXT _smtp._tls.yourdomain.com +short
dig TXT _smtp._tls.anotherdomain.com +short

Should return: "v=TLSRPTv1; rua=mailto:tls-reports@yourdomain.com"

Phase 7: Testing and Monitoring

Step 1: Send Test Emails

Send emails from external providers (Gmail, Outlook, Yahoo) to your domains.

Step 2: Monitor Logs

Postfix logs (successful TLS):

1
journalctl -u postfix | grep -i tls

Look for: TLS connection established to...

RSPAMD logs (MTA-STS detection):

1
tail -f /var/log/rspamd/rspamd.log | grep MTA_STS

Look for: MTA_STS(1.00){yourdomain.com;}

Apache logs (policy fetches):

1
tail -f /var/log/apache2/mta-sts.yourdomain.com_access.log

Look for external IPs (not your server IP) fetching mta-sts.txt

Step 3: What to Expect

Immediate (after DNS propagation):

  • External validators pass
  • Internal email delivery works
  • TLS connections show in logs

Within 24-48 hours:

  • External servers fetch your policy files
  • TLS reports start arriving (JSON attachments)
  • Policy enforcement visible in reports

Major Troubleshooting Scenarios

Issue 1: External Validator Says “DNS Record Not Found”

Symptoms:

  • Your dig commands work fine
  • External validators fail
  • No external policy fetches in Apache logs

Cause: DNS record has escaped quotes

Diagnosis:

1
dig TXT _mta-sts.yourdomain.com +short

Problem if you see: "\"v=STSv1; id=20250809\"" Should be: "v=STSv1; id=20250809"

Solution: Fix DNS record formatting in your DNS provider interface.

Issue 2: Postfix SMTP Errors

Symptoms:

1
2
error: open database /etc/postfix/tls_policy.db: No such file or directory
fatal: need service transport:endpoint instead of "unix"

Cause: Incorrect smtp_tls_policy_maps configuration

Solution:

1
2
3
# Remove the problematic line
sed -i 's/smtp_tls_policy_maps.*$/# smtp_tls_policy_maps removed/' /etc/postfix/main.cf
postfix reload

Issue 3: MX Record Mismatch

Symptoms:

  • External validators show MX mismatch errors
  • Email delivery failures
  • Policy shows different MX than DNS

Diagnosis:

1
2
3
4
5
# Check actual MX records
dig MX yourdomain.com +short

# Compare with policy file
cat /var/www/mta-sts.yourdomain.com/.well-known/mta-sts.txt

Solution: Update policy file to include ALL MX records exactly as they appear in DNS.

Issue 4: No External Policy Fetches

Symptoms:

  • Only your server IP appears in Apache logs
  • No external servers fetching mta-sts.txt

Common Causes:

  1. DNS formatting issue (see Issue 1)
  2. Providers cached negative results before your setup
  3. No external email traffic to trigger fetches

Solutions:

  1. Fix DNS formatting
  2. Change DNS id parameter to force refresh
  3. Send test emails from multiple external providers

Issue 5: RSPAMD Configuration Errors

Symptoms:

1
configtest: syntax error

Cause: Using non-existent RSPAMD modules

Solution:

1
2
3
4
5
6
# Remove these files if they exist
rm /etc/rspamd/local.d/mta_sts.conf 2>/dev/null
rm /etc/rspamd/local.d/tls_rpt.conf 2>/dev/null

# Only use multimap.conf
rspamadm configtest

Issue 6: Certificate Problems

Symptoms:

  • Policy file accessible via HTTP but not HTTPS
  • Certificate warnings in external validators

Diagnosis:

1
curl -v https://mta-sts.yourdomain.com/.well-known/mta-sts.txt 2>&1 | grep -E "(certificate|verify)"

Solution: Ensure valid SSL certificates for mta-sts.* subdomains.

Advanced Configuration

Testing Mode vs Enforce Mode

For initial testing:

1
2
3
4
version: STSv1
mode: testing
mx: mail.yourdomain.com
max_age: 86400

For production:

1
2
3
4
version: STSv1
mode: enforce
mx: mail.yourdomain.com
max_age: 86400

Testing mode logs violations but allows delivery. Enforce mode rejects non-compliant delivery attempts.

Force Policy Refresh

To force external servers to re-fetch your policy:

  1. Update policy file content
  2. Change DNS id parameter:
    _mta-sts.yourdomain.com. IN TXT "v=STSv1; id=20250809-2"
    
  3. Wait for DNS propagation
  4. External servers will fetch fresh policy

Multiple Domain Considerations

If multiple domains use the same mail server:

  • Each domain needs its own MTA-STS subdomain and certificate
  • Each domain needs its own policy file
  • Policy files can reference the same MX servers
  • DNS records must be added for each domain

Success Verification Checklist

DNS and Web Infrastructure

  • DNS records return correct format (no escaped quotes)
  • Policy files accessible via HTTPS with valid certificates
  • External validators pass for all domains
  • MX records exactly match policy statements

Mail Server Function

  • Postfix TLS working (verify return code: 0)
  • No smtp_tls_policy_maps errors in logs
  • RSPAMD configtest passes
  • Test emails deliver successfully

External Validation

  • All domains pass external MTA-STS validators
  • TLS-RPT records properly formatted
  • No DNS formatting warnings

Monitoring

  • Apache logs show external policy fetches
  • RSPAMD logs show MTA-STS domain detection
  • TLS reports arriving with successful session counts

Long-term Maintenance

Regular Tasks

  • Monitor TLS reports for delivery issues
  • Check certificate expiration for mta-sts subdomains
  • Update DNS id when changing policies
  • Review Apache logs for unusual access patterns

Policy Updates

  1. Update policy file content
  2. Change DNS id parameter
  3. Test with external validators
  4. Monitor for external fetches of new policy

Certificate Renewal

Ensure your certificate renewal process includes MTA-STS subdomains:

1
2
# Include in Let's Encrypt renewal
certbot certonly --apache -d mta-sts.yourdomain.com

Conclusion

This guide provides real-world tested MTA-STS implementation with RSPAMD 3.4. The key lessons learned:

  1. External validation is critical - internal tests miss DNS formatting issues
  2. DNS record formatting must be exact - escaped quotes break external discovery
  3. MX record matching is essential - policy must exactly match DNS MX records
  4. RSPAMD 3.4 limitations - use multimap for tracking, avoid non-existent modules
  5. TLS reporting provides visibility - essential for monitoring enforcement

Your email infrastructure now enforces TLS encryption for all inbound mail, meeting modern security standards and protecting against man-in-the-middle attacks.

This post is licensed under CC BY 4.0 by the author.