Table of Contents

  1. Introduction
  2. Understanding Modern Email Attacks
  3. Initial iRedMail Security Review
  4. Postfix Hardening
  5. Dovecot Security
  6. Firewall Strategy
  7. Advanced Fail2Ban Configuration
  8. Automated Subnet Blocking for Mail Services
  9. Roundcube Webmail Security
  10. Monitoring and Alerting
  11. Incident Response
  12. Conclusion

Introduction

Email servers are prime targets for attackers. This guide focuses on securing iRedMail, a popular open-source mail server solution, against distributed brute force attacks, pre-greet attacks, and automated scanning.

What You’ll Learn:

  • Identifying various attack patterns
  • Postfix postscreen configuration
  • Automated subnet-level blocking
  • Monitoring mail server security
  • Incident response procedures

Understanding Modern Email Attacks

Types of Attacks We Mitigated

Attack TypePatternImpact
SSH Brute ForceMultiple usernames from rotating IPsServer resource exhaustion
Postfix Pre-greetData sent before SMTP greetingBypasses some filters
Distributed ScanningIP rotation across /24 subnetsEvades single IP bans
SMTP AUTH BrutePassword guessing on submission portsAccount compromise

Real Attack Example

From our logs:

Jun 2 22:56:58 mail postfix/postscreen: PREGREET from [34.77.183.53]
Jun 2 22:56:59 mail postfix/postscreen: PREGREET from [34.77.183.53]
Jun 2 22:56:59 mail postfix/postscreen: PREGREET from [34.77.183.53]

This attacker sent data before the SMTP greeting, attempting to exploit vulnerabilities.


Initial iRedMail Security Review

Check iRedMail Version

# Check iRedMail version
cat /etc/iredmail-release

# Check installed packages
rpm -qa | grep -E "postfix|dovecot|mysql|php"

Review Default Configuration

# Check all running mail services
sudo netstat -tlnp | grep -E ":25|:465|:587|:993|:995|:143|:110"

# Expected ports:
# 25 - SMTP
# 465 - SMTPS
# 587 - Submission
# 993 - IMAPS
# 995 - POP3S
# 143 - IMAP (should be disabled)
# 110 - POP3 (should be disabled)

Disable Unencrypted Protocols

Edit /etc/dovecot/dovecot.conf:

# Disable plain text protocols
protocols = imaps pop3s
# Remove imap and pop3 from list

Edit /etc/postfix/master.cf:

# Comment out plain SMTP if not needed
# -o smtpd_tls_wrappermode=no

Postfix Hardening

Postscreen Configuration

Edit /etc/postfix/main.cf:

# Enable postscreen
postscreen_enable = yes
postscreen_bare_newline_enable = no
postscreen_bare_newline_action = drop
postscreen_non_smtp_command_enable = yes
postscreen_non_smtp_command_action = drop
postscreen_pipelining_enable = yes
postscreen_pipelining_action = drop

# DNS Blocklists
postscreen_dnsbl_sites = zen.spamhaus.org*2, b.barracudacentral.org*2
postscreen_dnsbl_threshold = 2
postscreen_dnsbl_action = drop

# Pre-greet detection
postscreen_greet_wait = 6s
postscreen_greet_banner = $smtpd_banner
postscreen_pregreet_ttl = 30d

SMTP Authentication Hardening

# Limit authentication attempts
smtpd_client_connection_rate_limit = 10
smtpd_client_message_rate_limit = 20
smtpd_client_recipient_rate_limit = 20

# Timeouts
smtpd_helo_required = yes
smtpd_helo_timeout = 5s
smtpd_recipient_limit = 100

Header and Body Checks

# Create header check file
sudo nano /etc/postfix/header_checks

# Add these rules
/^Subject:.*Re:.*Re:.*Re:/ DISCARD
/^Content-Type:.*multipart\/mixed.*name=".*\.(exe|scr|bat|cmd|com|pif)"$/ DISCARD

# Apply in main.cf
header_checks = regexp:/etc/postfix/header_checks

Dovecot Security

Authentication Limits

Edit /etc/dovecot/conf.d/10-auth.conf:

# Limit authentication attempts
auth_failure_delay = 2 secs
auth_username_format = %Lu

# Disable plain auth over insecure connections
disable_plaintext_auth = yes

# Set max authentication attempts
mail_max_userip_connections = 10

SSL/TLS Hardening

Edit /etc/dovecot/conf.d/10-ssl.conf:

ssl = required
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl_prefer_server_ciphers = yes

Connection Limits

# Edit /etc/dovecot/conf.d/20-imap.conf
mail_max_userip_connections = 10

# Edit /etc/dovecot/conf.d/20-pop3.conf
mail_max_userip_connections = 5

Firewall Strategy

Basic Mail Server Firewall

# Create dedicated zone
sudo firewall-cmd --permanent --new-zone=mail
sudo firewall-cmd --permanent --zone=mail --add-interface=eth0

