Mailserver

Mailserver gehören im allgemein zu den lästigsten Pflichten eines sysadmins – Man ist einfach froh, wenn er läuft und man möglichst nichts daran herum schrauben muss.

Wie auch immer, wir werden hier einen Hosting-Tauglichen Mailserver mit postfix, dovecot, mysql, amavisd-new, clamav und spamassassin auf der Basis von CentOS/RHEL aufsetzen.

Als Sahnehäubchen werden wir zuletzt noch mailgraph installieren um eine Grafische Auswertung über die versendeten Mails zu bekommen.

Vorwort

Meine ersten versuche mit Linux Mailservern hatte ich so anno 2005 gemacht, damals noch mit qmail, welches aber heute hoffnungslos veraltet und auch sehr mühsam zu erweitern ist.

Also stiess ich wenig später zu exim, da dieser auf meinem damals eingesetzten Debian-Server sehr verbreitet war – Die Konfiguration war dann aber doch sehr unübersichtlich, ich traute mich praktisch nichts daran an zufassen. So lief dann der exim Server mal recht mal schlecht, ganz zufrieden war ich jedoch nicht.

Dann arbeitete ich über zwei Jahre unter anderem als Postmaster für eine postfix-Installation, erst unter gentoo mit courier, dann unter CentOS mit Dovecot – Und dies entsprach mir dann voll und ganz! -Endlich ein Mailserver, der übersichtlich aufgebaut ist und einem die noch immer mühsame Administration zumindest erleichtert.
Und mittlerweile ist postfix ja auch klar die Nr.1 unter den Mailservern, wohingegen exim immer mehr ein Schattendasein fristet.

Installation

Als erstes müssen natürlich die erforderlichen Pakete installiert werden:

yum install postfix dovecot dovecot-mysql dovecot-pigeonhole amavisd-new spamassassin clamav clamd mysql mysql-server mailgraph telnet

Nun legen wir den Benutzer für die virtuellen Mail-Konten (vmail) an:

groupadd -g 1025 vmail
useradd  -u 1025 -g mail -G vmail -d /srv/mail vmail
chmod -v 750 /srv/mail

Merkt euch nun die UID vom user vmail, so wie die GID der Gruppe: mail.
Bei mir entspricht zum Beispiel vmail:mail immer 1025:1025 – Bitte beachten, dass ihr diese immer mit euren Werten ersetzt! (Tip: Ist unter /etc/passwd die UID 1025, bzw. unter /etc/group die GID 1025 noch frei, setze diese am besten auf diese Werte um Tippfehler beim copy&pasten zu vermeiden… 😉 )

Und natürlich musst du „example.com“ jeweils mit dem (Haupt-)Domainnamen deines Mailservers ersetzen.

Konfiguration

postfix

Bei den beiden postfix-Konfigurationsdateien /etc/postfix/main.cf und /etc/postfix/master.cf kann das meiste beim Standard belassen werden, folgende Zeilen müssen jedoch ersetzt/geändert werden:

/etc/postfix/main.cf

Die Direktiven home_mailbox und mailbox_command jeweils wie folgt setzen:

inet_interfaces = all
mynetworks = 
home_mailbox = Maildir/
mailbox_transport = dovecot
mailbox_command = /usr/libexec/dovecot/deliver
message_size_limit = 20480000

Die Standardmässige message_size_limit ist mit 10 MB etwas knapp für heutige Verhältnisse. Deshalb sollte man diese gleich auf 20 MB setzen. Die meisten grösseren E-Mail Provider haben das Limit zwischen 20- und 25 MB gesetzt.

Kleiner Exkurs- Der Parameter myhostname

Den Parameter myhostname musst du nicht unbedingt setzen; wird er nicht gesetzt nimmt postfix einfach den Hostnamen der auf dem System konfiguriert ist.
Korrekterweise müsste dieser jedoch derselbe sein auf welcher der reverse-Eintrag der IP des Servers sich auflöst.
D.h. wenn der reverse-Eintrag der IP deines Servers: „mail.example.com“ sagt, dein Server aber den Hostnamen: „mailserver01.deinedomain.de“ hat, so müsstest du:

myhostname = mail.example.com

eintragen.

Hinweis

Den reverse-Namen deiner IP findest du mit:

nslookup DEINE_IP

raus. – Hast du einen rootserver gemietet, so müsste sich dieser im Konfigurations-Panel des Providers ändern lassen.

postfix nimmt standardmässig den Wert aus $myhostname, um lokale Adressen zu vervollständigen.
D.h. wenn nun ein lokaler dienst eine mail an z.B. „root“ sendet, so macht der mailserver dann: „root@mail.example.com“ draus. – Möchtest du lieber, dass daraus weiterhin „root@mailserver01.example.com“ wird (wie es am korrektesten wäre), dann möchtest du vielleicht die $myorigin Variable setzen:

myorigin = mailserver01.$mydomain

Natürlich kannst du auch „myorigin = $mydomain“ setzen, dann würde z.B. aus root: „root@example.com“.

Achtung
Wenn du den myhostname Paramater ao änderst, musst du auf jeden Fall darauf schauen, dass du diesen Hostnamen aus myorigin (mailserver01.example.com, oder mail.example.com, oder example.com) auch im postfixadmin anlegst; denn sonst funktioniert das lokale mail-system deines Servers nicht mehr!
Mails lokal anschauen
Hat du es so eingerichtet, dass die lokalen Mails im Mailsver-Postfach landen, wirst du wahrscheinlich feststellen, dass das „mail“ Kommando nicht mehr funktioniert.
Möchtest du weiterhin mit „mail“ deine Mails lesen können, dann kannst du in ~/.bash_profile die MAIL Environment-Variable setzen:

MAIL=/srv/mail/mailserver01/root/Maildir/

Dies geht auch global in /etc/profile; doch dass funktioniert natürlich nur wenn du für jeden Systemuser einen Mail-Account auf dem Mailserver angelegt hast und die rechte in: /srv/mail/mailserver01/USER/ entsprechend setzt:

chown -vR :mail /srv/mail/mailserver01/USER/
find /srv/mail/mailserver01/USER/ -type d |xargs chmod -v 770
find /srv/mail/mailserver01/USER/ -type f |xargs chmod -v 660

Tip: Lokale Mails von anderen Servern umleiten
Falls du noch andere Server (z.B: einen Webserver) hast und möchtest, dass alle anderen Server über den Zentralen Mail-Server ihre Mails verschicken, kannst du diese als Relay-Hosts angeben:

relayhost = mail.example.com

Lokale Mails (wie z.B. root) werden so aber noch immer direkt ausgeliefert, da der relayhost Parameter nur für externe Mails gilt. Damit diese lokalen Mails ebenfalls zentral auf deinem Mail-Server landen, ändere auf den anderen Servern postfix Parameter „mydestination “ wie folgt ab:

mydestination = localhost

Damit sagst du deinem webserver, dass er für Mails wie: root@webserver01.example.com nicht mehr zuständig ist; somit werden diese Mails als normale externe Mails betrachtet und an den Mailserver weiter gegeben. Übrigens klappt dies auch ohne den oben beschriebenen relayhost Parameter, so lange es im DNS-Server einen MX-Eintrag für: webserver01.example.com gibt, der auf deinen Mail-Server zeigt.

Dann erstellst du auf dem Mail-Server eine Mail-Domain für den anderen Server (z.B. webserver01.example.com) und erstellst dort Mailboxen, Aliases, Forwards, Catch-All, etc.

Ab dann sendet der lokale postfix auf den anderen Servern alles über den Mailserver und die lokalen System User Mails landen fortan auf deinem zentralen Mailserver. 🙂

Alternativ kannst du, wenn du alle lokalen Mails nur an eine E-Mail Adresse weiter leiten willst eine entsprechende Zeile in: /etc/aliases machen:

root:          admin@server.example.com

Der Unterschied ist, dass mit der ersten Methode (setzen des mydestination Parameters) eine lokale Mail (z.B. an „apache“) immer auf auf apache@webserver01.example.com geleitet wird.
Mit der zweiten Methode (Eintrag in /etc/aliases) würde eine lokale Mail an apache auf admin@server.example.com ankommen.

Abschlusskonfiguration

Und ans ende der Datei fügst du dann noch folgende Zeilen an:

# TLS parameters
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_key_file = /etc/ssl/private/mail.key
smtpd_tls_cert_file = /etc/ssl/certs/mail.crt
smtpd_tls_CAfile = /etc/ssl/certs/cacert.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
 
 
# VIRTUAL DOMAINS
#
# This configures the virtual domain names
 
# get password from dovecot
smtpd_sasl_local_domain =
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions =  permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
broken_sasl_auth_clients = yes
 
# virtual mailbox settings
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
# change uid to postfix uid
virtual_minimum_uid = 1025
virtual_uid_maps = static:1025
# change gid to postfix gid
virtual_gid_maps = static:1025
virtual_mailbox_base = /srv/mail
 
# Enable this to use proxymap instead of direct mysql connection
#proxy_read_maps = $local_recipient_maps $virtual_mailbox_domains $virtual_alias_maps $virtual_mailbox_maps $virtual_mailbox_limit_maps
 
virtual_mailbox_domains = mysql:/etc/postfix/mysql/virtual_domains_maps.cf
virtual_alias_maps =
   mysql:/etc/postfix/mysql/virtual_alias_maps.cf,
   mysql:/etc/postfix/mysql/virtual_alias_domain_maps.cf,
   mysql:/etc/postfix/mysql/virtual_alias_domain_catchall_maps.cf
virtual_mailbox_maps =
   mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf,
   mysql:/etc/postfix/mysql/virtual_alias_domain_mailbox_maps.cf
 
# Additional for quota support
virtual_create_maildirsize = yes
virtual_mailbox_extended = yes
virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql/virtual_mailbox_limit_maps.cf
virtual_mailbox_limit_override = yes
virtual_maildir_limit_message = Sorry, the user's maildir has overdrawn his diskspace quota, please try again later.
virtual_overquota_bounce = yes
 
# SPAM FILTERING
#
# Configures amavisd-new for spam/virus filtering
content_filter=amavisfeed:[127.0.0.1]:10024

/etc/postfix/master.cf

Nun fügen wir unter: „Interfaces to non-Postfix software“ folgende Zeilen dazu:

# Dovecot LDA
dovecot   unix  -       n       n      -       -       pipe
  flags=DRhu user=vmail:mail argv=/usr/libexec/dovecot/dovecot-lda -f ${sender} -d ${recipient}
#
# ====================================================================
#
# amavis
amavisfeed unix -       -       n        -      2     smtp
     -o smtp_data_done_timeout=1200
     -o smtp_send_xforward_command=yes
     -o disable_dns_lookups=yes
     -o max_use=20
#
127.0.0.1:10025 inet n    -       n       -       -     smtpd
     -o content_filter=
     -o smtpd_delay_reject=no
     -o smtpd_client_restrictions=permit_mynetworks,reject
     -o smtpd_helo_restrictions=
     -o smtpd_sender_restrictions=
     -o smtpd_recipient_restrictions=permit_mynetworks,reject
     -o smtpd_data_restrictions=reject_unauth_pipelining
     -o smtpd_end_of_data_restrictions=
     -o smtpd_restriction_classes=
     -o mynetworks=127.0.0.0/8
     -o smtpd_error_sleep_time=0
     -o smtpd_soft_error_limit=1001
     -o smtpd_hard_error_limit=1000
     -o smtpd_client_connection_count_limit=0
     -o smtpd_client_connection_rate_limit=0
     -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
     -o local_header_rewrite_clients=
 
# smtps
# smtps and SASL authenticated (outgoing) mail goes to a different amavis policy bank
# as described here: http://www200.pair.com/mecham/spam/bypassing.html#10
smtps     inet  n       -       n       -       -       smtpd
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    -o smtpd_client_restrictions=permit_sasl_authenticated,reject
    -o content_filter=amavisfeed:[127.0.0.1]:10026
 
 
 
# ====================================================================
#

SSL-Zertifikate

Nun erstellen wir noch die benötigten SSL-Zertifikate:

mkdir -pv /etc/ssl/{certs,private}
touch mail.key
chmod -v 600 mail.key
openssl genrsa 1024 > mail.key
openssl req -new -key mail.key -x509 -days 3650 -out mail.crt
openssl req -new -x509 -extensions v3_ca -keyout cakey.pem
-out cacert.pem -days 3650
mv -v mail.key /etc/ssl/private/
mv -v mail.crt /etc/ssl/certs/
mv -v cakey.pem /etc/ssl/private/
mv -v cacert.pem /etc/ssl/certs/

amavis

Grundkonfiguration

Obwohl amavis meist „out-of-the-box“ gut funktioniert, sollte man sich mit der Konfigration /etc/amavisd.conf etwas vertraut machen, denn dort werden sowohl clamd wie auch SpamAssassin konfiguriert!

Die folgenden Parameter sind dabei besonders wichtig:

use strict;
$mydomain                    = 'mail.example.com';          # (no useful default)
$daemon_user                 = 'amavis';                        # amavis User
$daemon_group                = 'amavis';                        # amavis Group
$TEMPBASE                    = "$MYHOME/tmp";                   # Temporary files
$db_home                     = "$MYHOME/db";                    # DB-Files
$pid_file                    = "/var/run/amavis/amavisd.pid";   # (default: "$MYHOME/amavisd.pid")
$lock_file                   = "/var/lock/amavis/amavisd.lock"; # (default: "$MYHOME/amavisd.lock")
$max_servers                 = 2;                               # (default 2) number of pre-forked children
$enable_db                   = 1;                               # enable use of BerkeleyDB/libdb (SNMP and nanny)
$enable_global_cache         = 1;                               # enable use of libdb-based cache if $enable_db=1
@mynetworks                  = qw( 127.0.0.0/8 [::1] );         # Hier ggf. deine lokalen IPs hinzufügen
$log_level                   = 2;                               # Log level
$DO_SYSLOG                   = 1;                               # Use syslog
$unix_socketname             = "/var/run/amavis/amavisd.sock";  # Unix socket to accept amavis helper protocol
$inet_socket_port            = 10024;                           # accept connections on this TCP port(s) (SMTP...);
$final_spam_destiny          = D_DISCARD;                       # (default: D_BOUNCE) subject to $sa_dsn_cutoff_level
$QUARANTINEDIR               = "$MYHOME/quarantine";            # Quarantine directory
$path                        = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin';
@av_scanners =
(
  ['ClamAV-clamd',
    &ask_daemon, ["CONTSCAN {}n", "/var/run/clamav/clamd.sock"],
    qr/bOK$/m, qr/bFOUND$/m,
    qr/^.<em>?: (?!Infected Archive)(.</em>) FOUND$/m ],
);
$sa_tag_level_deflt          = undef;                         # (default: 2.0) X-Spam tags only from this score (undef; means every mail)
$sa_tag2_level_deflt         = 5.0;                           # (default: 5.0) Emails with a spam score from this level will be marked as spam
$sa_tag3_level_deflt         = undef;                         # Normaly unused
$sa_kill_level_deflt         = 8.50;                          # (default: 8.0) At this level act on the email according to the $final_spam_destiny setting.
$sa_dsn_cutoff_level         = 12;                            # (default: 12.0) Don't send bouce messages above this level
    1; # insure a defined return value
max_servers
Beim Parameter $max_servers ist zu beachten, dass dieser genau gleich hoch sein muss wie der maxproc-Parameter bei amavisfeed in /etc/postfix/master.cf!

Will man zusätzlich einige Datei-Erweiterungen ausschliessen, kann man dies mittels dem folgenden Block tun:

$banned_filename_re = new_RE(
  qr'^.(exe-ms|dll)$',                                       # banned file(1) types, rudimentary
  qr'^.(exe|lha|tnef|cab|dll)$',                             # banned file(1) types
  qr'..(pif|scr)$'i,                                         # banned extensions - rudimentary
  qr'^application/x-msdownload$'i,                            # block these MIME types
  qr'^application/x-msdos-program$'i,
  qr'^application/hta$'i,
  qr'.[^./][A-Za-z][^./]</em>.s<em>(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)[.s]$'i,
  qr'..(exe|vbs|pif|scr|cpl|bat|cmd|com)$'i,                 # banned extension - basic+cmd
);
%banned_rules = (
  'ALLOW_ARCHIVES'   => new_RE( [ qr'^.(zip|rar|arc|arj|zoo)$'=> 0 ] ),  # allow any within these archives
  'NO-MS-EXEC'       => new_RE( qr'^.(exe-ms)$' ),
  'PASSALL'          => new_RE( [qr'^' => 0] ),
  'ALLOW_EXE'        => # pass executables except if name ends in .vbs .pif .scr .bat
                        new_RE( qr'..(vbs|pif|scr|bat)$'i, [qr'^.exe$' => 0] ),
  'ALLOW_VBS'        => new_RE( [qr'..vbs$' => 0] ),         # allow names ending in .vbs
  'NORMAL'           => new_RE( qr'..(exe|vbs|pif|scr|cpl)$'i, ),   # banned extension - basic
  'DEFAULT'          => $banned_filename_re,
);

