Mail Server Nachbau

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

Mailserver Nachbau: Postfix + Dovecot + Rspamd (it213.int)

Überblick

Diese Anleitung baut den kompletten Mailserver-Stack nach: Postfix (SMTP) → Dovecot (IMAP/LMTP/Sieve) → Rspamd (Spam-Scoring, DKIM, Bayes-Lernen, Blacklists). Jede Datei ist komplett und copy-paste-fertig für die Domain it213.int, Host mail.it213.int.

ℹ️ Hinweis: Alle Dateien liegen auch fertig gepackt als mailconfig-it213.tar.gz vor, inkl. deploy.sh zum automatischen Ausrollen. Diese Anleitung zeigt dieselben Dateien einzeln mit Erklärung, für den Fall dass man Schritt für Schritt nachbauen statt nur ausrollen will.

Komponente Aufgabe Port(e)
Postfix SMTP-Empfang/-Versand, übergibt an Rspamd (Milter) und Dovecot (LMTP) 25, 465, 587
Dovecot IMAP-Zustellung, Mailbox-Speicherung, Sieve-Filter 143, 993, LMTP (Unix-Socket)
Rspamd Spam-Scoring, DKIM-Signing, Bayes-Klassifikation, Blacklists 11332 (Milter), 11334 (Controller)
Redis Backend für Rspamd Bayes-Statistik 6379

1. Postfix installieren

  • apt install postfix

Bei der Installation: "Internet Site" wählen, Mailname = it213.int.

Datei: /etc/postfix/main.cf

Komplett, so einfügen:

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 3.6

myhostname = mail.it213.int
mydestination = $myhostname, mail.it213.int, localhost.it213.int, it213.int, localhost
myorigin = /etc/mailname
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
inet_interfaces = all
inet_protocols = all

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

home_mailbox = Maildir/
mailbox_command =
recipient_delimiter = +
message_size_limit = 31457280
mailbox_size_limit = 0
virtual_mailbox_limit = 31457280

relayhost =

smtpd_tls_cert_file = /etc/ssl/own.crt
smtpd_tls_key_file  = /etc/ssl/own.key
smtpd_tls_security_level = may
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

virtual_alias_maps = hash:/etc/postfix/virtual

smtpd_milters = inet:127.0.0.1:11332
non_smtpd_milters = inet:127.0.0.1:11332
milter_default_action = accept
milter_protocol = 6

mailbox_transport = lmtp:unix:private/dovecot-lmtp
virtual_transport = lmtp:unix:private/dovecot-lmtp

⚠️ Achtung: smtpd_tls_cert_file/_key_file zeigen hier auf /etc/ssl/own.crt/own.key – eigenes Zertifikat vorher dort ablegen (oder Let's Encrypt nutzen und Pfad anpassen). Ohne gültiges Cert startet Postfix zwar, aber TLS funktioniert nicht richtig.

⚠️ Achtung: smtpd_relay_restrictions ist zwingend korrekt zu setzen – ohne diese Zeile oder in falscher Reihenfolge läuft der Server als offenes Relay.

Datei: /etc/postfix/master.cf

Komplett, ersetzt die Standarddatei:

#
# Postfix master process configuration file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no

smtps     inet  n       -       y       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_milters=inet:127.0.0.1:11332

pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd

maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}

uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)

ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}

ℹ️ Hinweis: {{{1}}}

Test Postfix

  • postfix check
  • systemctl restart postfix
  • systemctl status postfix

2. Dovecot installieren

  • apt install dovecot-imapd dovecot-lmtpd dovecot-sieve

Datei: /etc/dovecot/conf.d/10-master.conf

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

service imap {
}

service pop3 {
}

service auth {
  unix_listener auth-userdb {
  }

  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
}

service dict {
  unix_listener dict {
  }
}

ℹ️ Hinweis: Die beiden unix_listener-Blöcke unter service lmtp und service auth sind die Kopplung zu Postfix – ohne die kann Postfix weder Mails an Dovecot übergeben noch SASL-Auth durchführen. mode/user/group müssen exakt so gesetzt sein, sonst Permission-Fehler.

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

disable_plaintext_auth = no
auth_username_format = %n
auth_mechanisms = plain
!include auth-system.conf.ext

⚠️ Achtung: {{{1}}}

Datei: /etc/dovecot/conf.d/20-lmtp.conf

protocol lmtp {
  mail_plugins = $mail_plugins sieve
}

Datei: /etc/dovecot/conf.d/20-imap.conf

protocol imap {
  mail_plugins = $mail_plugins imap_sieve
}

Datei: /etc/dovecot/conf.d/15-mailboxes.conf

namespace inbox {
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
}

Test Dovecot

  • doveconf -n
  • systemctl restart dovecot
  • openssl s_client -connect 127.0.0.1:993 -quiet