# Allow mail ports
sudo firewall-cmd --permanent --zone=mail --add-port=25/tcp
sudo firewall-cmd --permanent --zone=mail --add-port=465/tcp
sudo firewall-cmd --permanent --zone=mail --add-port=587/tcp
sudo firewall-cmd --permanent --zone=mail --add-port=993/tcp
sudo firewall-cmd --permanent --zone=mail --add-port=995/tcp

# Allow SSH (admin access)
sudo firewall-cmd --permanent --zone=mail --add-service=ssh

# Limit connection rates
sudo firewall-cmd --permanent --zone=mail --add-rich-rule='rule service name="smtp" limit value="10/m" accept'

sudo firewall-cmd --reload

Blocking Abusive Subnets

# Block entire /24 subnet after detecting multiple attacks
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="34.77.183.0/24" drop'
sudo firewall-cmd --reload

Advanced Fail2Ban Configuration

iRedMail-Specific Jails

iRedMail creates several jails automatically. Check them:

sudo fail2ban-client status
# Typical iRedMail jails:
# - postfix
# - postfix-burst
# - pregreet
# - dovecot
# - roundcube
# - recidive

Configure Postfix Jail

Edit /etc/fail2ban/jail.d/iredmail.conf:

[postfix]
enabled = true
maxretry = 3
findtime = 600
bantime = 3600

[postfix-burst]
enabled = true
maxretry = 10
findtime = 60
bantime = 3600

[pregreet]
enabled = true
maxretry = 2
findtime = 60
bantime = 7200

Recidive Jail for Persistent Offenders

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime = 86400  # 24 hours
maxretry = 3
findtime = 86400

Automated Subnet Blocking for Mail Services

The Challenge

Attackers use multiple IPs from the same /24 subnet to avoid traditional bans. Our solution blocks entire subnets automatically.

Postfix Auto-Block Script

Create /usr/local/bin/auto-block-postfix.sh:

#!/bin/bash
THRESHOLD=3  # Block after 3 IPs from same /24
LOG_FILE="/var/log/auto-block-postfix.log"

# Whitelist legitimate email providers (add as needed)
WHITELIST="52.101|40.107|209.85|147.75.180"

# Get banned IPs from mail-related jails
BANNED_IPS=$(sudo fail2ban-client status postfix pregreet 2>/dev/null | \
    grep -A1 "Banned IP list" | tail -1 | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u)