Stanardmässig werden dabei die Dateitypen aus: $banned_filename_re genommen. Und wenn man die SQL-Einbindung (siehe weiter unten) macht, kann man zusätzlich eigene Regeln definieren und diese im SQL-Feld „policy.banned_rulenames“ angeben (auch mehrere, mit Komma getrennt, z.B.: „ALLOW_ARCHIVES, NORMAL“.

Tip: RAM-Disk
Wenn das bearbeiten der Mails durch amavis zu viel Disk-Performance braucht, kann man das tmp-verzeichnis von amavis auf eine RAM-Disk legen.

Diese wird mittels folgendem Eintrag in: /etc/fstab erzeugt:

none /var/spool/amavis/tmp tmpfs defaults,size=180m,mode=750,uid=65,gid=0,noatime 0 0

Dann noch das Verzeichnis erstellen und mounten:

mkdir -pv  /var/spool/amavis/tmp/
mount /var/spool/amavis/tmp/

Und die Variable $TEMPBASE in /etc/amavisd.conf auf: /var/spool/amavis/tmp/ setzen

Tip: Ausgehnde mails auschliessen
Ausgehende Mails von authentifizierten Benutzern erhalten in der Regel keinen spam, weshalb man diese teilweise ausschliessen will.

Dazu legt man in der /etc/postfix/master.cf zuerst einen Absatz für smtps Verkehr an, der dann auf einen zusätzlichen amavis Port (10026) geht:

smtps     inet  n       -       n       -       -       smtpd
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    -o smtpd_client_restrictions=permit_sasl_authenticated,reject
    -o content_filter=amavisfeed:[127.0.0.1]:10026

Dann ändert man in /etc/amavisd.conf die Zeile:

$inet_socket_port            = 10024;

in:

$inet_socket_port            = [10024, 10026];

ab und fügt eine sog. „Policy Bank“ für diesen Port hinzu:

$interface_policy{'10026'} = ('SASLBYPASS');
$policy_bank{'SASLBYPASS'} = {  # mail from submission and smtps ports
  originating => 1,  # declare that mail was submitted by our smtp client
  bypass_spam_checks_maps   => [1],  # don't spam-check this mail
  bypass_banned_checks_maps => [1],  # don't banned-check this mail
  bypass_header_checks_maps => [1],  # don't header-check this mail
};

Hier kann man dann konfigurieren, dass die spam-, verbotene dateien- und header checks umgangen werden, aber nach wie vor noch nach Viren gescannt wird.

Dies funktioniert allerdings nur dann wenn man SMTPS (Port 465) für den Mailversand benutzt, was heutzutage eigentlich jeder tun sollte.
Will man nun aber alle authentifizierten Benutzer (also auch die, die den Port 25 benutzen) vom scannen auschliessen, kann man das wie folgt erreichen:

Zuerst muss in /etc/postfix/main.cf die Zeile:

content_filter=amavisfeed:[127.0.0.1]:10024

wie folgt ersetzt werden:

content_filter = amavisfeed:[127.0.0.1]:10026
  smtpd_data_restrictions =
  reject_unauth_pipelining
  permit_mynetworks
  permit_sasl_authenticated
  check_client_access regexp:/etc/postfix/filter-catchall.regexp

Dann muss noch die Datei: /etc/postfix/filter-catchall.regexp mit folgendem Inhalt erstellt werden:

/^/ FILTER amavisfeed:[127.0.0.1]:10024

Nun werden alle über SASL authentifizierten Benutzer vom Spam-Scanning ausgeschlossen.

SQL-Einbindung

Mittels einer kleinen SQL-Datenbank kann man amavis noch feiner einstellen, indem man z.B. einzelne E-Mail Adressen oder ganze Domains vom scannen ein-/auschliessen- und black-/whitelist anlegen kann.

Die Integration ist relativ einfach:
Zuerst wird wie im README.sql-mysql die amavis-Datenbank und Benutzer angelegt:

mysql -u root -p
mysql >
CREATE USER 'amavis'@'localhost' IDENTIFIED BY 'secret';
CREATE DATABASE amavis;
GRANT ALL PRIVILEGES ON amavis.* TO amavis@localhost IDENTIFIED BY 'secret';

Erstelle eine Dazei mit folgendem Inhalt:

/tmp/amavis.sql

-- local users
CREATE TABLE users (
  id         INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  -- unique id
  priority   INTEGER      NOT NULL DEFAULT '7',  -- sort field, 0 is low prior.
  policy_id  INTEGER UNSIGNED NOT NULL DEFAULT '1',  -- JOINs with policy.id
  email      varbinary(255) NOT NULL UNIQUE,
  fullname   VARCHAR(255) DEFAULT NULL    -- not used by amavisd-new
  -- local   char(1)      -- Y/N  (optional field, see note further down)
);
 
-- any e-mail address (non- rfc2822-quoted), external or local,
-- used as senders in wblist
CREATE TABLE mailaddr (
  id         INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  priority   INTEGER      NOT NULL DEFAULT '7',  -- 0 is low priority
  email      varbinary(255) NOT NULL UNIQUE
);
 
-- per-recipient whitelist and/or blacklist,
-- puts sender and recipient in relation wb  (white or blacklisted sender)
CREATE TABLE wblist (
  rid        INTEGER UNSIGNED NOT NULL,  -- recipient: users.id
  sid        INTEGER UNSIGNED NOT NULL,  -- sender: mailaddr.id
  wb         VARCHAR(10)  NOT NULL,  -- W or Y / B or N / space=neutral / score
  PRIMARY KEY (rid,sid)
);
 
CREATE TABLE policy (
  id  INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
                                    -- 'id' this is the _only_ required field
  policy_name      VARCHAR(32),     -- not used by amavisd-new, a comment
 
  virus_lover           CHAR(1) DEFAULT NULL,     -- Y/N
  spam_lover            CHAR(1) DEFAULT NULL,     -- Y/N
  unchecked_lover       CHAR(1) DEFAULT NULL,     -- Y/N
  banned_files_lover    CHAR(1) DEFAULT NULL,     -- Y/N
  bad_header_lover      CHAR(1) DEFAULT NULL,     -- Y/N
 
  bypass_virus_checks   CHAR(1) DEFAULT NULL,     -- Y/N
  bypass_spam_checks    CHAR(1) DEFAULT NULL,     -- Y/N
  bypass_banned_checks  CHAR(1) DEFAULT NULL,     -- Y/N
  bypass_header_checks  CHAR(1) DEFAULT NULL,     -- Y/N
 
  virus_quarantine_to      VARCHAR(64) DEFAULT NULL,
  spam_quarantine_to       VARCHAR(64) DEFAULT NULL,
  banned_quarantine_to     VARCHAR(64) DEFAULT NULL,
  unchecked_quarantine_to  VARCHAR(64) DEFAULT NULL,
  bad_header_quarantine_to VARCHAR(64) DEFAULT NULL,
  clean_quarantine_to      VARCHAR(64) DEFAULT NULL,
  archive_quarantine_to    VARCHAR(64) DEFAULT NULL,
 
  spam_tag_level  FLOAT DEFAULT NULL, -- higher score inserts spam info headers
  spam_tag2_level FLOAT DEFAULT NULL, -- inserts 'declared spam' header fields
  spam_tag3_level FLOAT DEFAULT NULL, -- inserts 'blatant spam' header fields
  spam_kill_level FLOAT DEFAULT NULL, -- higher score triggers evasive actions
                                      -- e.g. reject/drop, quarantine, ...
                                     -- (subject to final_spam_destiny setting)
  spam_dsn_cutoff_level        FLOAT DEFAULT NULL,
  spam_quarantine_cutoff_level FLOAT DEFAULT NULL,
 
  addr_extension_virus      VARCHAR(64) DEFAULT NULL,
  addr_extension_spam       VARCHAR(64) DEFAULT NULL,
  addr_extension_banned     VARCHAR(64) DEFAULT NULL,
  addr_extension_bad_header VARCHAR(64) DEFAULT NULL,
 
  warnvirusrecip      CHAR(1)     DEFAULT NULL, -- Y/N
  warnbannedrecip     CHAR(1)     DEFAULT NULL, -- Y/N
  warnbadhrecip       CHAR(1)     DEFAULT NULL, -- Y/N
  newvirus_admin      VARCHAR(64) DEFAULT NULL,
  virus_admin         VARCHAR(64) DEFAULT NULL,
  banned_admin        VARCHAR(64) DEFAULT NULL,
  bad_header_admin    VARCHAR(64) DEFAULT NULL,
  spam_admin          VARCHAR(64) DEFAULT NULL,
  spam_subject_tag    VARCHAR(64) DEFAULT NULL,
  spam_subject_tag2   VARCHAR(64) DEFAULT NULL,
  spam_subject_tag3   VARCHAR(64) DEFAULT NULL,
  message_size_limit  INTEGER     DEFAULT NULL, -- max size in bytes, 0 disable
  banned_rulenames    VARCHAR(64) DEFAULT NULL, -- comma-separated list of ...
        -- names mapped through %banned_rules to actual banned_filename tables
  disclaimer_options  VARCHAR(64) DEFAULT NULL,
  forward_method      VARCHAR(64) DEFAULT NULL,
  sa_userconf         VARCHAR(64) DEFAULT NULL,
  sa_username         VARCHAR(64) DEFAULT NULL
);

Nun lade diese Datei in die Datenabk:

 

Dann folgendes unten in der /etc/amavisd.conf eingetragen:

@lookup_sql_dsn =
  ( ['DBI:mysql:database=amavis;host=dbserver', 'amavis', 'geheimespasswort'], );
 
$sql_select_policy =
  'SELECT *,users.id'.
  ' FROM users LEFT JOIN policy ON users.policy_id=policy.id'.
  ' WHERE users.email IN (%k) ORDER BY users.priority DESC';
 
$sql_select_white_black_list =
  'SELECT wb'.
  ' FROM wblist JOIN mailaddr ON wblist.sid=mailaddr.id'.
  ' WHERE wblist.rid=? AND mailaddr.email IN (%k)'.
  ' ORDER BY mailaddr.priority DESC';
 
%sql_clause = (
  'sel_policy' => $sql_select_policy,
  'sel_wblist' => $sql_select_white_black_list,
  'sel_adr' =>
    'SELECT id FROM maddr WHERE partition_tag=? AND email=?',
);

amavisd-release

Will man eine von amavis ausgefilterte Nachricht trotzdem zustellen lassen, muss man die amavisd.conf zuerst anpassen, indem man eine Policy Bank hinzufügt:

$interface_policy{'SOCK'} = 'AM.PDP-SOCK';
$policy_bank{'AM.PDP-SOCK'} = {
  protocol => 'AM.PDP',                                       # select Amavis policy delegation protocol
  auth_required_release => 0,                                 # don't require secret_id for amavisd-release
};

Danach kann man mittels:

[root@mailserver ~]# amavisd-release spam-xyzabcsdfsf.gz
250 2.0.0 from MTA([127.0.0.1]:10025): 250 2.0.0 Ok: queued as 9287C5B2

die Mail nachträglich zustellen lassen.

Hinweis

amavisd-release greift hardcoded auf den UNIX-Socket: „/var/amavis/amavisd.sock“ zu, was der Standard-Einstellung in amavisd.conf entspricht („$MYHOME/amavisd.sock“).
Wenn man jedoch den $unix_socketname in amavisd.conf vom Standard abweichend konfiguriert hat, wie in unserem Beispiel auf: „/var/run/amavis/amavisd.sock“, dann erstellt man am besten einen symlink zum tatsächlichen Socket:

ln -sv /var/run/amavis/amavisd.sock /var/amavis/amavisd.sock

clam-av (clamd)

Beim Clam-AV Virenscanner sollte keine zusätzliche Konfiguration nötig sein.

SpamAssassin

SpamAssassin wird fast ausschliesslich über die amavisd.conf Konfiguriert. Obwohl es durchaus möglich wäre eine zusätzliche Konfiguration in /etc/mail/spamassassin/local.cf zu erstellen sollte man dies nur in Ausnahmefällen tun. Denn diverse SpamAssassin-Parameter (z.B. alle die die Mail irgendwie verändern) werden von amavis ohnehin ignoriert!

Falls man doch Änderungen in der SpamAssassin konfiguration machen will, macht man dies am besten im file: /var/amavis/.spamassassin/user_prefs:

Das folgende Beispiel würde den „autolearn-filter“ etwas besser Einstellen als die Standard-Werte (non-spam: 0.1 / spam: 6.0):

bayes_auto_learn 1
bayes_auto_learn_threshold_nonspam 0.0
bayes_auto_learn_threshold_spam 12.0

Datenbank und postfixadmin

Nun werden wir die Datenbank für postfixadmin erstellen und dieses Konfigurieren.

Falls der mysql-server gerade neu installiert wurde, müssen wir noch ein Passwort setzen:

mysqladmin password DEIN_PASSWORT

Sollte es sich um einen bereits laufenden mysql-server halten, nimm einfach das passwort, dass du bereits konfiguriert hast. 😉

Aufsetzen der Datenbank:

mysql -u root -p
mysql >
CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'mailuserpassword';
CREATE DATABASE postfix;
GRANT ALL PRIVILEGES ON postfix.* TO postfix@localhost IDENTIFIED BY 'mailuserpassword';

– Für „mailuserpassword“ setzt du natürlich ein eigenes Passwort ein und „postfix“ ist einfach der mysql-user mit dem auf die Datenbank postfix zugegriffen wird.

Nun installierst du postfixadmin und konfigurierst die Werte in: postfixadmin/config.inc.php so, dass sie auf dein setup passen. – Zu letzt noch:

$CONF['configured'] = true;

setzen und du müsstest über postfixadmin bereits deine Mail- Domains, Konten, Aliase, usw. anlegen können.

Wichtig

Lege auf jeden Fall den Hostnamen deines Server (z.B. mailserver01.example.com) im postfixadmin an und setze im DNS-Server einen mx-record darauf. Auf diesen solltest du dann _mindestens_ die aliase aus der Datei /etc/aliases anlegen (aber mach am besten einen catch-all darauf); denn sonst funktioniert das lokale mail-system deines Servers nicht mehr!

Virtuelle E-Mail Konten vorbereiten

Als erstes erstellst du nun einen Ordner, wo zukünftig sämtliche mails deiner virtuellen Konten gespeichert werden, in diesem Tutorial ist das: „/srv/mail“

mkdir -pv /srv/mail
chown -vR vmail:mail /srv/mail
chmod - vR 775 /srv/mail

Nun müssen noch die mysql-Abfragen für postfix erstellt werden; dabei handelt es sich um einzelne files, die wir bereits in /etc/postfix/main.cf definiert hatten und eifach nur eine SQL-Abfrage enthalten.

Erst erstellen wir dafür ein Verzeichnis:

mkdir -pv /etc/postfix/mysql

Und erstellen dann darin die folgenden Dateien:
(Die Werte user, password und dbname müssen natürlich angepasst werden!)
/etc/postfix/mysql/virtual_alias_maps.cf:

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
#expansion_limit = 100

/etc/postfix/mysql/virtual_alias_domain_maps.cf:

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'

/etc/postfix/mysql/virtual_alias_domain_catchall_maps.cf:

# handles catch-all settings of target-domain
user = postfix
password = password
hosts = localhost
dbname = postfix
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'

/etc/postfix/mysql/virtual_domains_maps.cf:

user = postfix
password = password
hosts = localhost
dbname = postfix
query          = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#query          = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query           = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#expansion_limit = 100

/etc/postfix/mysql/virtual_mailbox_maps.cf:

user = postfix
password = password
hosts = localhost
dbname = postfix
query           = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
#expansion_limit = 100

/etc/postfix/mysql/virtual_alias_domain_mailbox_maps.cf:

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'

/etc/postfix/mysql/virtual-mailbox-limit-maps.cf:

# For quota support
user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
Hinweis

Im Prinzip könnte man hier auch ein anderes Datenbank-Schema verwenden; es ist jedoch am einfachsten gleich das Schema zu verwenden, welches postfixadmin benutzt, da man ansonsten die Einträge mühsam von Hand in die Datenbank eintragen müsste.

mysql mit proxymap

Die obige Konfiguration öffnet nun für jedes Mail mehrere mysql-Verbindungen, was irgendwann zur Überlastung des mysql-Servers führen könnte.

Deshalb kann man dafür proxymap benutzen. Proxymap bündelt mehrere mysql-Abfragen und führt diese Kompakt in einer Verbindung durch. So können enorm Ressourcen gespart werden.

Folgende Änderungen sind dazu nötig:

Das Verzeichnis: /etc/postfix/mysql und alle Dateien darin müssen root gehören und für die die Gruppe postfix lesbar sein:

chown -vR root:postfix /etc/postfix/mysql
chmod -v 750 /etc/postfix/mysql
chmod -v 640 /etc/postfix/mysql/*

Nun müssen in /etc/postfix/main.cf alle maps die wir mit mysql-Abfragen, im Parameter „proxy_read_maps“ definiert werden; zudem braucht es noch $local_recipient_maps darin.
Diesen Parameter fügen wir am besten vor die erste „mysql:“-Abfrage ein:

proxy_read_maps = $local_recipient_maps $virtual_mailbox_domains $virtual_alias_maps $virtual_mailbox_maps $virtual_mailbox_limit_maps

Nun muss nur noch jedes:

mysql:

mit:

proxy:mysql:

ersetzt werden; d.H. einfach immer ein „proxy:“ davor schreiben. Beispiel:

virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql/virtual_domains_maps.cf

Danach kann die funktionalität mit:

postmap -q "VIRTUELLE_DOMAIN.TLD" proxy:mysql:/etc/postfix/mysql/virtual_domains_maps.cf

überprüft werden.

Dovecot

Nun gehts ans Einrichten von Dovecot, welches nun schnell geht.

Es müssen nur noch die folgende drei files geändert/erstellt werden:

/etc/dovecot/dovecot.conf

#========================== Global Section ====================================
 
base_dir = /var/run/dovecot/
protocols = imap pop3 sieve
listen = *, [::]
first_valid_uid = 1025
mail_location = maildir:/srv/mail/%d/%n/Maildir
auth_mechanisms = plain login
auth_verbose = yes
disable_plaintext_auth = no
verbose_proctitle = yes
 
 
 
#========================== SSL ===============================================
# Preferred permissions: root:root 0400
 
ssl_cert = </etc/ssl/certs/mail.crt
ssl_key =  </etc/ssl/private/mail.key
# This is optional:
ssl_ca = </etc/ssl/certs/cacert.pem
 
 
 
#========================== Plugins ===========================================
# Space separated list of plugins to load for all services. Plugins specific to
# IMAP, LDA, etc. are added to this list in their own .conf files.
mail_plugins = $mail_plugins quota
 
 
## Dictionary DB proxy
dict {
  sqlquota = mysql:/etc/dovecot/dict-quota.conf
}
 
plugin {
  # Quota
  quota = dict:User quota::proxy::sqlquota
  quota_rule2 = INBOX.Trash:storage=+100M
  quota_warning = storage=90%% quota-warning 90 %u
  quota_warning2 = -storage=90%% quota-warning below %u # user is no longer over quota
 
  # Sieve
  # sieve_dir gets pulled from the userdb sql query
  #sieve_dir = /srv/mail/%d/%n/sieve
  sieve = /srv/mail/%d/%n/.dovecot.sieve
}
 
 
 
#========================== Services ==========================================
 
service auth {
  unix_listener /var/spool/postfix/private/auth {
    user = postfix
    group = postfix
    mode = 0660
  }
 
  unix_listener auth-master {
  }
 
  unix_listener auth-userdb {
    user = vmail
    #group = root
    #mode = 0600
  }
 
}
 
service dict {
  unix_listener dict {
    user = vmail
    mode = 0600
  }
}
 
userdb {
  driver = sql
  args = /etc/dovecot/sql.conf
}
 
passdb {
  driver = sql
  args = /etc/dovecot/sql.conf
}
 
 
service quota-warning {
  # use some unprivileged user for executing the quota warnings
  user = vmail
  executable = script /usr/local/libexec/quota-warning.sh
 
  unix_listener quota-warning {
    user = vmail
  }
}
 
 
 
#========================== Protocols =========================================
 
protocol lda {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins sieve
  postmaster_address = postmaster@example.com
  # For using syslog with deliver, set the paths empty
  log_path =
  info_log_path =
}
 
protocol lmtp {
  mail_plugins = $mail_plugins sieve
}
 
protocol imap {
  mail_plugins = $mail_plugins imap_quota
}
 
protocol pop3 {
  pop3_lock_session=yes
}
 
protocol sieve {
}
 
 
 
#========================== Namespaces ========================================
 
namespace {
  type = private
  separator = /
  prefix =
  inbox = yes
}
 
# This is only for compatibility with clients before courriere migration
namespace {
  type = private
  separator = .
  prefix = INBOX.
  inbox = no
  hidden = yes
  list = no
  alias_for =
}
SNI mit dovecot

Wenn man mit mehreren domains (z.B. mail.example.com und mail.example.org) auf den Mailserver Zugreifen will kann man in der dovecot.conf, wie beim Webserver ein SSL Zertifikat für jede domain angeben:

# SNI for other domains
local_name mail.varco.ch {
  ssl_cert = </usr/local/share/ssl/startssl/certs/example.org.crt
  ssl_key = </usr/local/share/ssl/startssl/keys/example.org.key
}

Teste kann man das dann mit dem openssl Kommando und dem zusätzöichen Paramater -servername:

openssl s_client -showcerts -connect mail.example.com:993 -servername "mail.example.com"
openssl s_client -showcerts -connect mail.example.org:993 -servername "mail.example.org"

/etc/dovecot/sql.conf

driver = mysql
connect = host=localhost port=3306 user=vmail password=DEIN_DBUSER_PASSWORT dbname=postfix
default_pass_scheme = MD5-CRYPT
 
password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
user_query = SELECT maildir, 1025 AS uid, 1025 AS gid, '/srv/mail/%d/%n/' as mail_home, CONCAT('*:storage=',floor(quota/1000)) as quota_rule, '/srv/mail/%d/%n/sieve/' as sieve_dir FROM mailbox WHERE username = '%u'

/etc/dovecot/dict-quota.conf

connect = host=localhost port=3306 user=vmail password=DEIN_DBUSER_PASSWORT dbname=postfix
default_pass_scheme = MD5-CRYPT
 
map {
  pattern = priv/quota/storage
  table = quota2
  username_field = username
  value_field = bytes
}
map {
  pattern = priv/quota/messages
  table = quota2
  username_field = username
  value_field = messages
}

/usr/local/libexec/quota-warning.sh

usage()
{
  echo -e "usage: $0 <percent-full> <user>\n"
}
 
PERCENT=$1
USER=$2
 
# Do some checks
# Check if any parameters are entered
if [ -z "$1" ]; then
  usage
  exit 1
fi
 
if [ ! $PERCENT == "below" ]; then
  check=`echo $PERCENT | sed 's/[^0-9]*//g'`
  if [ -z ${check} ]; then
    echo "Percentage must be a number!"
    usage
    exit 1
  fi
fi
 
if [ -z "$USER" ]; then
  echo "A username is required"
  usage
  exit 1
fi
 
 
if [ ! $PERCENT == "below" ]; then
  cat << EOF | /usr/libexec/dovecot/dovecot-lda -d $USER -o "plugin/quota=dict:User quota::noenforcing:proxy::sqlquota"
From: postmaster@example.com
Subject: quota warning
 
Your mailbox is now $PERCENT% full.
Please cleanup you mailbox as the server will not accept any more mails
when you exeed your quota by 100%!
EOF
else
  cat << EOF | /usr/libexec/dovecot/dovecot-lda -d $USER -o "plugin/quota=dict:User quota::noenforcing:proxy::sqlquota"
From: postmaster@example.com
Subject: quota ok
 
Well done, your mailbox is now $PERCENT the limit again.
EOF
fi

postgrey

Fürs sogenannte „greylisting“ (eine sehr effektive Anti-Spam Methode) hat sich postgrey als der greylisting-server für postfix etabliert.

Die Einrichtung ist denkbar einfach:

yum install perl-NetAddr-IP perl-Net-Server perl-BerkeleyDB
 
useradd -r -s /sbin/nologin -c 'postgrey user' -d /var/spool/postfix/postgrey postgrey
mkdir -v /var/spool/postfix/postgrey
chmod -v 755 /var/spool/postfix/postgrey
chown -v postgrey:postfix /var/spool/postfix/postgrey
 
cd /usr/local/src/
wget 'https://postgrey.schweikert.ch/pub/postgrey-latest.tar.gz'
tar -xvzf postgrey-latest.tar.gz
chown -vR root:root postgrey-*
 
cd postgrey-*
mv -v postgrey /usr/local/sbin/postgrey
mv -v contrib/postgreyreport /usr/local/sbin/postgreyreport
mv -v postgrey_whitelist_* /etc/postfix/

Da das init-script im Paket für debian ist, muss dieses für CentOS/RedHat in: /etc/init.d/postgrey erstellt werden:

#!/bin/sh
#
# chkconfig: - 79 31
# description: Postfix Greylisting Policy Server
#
# processname: postgrey
#
 
# Source function library.
. /etc/rc.d/init.d/functions
 
# Source networking configuration.
. /etc/sysconfig/network
 
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
 
prog=postgrey
postgrey=/usr/local/sbin/$prog
DBPATH=/var/spool/postfix/postgrey
SOCKET=$DBPATH/socket
OPTIONS="--unix=$SOCKET"
 
# Source an auxiliary options file if we have one, and pick up OPTIONS,
if [ -r /etc/sysconfig/$prog ]; then
    . /etc/sysconfig/$prog
fi
 
[ -x $postgrey -a -d $DBPATH ] || exit 0
 
RETVAL=0
 
start() {
    echo -n $"Starting $prog: "
    daemon $postgrey -d $OPTIONS
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
}
stop() {
    echo -n $"Stopping $prog: "
    killproc $postgrey
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
}
 
restart() {
    stop
    start
}
 
reload() {
    echo -n $"Reloading $prog: "
    killproc $postgrey -HUP
    RETVAL=$?
    echo
}
 
# See how we were called.
case "$1" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    restart)
        restart
    ;;
    reload)
        reload
    ;;
    condrestart)
        [ -f /var/lock/subsys/$prog ] && restart
    ;;
    status)
        status $postgrey
    ;;
    *)
        echo $"Usage: $0 {start|stop|restart|condrestart|reload|status}"
        exit 1