Erwartete Antwort: * OK [CAPABILITY IMAP4rev1 ...] Dovecot ready.


3. Sieve: Spam automatisch einsortieren

Datei: /var/lib/dovecot/sieve/spam-to-junk.sieve

require ["fileinto"];
if header :contains "X-Spam" "Yes" {
    fileinto "INBOX.Junk";
    stop;
}
  • mkdir -p /var/lib/dovecot/sieve
  • sievec /var/lib/dovecot/sieve/spam-to-junk.sieve

4. IMAPSieve: automatisches Bayes-Lernen

Wenn eine Mail manuell nach Junk verschoben wird (oder raus), soll Rspamd automatisch daraus lernen.

Datei: /etc/dovecot/sieve/learn-spam.sieve

require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];

if environment :matches "imap.mailbox" "*" {
    set "mailbox" "${1}";
}

if string "${mailbox}" "Trash" {
    stop;
}

pipe :copy "rspamd-learn-spam.sh";

Datei: /etc/dovecot/sieve/learn-ham.sieve

require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];

if environment :matches "imap.mailbox" "*" {
    set "mailbox" "${1}";
}

if string "${mailbox}" "Junk" {
    stop;
}

pipe :copy "rspamd-learn-ham.sh";
  • mkdir -p /etc/dovecot/sieve
  • sievec /etc/dovecot/sieve/learn-spam.sieve
  • sievec /etc/dovecot/sieve/learn-ham.sieve

Datei: /etc/dovecot/sieve-pipe/rspamd-learn-spam.sh

#!/bin/bash
exec /usr/bin/rspamc learn_spam

Datei: /etc/dovecot/sieve-pipe/rspamd-learn-ham.sh