# Also check recidive
BANNED_IPS="$BANNED_IPS"$'\n'$(sudo fail2ban-client status recidive 2>/dev/null | \
    grep -A1 "Banned IP list" | tail -1 | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")

# Process each subnet
echo "$BANNED_IPS" | grep -v '^$' | cut -d. -f1-3 | sort | uniq -c | while read count subnet; do
    [ -z "$subnet" ] && continue
    
    # Skip whitelisted providers
    if echo "$subnet" | grep -qE "$WHITELIST"; then
        echo "$(date): Skipping whitelisted $subnet.0/24" >> $LOG_FILE
        continue
    fi
    
    if [ $count -ge $THRESHOLD ]; then
        if ! sudo firewall-cmd --list-rich-rules | grep -q "$subnet.0/24"; then
            echo "$(date): Blocking $subnet.0/24 (detected $count IPs)" | tee -a $LOG_FILE
            sudo firewall-cmd --permanent --add-rich-rule="rule family=\"ipv4\" source address=\"$subnet.0/24\" drop"
            sudo firewall-cmd --reload
            
            # Clean up individual bans
            echo "$BANNED_IPS" | grep "$subnet." | while read ip; do
                sudo fail2ban-client unban $ip 2>/dev/null
            done
        fi
    fi
done

Set Up Cron Jobs

# Run every minute
sudo crontab -e
# Add:
* * * * * /usr/local/bin/auto-block-postfix.sh
* * * * * sleep 30; /usr/local/bin/auto-block-postfix.sh

Monitoring the Auto-Block Script

bash

# View blocks
sudo tail -f /var/log/auto-block-postfix.log

# Check current firewall blocks
sudo firewall-cmd --list-rich-rules | grep drop

Roundcube Webmail Security

Secure Roundcube Configuration

Edit /var/www/roundcubemail/config/config.inc.php:

// Security settings
$config['session_lifetime'] = 30;
$config['session_domain'] = '.yourdomain.com';
$config['session_name'] = 'roundcube_session';
$config['cookie_secure'] = true;
$config['cookie_httponly'] = true;
$config['cookie_samesite'] = 'Strict';

// Login attempts
$config['login_rate_limit'] = 3;
$config['login_rate_time'] = 5;

// Disable dangerous features
$config['enable_installer'] = false;
$config['enable_spellcheck'] = false;

.htaccess for Roundcube

Create /var/www/roundcubemail/.htaccess:

# Deny access to sensitive files
<FilesMatch "^(config|temp|logs|SQL)">
    Order allow,deny
    Deny from all
</FilesMatch>

# Limit login attempts
<Limit POST>
    Order deny,allow
    deny from all
    allow from all
</Limit>

Protect admin interface

# Add password protection to /admin
sudo htpasswd -c /etc/roundcube/admin.htpasswd admin

# Add to Apache config
<Directory /var/www/roundcubemail/admin>
    AuthType Basic
    AuthName "Admin Access"
    AuthUserFile /etc/roundcube/admin.htpasswd
    Require valid-user
</Directory>

Monitoring and Alerting

Security Status Script

Create /usr/local/bin/mail-security-status.sh:

#!/bin/bash
echo "=========================================="
echo "MAIL SERVER SECURITY STATUS"
echo "Host: $(hostname)"
echo "Time: $(date)"
echo "=========================================="
echo ""

echo "=== FIREWALL ==="
TOTAL=$(sudo firewall-cmd --list-rich-rules 2>/dev/null | grep -c "source address")
echo "Total blocked subnets: $TOTAL"
echo ""

echo "=== FAIL2BAN ==="
sudo fail2ban-client status | grep "Jail list" | sed 's/.*Jail list://' | tr ',' '\n' | while read jail; do
    BANS=$(sudo fail2ban-client status "$jail" 2>/dev/null | grep -c "Banned IP list" -A1 | tail -1 | grep -oE "[0-9]+" | head -1)
    echo "  $jail: $BANS bans"
done
echo ""

echo "=== RECENT ATTACKS ==="
echo "Postfix pregreet (last hour): $(sudo journalctl -u postfix --since '1 hour ago' 2>/dev/null | grep -c 'PREGREET')"
echo "Failed SASL auth (last hour): $(sudo journalctl -u postfix --since '1 hour ago' 2>/dev/null | grep -c 'SASL LOGIN authentication failed')"
echo ""

echo "=== AUTO-BLOCK LOGS ==="
echo "Last 3 blocks:"
sudo tail -3 /var/log/auto-block-postfix.log 2>/dev/null
echo ""

echo "=========================================="

Email Alerts

# Add to crontab for hourly reports
0 * * * * /usr/local/bin/mail-security-status.sh | mail -s "Hourly Mail Security Report" admin@example.com

Centralized Logging (ELK Stack)

# Install Filebeat
sudo dnf install filebeat -y

# Configure to send to ELK
sudo nano /etc/filebeat/filebeat.yml
# Add postfix, dovecot, fail2ban logs

sudo systemctl enable --now filebeat

Incident Response

When You Detect an Attack

1. Identify the Attack Pattern

# Check recent attacks
sudo journalctl -u postfix --since "10 minutes ago" | grep -E "CONNECT from|PREGREET"

# Identify attacking subnets
sudo journalctl -u postfix --since "1 hour ago" | grep -oE "from \[([0-9]+\.){3}[0-9]+\]" | \
    cut -d'[' -f2 | cut -d']' -f1 | cut -d. -f1-3 | sort | uniq -c | sort -rn | head -20

2. Block Immediately

# Manual block of attacking subnet
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="ATTACKING_SUBNET.0/24" drop'
sudo firewall-cmd --reload

3. Clear Bans

# Unban all IPs from attacking subnet
sudo fail2ban-client status postfix | grep -o "XX\.XX\.XX\.[0-9]*" | while read ip; do
    sudo fail2ban-client unban $ip
done

4. Report Abuse

# Template for abuse report
cat << EOF | mail -s "Abuse report from your IP range" abuse@provider.com
Dear Provider,

Your IP range is being used to attack our mail server.

Attacking IPs: [LIST]
Time: [TIME]
Attack type: [TYPE]

Log samples:
[SAMPLES]

Please investigate.

Regards,
[Your Name]
EOF

Post-Incident Analysis

# Generate attack report
sudo journalctl -u postfix --since "24 hours ago" | \
    grep -E "PREGREET|authentication failed" > /tmp/attack-report.txt

# Count unique attacking IPs
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" /tmp/attack-report.txt | sort -u | wc -l

Conclusion

Your iRedMail server is now hardened with:

  • ✅ Postfix postscreen with DNSBL
  • ✅ Dovecot authentication limits
  • ✅ Automated subnet blocking for distributed attacks
  • ✅ Roundcube webmail security
  • ✅ Comprehensive monitoring and alerting
  • ✅ Incident response procedures

Blocked Subnets Summary

After implementing this guide, your server should have blocked:

  • 50+ malicious subnets
  • Thousands of attacking IPs
  • Multiple hosting providers (Google Cloud, Hetzner, DigitalOcean, etc.)

Final Security Checklist

  • SSH key-only authentication
  • Firewall rate limiting
  • Fail2Ban with recidive jail
  • Auto-block scripts running via cron
  • Whitelist for legitimate email providers
  • Monitoring and alerts configured
  • Backup strategy in place
  • Incident response plan documented

Resources


Questions about implementing this guide? Leave a comment below or contact our security team.