esac
 
exit $RETVAL

Nun noch ausführbar machen:

chmod -v 755 /etc/init.d/postgrey

Zudem muss noch eine Datei für die Optionen in: /etc/sysconfig/postgrey angelegt werden:

OPTIONS="--unix=/var/spool/postfix/postgrey/socket --inet=localhost:10023 --user=postgrey --group=postgrey"

Jetzt kann postgrey gestartet werden:

chkconfig postgrey --add
chkconfig postgrey on
/etc/init.d/postgrey start
/etc/init.d/postgrey status

Ist postgrey erfolgreich gestartet wird nun zuletzt in der Datei /etc/postfix/main.cf den Parameter: smtpd_recipient_restrictions mit der Anweisung: check_policy_service erweitert (einfach hinten anhängen).

Beispiel:

smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination,
  check_policy_service inet:localhost:10023

(Die Zeile: check_policy_service inet:localhost:10023 ist neu)

Postfix neu starten und fertig.

Roundcube und Mailgraph

Die Installation von Roundcube und Mailgraph sind ziemlich selbsterklärend. 😉

Roundcube kannst du auch auf einem völlig anderen Server (z.B. einem Webserver) installieren.
Wenn du das selbe bei Mailgraph machen möchtest (z.B. weil du keinen Webserver laufen lassen willst), installiere Mailgraph sowohl auf dem Web- wie auch auf dem Mailserver.
Nun synchroniserst du einfach die RRD-Dateien mit deinem Webserver, z.B. so:

/usr/bin/rsync -a --exclude=".*" /var/lib/mailgraph/ mailgraph@webserver01:/srv/www/admin/mailgraph/rrds/

Das finale

Nun nur noch alles aktivieren, starten und testen:

chkconfig dovecot on
chkconfig postfix on
chkconfig amavisd on
chkconfig clamd on
chkconfig spamassassin on
chkconfig postgrey on
chkconfig mailgraph on
chkconfig mysqld on
chkconfig httpd on
 
/etc/init.d/postfix start
/etc/init.d/dovecot start
/etc/init.d/amavisd start
/etc/init.d/clamd start
/etc/init.d/spamassassin start
/etc/init.d/postgrey start
/etc/init.d/mailgraph start
/etc/init.d/mysqld start
/etc/init.d/httpd start
Hinweis zu spamassassin

Das laufen lassen des spamassassin-daemons (spamd) ist im Prinzip unnötig, da amavis nicht per TCP auf dem spamd zugreift, sondern direkt die API von spamassassin lädt.
Laufen muss der spamd nur dann, wenn amavis auf einer anderen Maschine läuft als spamassassin; dann muss dies jedoch auch in der /etc/amavis.cond explizit so konfiguriert werden.
Die Performance ist allerdings etwas schlechter, wenn man das über die TCP (spamd) Variante macht, wehshalb es wirklich nicht viele Situationen gibt bei denen der spamd laufen muss.