#!/bin/bash
exec /usr/bin/rspamc learn_ham
  • mkdir -p /etc/dovecot/sieve-pipe
  • chmod +x /etc/dovecot/sieve-pipe/*.sh

Datei: /etc/dovecot/conf.d/90-sieve.conf

plugin {
    sieve = ~/.dovecot.sieve
    sieve_before = /var/lib/dovecot/sieve/spam-to-junk.sieve
    sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
    sieve_plugins = sieve_imapsieve sieve_extprograms
    sieve_pipe_bin_dir = /etc/dovecot/sieve-pipe

    imapsieve_mailbox1_name = INBOX.Junk
    imapsieve_mailbox1_causes = COPY
    imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve

    imapsieve_mailbox2_name = *
    imapsieve_mailbox2_from = INBOX.Junk
    imapsieve_mailbox2_causes = COPY
    imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve
}

⚠️ Achtung: imapsieve_mailbox1_name/_from müssen INBOX.Junk heißen (mit Präfix), nicht nur Junk – auch wenn doveconf -n einen leeren prefix-Wert zeigt. Das ist der interne Name, den Dovecot beim Maildir++-Layout verwendet. Falscher Name ist die häufigste Ursache, dass die Regel nie feuert, ohne Fehlermeldung im Log. Zur Diagnose: journalctl -u dovecot -f

Test Lernen

Mail in Roundcube nach Junk verschieben, dann:

  • rspamc stat | grep -i bayes

learned bei BAYES_SPAM muss um 1 steigen. Rückweg (Junk → Inbox) für BAYES_HAM entsprechend testen.


5. Rspamd installieren

  • apt install rspamd redis-server

Datei: /etc/rspamd/local.d/redis.conf

servers = "127.0.0.1:6379";
timeout = 1s;

Datei: /etc/rspamd/local.d/classifier-bayes.conf

backend = "redis";
new_schema = true;
expire = 8640000;

autolearn {
  spam_threshold = 12.0;
  ham_threshold = -2.0;
  check_balance = true;
}

Datei: /etc/rspamd/local.d/actions.conf

reject = 15;
greylist = 4;
add_header = 6;

ℹ️ Hinweis: Diese Werte legen fest, ab welchem Spam-Score was passiert. greylist niedrig, add_header mittel, reject hoch – bewusst wählen, nicht auf 999 setzen, sonst ist die Aktion faktisch deaktiviert.

Datei: /etc/rspamd/local.d/worker-proxy.inc

milter = yes;
timeout = 120s;
upstream "local" {
  default = yes;
  self_scan = yes;
}

Datei: /etc/rspamd/local.d/milter_headers.conf

use = ["x-spamd-bar", "x-spam-level", "x-spam-status", "authentication-results"];

Datei: /etc/rspamd/override.d/worker-controller.inc

Passwort-Hash vorher erzeugen:

  • rspamadm pw
password = "HASH_HIER_EINFÜGEN";
enable_password = "HASH_HIER_EINFÜGEN";
bind_socket = [
    "localhost:11334",
    "/run/rspamd/controller.sock mode=0660"
];

Test Rspamd

  • systemctl restart rspamd
  • rspamc stat

6. DKIM-Signing

Key erzeugen:

  • rspamadm dkim_keygen -b 2048 -s dkim -d it213.int -k /var/lib/rspamd/dkim/it213.int.dkim.key

Die Ausgabe ist der DNS-TXT-Record für dkim._domainkey.it213.int – bei eurem DNS-Provider eintragen.

Rechte setzen:

  • chown _rspamd:_rspamd /var/lib/rspamd/dkim/it213.int.dkim.key
  • chmod 600 /var/lib/rspamd/dkim/it213.int.dkim.key

Datei: /etc/rspamd/local.d/dkim_signing.conf

domain {
  it213.int {
    selectors [
      {
        path = "/var/lib/rspamd/dkim/it213.int.dkim.key";
        selector = "dkim";
      }
    ]
  }
}

Test DKIM

  • systemctl reload rspamd
  • echo -e "From: test@it213.int\nTo: test@example.com\nSubject: Test\n\nBody" | rspamc symbols

Symbol DKIM_SIGNED muss im Output erscheinen.


7. Blacklist / Whitelist

Datei: /etc/rspamd/local.d/modules.conf

multimap {
  enabled = true;
}

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

WHITELIST_SENDER_DOMAIN {
    type = "from";
    filter = "email:domain";
    map = "/etc/rspamd/local.d/lists/whitelist.sender.domain.map";
    action = "accept";
    symbol = "WHITELISTED_DOMAIN";
}

WHITELIST_SENDER_EMAIL {
    type = "from";
    map = "/etc/rspamd/local.d/lists/whitelist.sender.email.map";
    action = "accept";
    symbol = "WHITELISTED_ADDRESS";
}

BLACKLIST_SENDER_DOMAIN {
    type = "from";
    filter = "email:domain";
    map = "/etc/rspamd/local.d/lists/blacklist.sender.domain.map";
    action = "reject";
    symbol = "BLACKLISTED_DOMAIN";
}

BLACKLIST_SENDER_EMAIL {
    type = "header";
    header = "From";
    filter = "email";
    map = "/etc/rspamd/local.d/lists/blacklist.sender.email.map";
    action = "reject";
    symbol = "BLACKLISTED_ADDRESS";
    regexp = false;
}

BLOCKLIST_IP {
    type = "ip";
    map = "/etc/rspamd/local.d/lists/blockip.map";
    prefilter = true;
    action = "reject";
    symbol = "BLOCKLIST_IP";
}

ALLOWLIST_IP {
    type = "ip";
    map = "/etc/rspamd/local.d/lists/allowip.map";
    prefilter = true;
    action = "accept";
    symbol = "ALLOWLIST_IP";
}

Maps anlegen (eine Adresse/Domain/IP pro Zeile):

  • mkdir -p /etc/rspamd/local.d/lists
  • touch /etc/rspamd/local.d/lists/{whitelist.sender.domain.map,whitelist.sender.email.map,blacklist.sender.domain.map,blacklist.sender.email.map,blockip.map,allowip.map}

8. Virenscanner (ClamAV)

⚠️ Achtung: Neuaufbau, kein dokumentierter Ist-Zustand einer laufenden Referenz. Vor Produktiveinsatz selbst durchtesten.

  • apt install clamav-daemon
  • systemctl enable --now clamav-daemon
  • freshclam

Datei: /etc/rspamd/local.d/antivirus.conf

clamav {
  action = "reject";
  symbol = "CLAM_VIRUS";
  type = "clamav";
  servers = "/var/run/clamav/clamd.ctl";
}

Test

Symbol CLAM_VIRUS muss erscheinen.


9. End-to-End-Verifikation

Funktion Testbefehl Erwartetes Ergebnis
Postfix läuft systemctl status postfix active (running)
Dovecot läuft systemctl status dovecot active (running)
TLS-Cert korrekt openssl s_client -connect mail.it213.int:993 richtiges Cert
Rspamd scannt rspamc stat Scanned-Counter > 0
DKIM signiert rspamc symbols (Testmail) Symbol DKIM_SIGNED
Bayes lernt (Spam) Mail nach Junk verschieben, rspamc stat BAYES_SPAM learned +1
Bayes lernt (Ham) Mail aus Junk raus, rspamc stat BAYES_HAM learned +1
ClamAV aktiv EICAR-Test Symbol CLAM_VIRUS
Blacklist wirkt Testmail von geblockter Domain/IP Reject bzw. BLACKLISTED_*-Symbol

ℹ️ Hinweis: Checkliste eignet sich auch zur Wiederholung nach Updates/Config-Änderungen, um schnell zu sehen was kaputtgegangen ist.