Testen

Ein so umfangreiches setup will natürlich getestet werden. Hier sind einige Tests aufgelistet:

Postfix

Das wichtigste zuerst: Teste ob der Mail-Versand klappt, in dem du dich mit „telnet 25“ bei deinem Mailserver verbindest und ein Mail ablieferst:

220 mail.deinserver.tld ESMTP Postfix
 
EHLO myhost.myprovider.tld
 
250-mail.deinserver.tld
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
 
MAIL FROM:<myemail@mydomain.tld>
 
250 2.1.0 Ok
 
RCPT TO:<testemail@deinserver.tld>
 
250 2.1.5 Ok
 
DATA
 
354 End data with .
 
From: myemail-mydomain.tld <myemail@mydomain.tld>
To: testemail-deinserver.tld <testemail@deinserver.tld>
Subject: Testmail
 
Testmail.
.
 
250 2.0.0 Ok: queued as XTFHFD

Damit du nicht immer umständlich die Eingaben via Telnet machen musst, kannst du dir das Telnet SMTP Test Tool] herunterladen.

Teste dabei einmal eine Mail an eine Mailadresse deines Servers und eine an einen fremden Mailserver zu senden.
=> Ohne SMTP Authentifizierung darf die Mail auf keinen Fall rausgehen, sonst hast du einen Open Relay! Stattdessen muss die Meldung kommen: „Relaying denied“.

dovecot mit quota und sieve

Lade dir einen IMAP-Client, z.B. Thunderbird Portable runter und richte ein das Mail für eines deiner IMAP Konten ein. Schaue, dass alle Mails ankommen, Teste ob du mails versenden kannst, ob du mit dem Sieve Plugin Filter erstellen/beabeiten kanst, usw.

Teste auch ob das Quota wirkt.

amavis, spamassassin clamd

Sende dir jeweils eine Spam– und ein Viren– Mail zu. Dise dürftest du nicht erhalten und müsstest im maillog sehen, dass die Mails geblockt wurden.

Roundcube

Loge dich im Webmail ein und teste ob alles funktioniert

Mailgraph

Schaue ob die mailgraph Statistiken aktualisiert werden.

Nützliche scripts

Hier werden einige nützliche scripts gezeigt mit denen man sich die Arbeit erleichtern kann.

mailq-topsenders

Es kann vorkommen, dass ein Benutzer des Mailservers bewusst oder unbewusst (z.B. durch Viren) sehr viele Mails schickt und so die mailq füllt. Mit diesem Script findest du sehr schnell raus wer am meisten Mails in die mailq eingeliefert hat:

#!/bin/bash
 
TOP_SENDERS=$(mailq|grep ^[A-F0-9]|cut -c 42-80|sort |uniq -c|sort -n|tail)
 
if [ "$TOP_SENDERS" == "" ]; then
  echo "mailq is empty"
else
  echo -e "Top-Senders:n$TOP_SENDERS"
fi

mailq-readmail

Falls du mit dem obigen script einen Benutzer identifiziert hast, kannst du mittels diesem Script die ganzen Mails in der mailq des Benutzer lesen.

#!/bin/bash
 
SENDER="$1"
TMPDIR=$(mktemp -d)
 
if [ "$SENDER" = "" ]; then
  echo "usage: $(basename $0) <user@example.org>"
  exit 1
fi
 
SENDER_IN_QUEUE=$(mailq|grep ^[A-F0-9]|cut -c 42-80|sort |uniq -c|sort -n|tail |grep $SENDER)
 
if [ "$SENDER_IN_QUEUE" = "" ]; then
  echo -e ""$SENDER" is not in queue"
  exit 1
fi
 
for n in $(mailq|grep ^[A-F0-9].*$SENDER| cut -c 1-10) ; do
  FILE=$(echo $n|sed -e "s/^(.)//var/spool/postfix/deferred/1/1/" -e "s/ .*$//")
  if [ -f "$FILE" ]; then
    postcat "$FILE" > $TMPDIR/$n
  else
    echo "File $FILE missing, probably active"
  fi
done
less $TMPDIR/*
rm -rfv $TMPDIR

mysql-repair-slave

Wenn man eine master-/slave Kombination des mysql Servers gemacht hat, kann es manchmal sein, dass die Daten im slave nicht mehr synchronisiert werden können. In einem solchen Fall kann man mit diesem script den slave wieder neu synchronisieren.

Hinweis: Die Werte für DB-MASTER-SERVER, POSTFIX-DB und AMAVIS-DB müssen im script natürlich noch angepasst werden.

#!/bin/bash
 
TEMP_FILENAME=/tmp/mysql_slave.sql
read -s -p "Enter mysql root Password: " MYSQL_ROOT_PW
 
mysql -uroot -p$MYSQL_ROOT_PW -e "SLAVE STOP;"
mysqldump -h DB-MASTER-SERVER -udba -p$MYSQL_ROOT_PW --master-data --databases POSTFIX-DB AMAVIS-DB > $TEMP_FILENAME
mysql -uroot -p$MYSQL_ROOT_PW < $TEMP_FILENAME
rm -fv $TEMP_FILENAME
mysql -uroot -p$MYSQL_ROOT_PW -e "SLAVE START;"
mysql -uroot -p$MYSQL_ROOT_PW -e "SHOW SLAVE STATUSG;"

Troubleshooting

Falls noch nicht alles so funktioniert, wie es soll, liefert dir das maillog sehr hilfreiche Informationen:

tail -f /var/log/maillog

Auch solltest du sicherstellen, dass du dich lokal per telnet mit folgenden ports Verbinden kannst: 25, 110, 143, 993, 995, 783, 10024, 10025

Und diese Ports musst du per Telnet auch von aussen aus erreichen können: 25, 110, 143, 993, 995

Related Links

Related Downloads

postfixadmin: Ein schönes Frontend um die virtuellen Mailkonten zu verwalten
Telnet_SMTP_Test_Tool: Praktisches Tool, um schnell SMTP-Verbindungen zu testen

postgrey: Postgrey server
Policyd: Mit dem policyd kann man zusätzliche Mail-Limits setzten, z.B. wie viele Mails ein Benutzer innerhalb einer bestimmten zeit senden darf

Published by

Steven Varco

Steven ist ein Redhat RHCE-Zertifizierter Linux-Crack und ist seit über 18 Jahren sowohl beruflich wie auch privat auf Linux spezialisiert. In seinem Keller steht ein Server Rack mit diversen ESX und Linux Servern.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.