Von der Cloud in die Cloud: Migration von M365 zu Postfix & Nextcloud

Für mich stand gerade mal ein grösseres Projekt an. Seit nun ca. 2 Jahren war ich Kunde bei Microsoft, genauer gesagt bei Ihrem SaaS Dienst M365, bisher bekannt als O365. Im Grunde war ich auch zufrieden. Die Dienste, wie Mail, Onedrive und Teams liefen ohne Ausfälle. Zumindest ohne dass ich es bemerkt hätte.

Es kam aber der Tag, an dem bekannt wurde, dass Microsoft einen Master Key „verloren“ hat. Dies ist aber nicht Microsoft selbst aufgefallen, sondern einem ihrer Kunden, der das kostenpflichte Addons zum Auswerten der Logs gebucht hatte. In eben diesen Logs hatte der Kunde verdächtiges Verhalten aufgespürt und dies auch direkt an Microsoft gemeldet. Wie man sich nun schon fast denken kann, hat Microsoft dies ersteinmal nicht gross nach aussen kommuniziert. Intern hat man sich auf die Suche nach betroffenen Kunden gemacht und diese direkt kontaktiert. Es sollen angeblich nur um die 25 gewesen sein, hauptsächlich Behörden, auch in Deutschland. Ein Skandal, der verwunderlicher weise nicht viel Aufsehen erregte, ausser in Fachkreisen. Der Masterkey war so mächtig, dass einige Security Experten sogar davon sprachen, Microsoft hätte seine Kronjuwelen verloren. -BÄM- Ein Wirkungstreffer sollte man meinen. Aber nicht so bei Microsoft. Sie haben das ganze verharmlost.

Nun zurück zu meinem Projekt. Ich war von Microsofts Sicherheitspolitik noch nie überzeugt. Anstatt sichere Produkte mit dem Siegel „Secure by Design“ auf den Markt zu bringen, war bzw. ist die gängige Praxis leider genau das Gegenteil. Die Standardeinstellungen sind löchrig wie der schweizer Käse. Features sind den Redmondern wichtiger als Sicherheit.

Als langjähriger Admin weiss ich natürlich, an welchen Schrauben man drehen sollte, damit das Schlimmste abgewendet werden kann. Aber es ist immer mit extra Aufwand verbunden und natürlich auch einem Komfortverlust.

Mit dem neuerlichem Vorfall bei Microsoft habe ich mein (privates) Vertrauen in diese Firma nun endgültig verloren. Ich wollte weg, weit weg. Naja, sinnbildlich gesprochen.

Ich machte mir ein paar Gedanken, wie es für meine Mails und Daten nun weitergehen sollte und entschloss mich, auf Postfix und Nextcloud setzen. Beides Open Source, beides seit Jahren erprobt und millionenfach eingesetzt, weltweit. Es gibt zahlreiche Dokumentationen, die einem die Installation und Konfiguration erleichtern würden.

Mir ist natürlich klar, dass mit solch einem Projekt die Sicherheit nicht frei Haus kommt. Ich bin dafür verantwortlich, mit allen Pros und Cons. Aber dafür bin ich auch frei, zumindest gefühlt.

In diesem Tutorial möchte ich euch zeigen, wie auch ihr diese Freiheit erlangen könnt 😉 Nur Spass. Hier wird keiner erlöst, nur an die Hand genommen.

Voraussetzung:

Ihr benötigt einen Server, der aus dem Internet erreichbar ist. Es gibt günstige VPS Angebot schon ab 4-5€ im Monat. Für den Heimgebrauch völlig ausreichend. Im Tutorial wird Ubuntu 22.04 verwendet. Gezeigte Befehle sollten aber auf allen aktuellen Debian basierten Systemen funktionieren.

Ziel:

In diesem Tutorial zeige ich euch, wie ihr Postfix(MTA) mit Dovecot(MDA/LDA) und die Benutzerspeicherung in eine MySQL Datenbank bewerkstelligt. Ausserdem richten wir das automatische Virenscanning via ClamAV ein und filtern unsere Mails nach SPAM via Spamassassin. Auch das Signieren ausgehender mails via OpenDKIM werde ich beschreiben. Zusätlich richten wie Dovecot-Sieve ein und können so bereits eingehende Mails nach bestimmten Kriterien filtern und in entsprechende Mailbox-Ordnern einsortieren. Am Ende des Tutorials sichern wir unseren Server noch etwas weiter ab, sofern noch nicht selbst von eurer Seite geschehen.

Die Installation bzw. Einrichtung von Nextcloud als Ersatz für OneDrive werde ich in diesem Tutorial nicht besprechen. Dazu verweise ich auf diesen Artikel.Das Video ist sehr ausführlich und die nötigen Befehle sind sehr gut dokumentiert.

Inhaltsverzeichnis:

1.) Pakete installieren

2.) Zertifikate

3.) MySQL

4.) Postfix

5.) Dovecot

6.) Spamassassin

7.) Dovecot-Sieve Filter

8.) OpenDKIM

9.) Serverabsicherung

10.) To do’s


1.) Pakete installieren

Folgende Pakete werden installiert:

sudo apt install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql mysql-server dovecot-sieve

Wir wählen „Internet Site“ aus.

Hier tragen wir unsere Domain ein, keinen Hostnamen.

2.)Zertifikat besorgen

Für Postfix und Dovecot benötigen wir ein SSl Zertifikat. Dieses lässt sich kostenlos über Let’s Encrypt beziehen. Auf Ubuntu 22.04 lässt sich der Certbot Service, welcher zum Abholen der Zertifikate benötigt wird, wie folgt installieren:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Weiter geht es dann mit folgendem Befehl:

sudo certbot certonly --standalone

Damit haben wir den Private Key und das Zertifikat unter /etc/letsencrypt/live/example.com/ liegen.


3.) MySQL

Sofern ihr bei der Installation von MySQL via apt nicht danach gefragt wurdet ein root Passswort anzulegen, könnt ihr dies mit nur weng Aufwand nachholen. Einen Artikel dazu habe ich hier geschrieben.

Nachdem dies erledigt ist loggen wir uns zunächst beo MySQL ein:

sudo mysql -u root -p

Wir legen uns eine komplett neue Datenbank namens mailserver an:

CREATE DATABASE mailserver;

Nun legen wir einen User an, der später von Postfix bzw. Dovecot benötigt wird, um sich zu authentisieren.

CREATE USER 'mailuser'@'127.0.0.1' IDENTIFIED BY 'password';

Dieser user benötigt nur Rechte zum Abfragen auf die Datenbank, also „Select“:

GRANT SELECT ON mailserver.* TO 'mailuser'@'127.0.0.1';
	
mysql > FLUSH PRIVILEGES;

Als nächstes legen wir eine Tabelle an, die unsere Domain(s) beinhalten wird:

CREATE TABLE `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Als nächstes folgt eine Tabelle, die alle Emailadressen und zugehörige Passwörter enhalten wird:

CREATE TABLE `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `password` varchar(106) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Nun zum Schluss eine weiter Tabelle, die Aliase beherbergt. Aliase sind Weiterleitungsadressen. Wenn z.B. eure Hauptadresse test@example.com ist, dann ist es möglich via Alias z.B. postmaster@example.com and die Hauptadresse weiterzuleiten.

CREATE TABLE `virtual_aliases` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `source` varchar(100) NOT NULL,
  `destination` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Nun befüllen wir unsere Tabelle virtual_domains mit den Domains, die wir später als Maildomains nutzen wollen:

INSERT INTO `servermail`.`virtual_domains` (`id` ,`name`) VALUES
('1', 'example.com'),
('2', example2.com');

Zu einem späteren Zeitpunkt kann man immer noch neue Domains hinzufügen.

An dieser Stelle müssen wir MySQL verlassen, um uns für jeden User ein sicheres Passwort zu generieren, bzw. aus dem Passwort einen Hash. Nicht das Passwort, sondern der Hash wird in der Tabelle gespeichert.

Der Hash wird mit dem tool doveadm generiert:

sudo doveadm pw -s SHA512-CRYPT

Nachdem Ihr den Befehl ausgeführt habt müsst Ihr 2x das Passwort eingeben. Danach wird auch ein ähnlicher Hash, wie hier angezeigt:

{SHA512-CRYPT}$6$WHttEk/nzN7fk4TM$x/KN3.UCQA1DH3euDMpcaAij520HBOhTtyWqf2ALWbCk/CZLnRtbNKyAOJIjGCmNIMAtfpctOXNfvFcu7PxmQ

Der eigentliche Hash, also den Teil, den wir in die Tabelle in MySQL eingeben, ist alles rechts von der letzten geschweiften Klammer ( } ).

Im Folgenden erzeugen wir einen Eintrag mit dem User test@example.com und seinem zugehörigen Passwort. Dies sind also die Logindaten für den späteren Einsatz im Mailclient.

INSERT INTO `servermail`.`virtual_users`(`id`, `domain_id`, `password` , `email`) VALUES
('1','1','$6$rUbxIRkrdao.Gzwm$McnUc0DZ4mMZ7H1mPO3yYgytJ0s5Z3KqTilwUNWWpbHVdStpj87Vz3u.EPAEoYvq/EZsdzGOc0/vt7iMJRyPD.', 'test@example.com');

Zum überprüfen, ob obige Daten auch correct in die Tabelle eingtragen wurden, kann man folgenden Befehl nutzen:

SELECT * FROM mailserver.virtual_users;

Einen Alias können wir wie folgt hinzufügen:

INSERT INTO mailserver.virtual_aliases (domain_id, source, destination) VALUES ('1', 'alias@example.com', 'test@example.com');


4.) Postfix

Nun ist die Konfiguration von Postfix an der Reihe. Bevor wir aber die Konfigdateien editieren, machen wir ein Backup:

cd /etc/postfix
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
sudo cp /etc/postfix/master.cf /etc/postfix/materer.cf.bak

Richtet eure main.cf wie folgt ein. Achtet dabei auf den individuelle Pfad bei key und cert ( unten fett dargestellt).

# See /usr/share/postfix/main.cf.dist for a commented, more complete version

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
# fresh installs.
compatibility_level = 2

# TLS parameters
smtpd_tls_cert_file=/etc/letsencrypt/live/example.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/example.com/privkey.pem
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous

# Authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

# Restrictions
smtpd_helo_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname
smtpd_recipient_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_recipient,
        reject_unknown_recipient_domain,
        reject_unlisted_recipient,
        reject_unauth_destination
smtpd_sender_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_sender,
        reject_unknown_sender_domain
smtpd_relay_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        defer_unauth_destination

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = example.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydomain = example.com
myorigin = $mydomain
mydestination = localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# Handing off local delivery to Dovecot's LMTP, and telling it where to store mail
virtual_transport = lmtp:unix:private/dovecot-lmtp

# Virtual domains, users, and aliases
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

       
# Even more Restrictions and MTA params
disable_vrfy_command = yes
strict_rfc821_envelopes = yes
#smtpd_etrn_restrictions = reject
#smtpd_reject_unlisted_sender = yes
#smtpd_reject_unlisted_recipient = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtp_always_send_ehlo = yes
#smtpd_hard_error_limit = 1
smtpd_timeout = 30s
smtp_helo_timeout = 15s
smtp_rcpt_timeout = 15s
smtpd_recipient_limit = 40
minimal_backoff_time = 180s
maximal_backoff_time = 3h

# Reply Rejection Codes
invalid_hostname_reject_code = 550
non_fqdn_reject_code = 550
unknown_address_reject_code = 550
unknown_client_reject_code = 550
unknown_hostname_reject_code = 550
unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550

Nun richten wir die 3 files ein, die in der /etc/postfix/main.cf schon deklariert sind. Das erste wäre die

/etc/postfix/mysql-virtual-mailbox-domains.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

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

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

/etc/postfix/mysql-virtual-alias-maps.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

Zum Abschluss starten wir Postfix einmal neu:

sudo systemctl restart postfix

Postfix testen:

Die ersten beiden Befehle sollten als Rückgabewert die ‚1‘ liefern. Beim dritten Befehl wird die Hauptmailadresse ausgeben, auf den der Alias verweist.

sudo postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

sudo postmap -q email1@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

sudo postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Als nächstes kümmern wir uns um die Einstellungen in der master.cf. Diese Konfigurationsdatei startet und steuert die Postfix Prozesse.

#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
#smtp      inet  n       -       -       -       1       postscreen
#smtpd     pass  -       -       -       -       -       smtpd
#dnsblog   unix  -       -       -       -       0       dnsblog
#tlsproxy  unix  -       -       -       -       0       tlsproxy
submission inet n       -       y      -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  ...

Abschliessend nehmen wir noch Änderung an den Rechten von /etc/postfix vor, sodass die Gruppe ‚other‘ keine keinenn Zugriff mehr hat.

sudo chmod -R o-rwx /etc/postfix
sudo systemctl restart postfix


5.) Dovecot

Dovecot dient für unsere Zwecke als IMAP Server und LDA ( local delivery agent ). Er nimmt die Mails von Postfix an und liefert sie an die User aus.

Als erstes machen wir wieder Backups von den zu bearbeitenden Konfigdateien:

sudo cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.bak
sudo cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.bak
sudo cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.bak
sudo cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.bak
sudo cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.bak
sudo cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.bak

Danach ändern wir die Konfigs auf die gezeigten Werte:

/etc/dovecot/dovecot.conf

## Dovecot configuration file
...
# Enable installed protocols
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap pop3 lmtp

postmaster_address = postmaster at example.com
...

/etc/dovecot/conf.d/10-mail.conf

...
mail_location = maildir:/var/mail/vhosts/%d/%n/
...
mail_privileged_group = mail
...

Erstellt nun das Verzeichnis /var/mail/vhosts und Unterverzeichnis eurer Domain. Ersetzt example.com mit dem Namen eurer Domain:

sudo mkdir -p /var/mail/vhosts/example.com

Nun benötigen wir einen Systemuser und eine Systemgroup jeweils mit dem Namen vmail. Diese werden dann die Mails auf dem Server lesen können:

sudo groupadd -g 5000 vmail
sudo useradd -g vmail -u 5000 vmail -d /var/mail
sudo chown -R vmail:vmail /var/mail

Als nächstes editiert die Datei /etc/dovecot/conf.d/10-auth.conf

...
disable_plaintext_auth = yes
...
auth_mechanisms = plain login
...
!include auth-system.conf.ext
...
!include auth-sql.conf.ext
...

In der Datei /etc/dovecot/conf.d/auth-sql.conf.ext stehen die Authentisierungs-und Storageinformationen.Passt sie wie folgend gezeigt an:

...
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
...
#userdb {
#  driver = sql
#  args = /etc/dovecot/dovecot-sql.conf.ext
#}
...
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}
...

In der Datei /etc/dovecot/dovecot-sql.conf.ext stehen die MySQL Verbindungsparameter:

...
driver = mysql
...
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailuserpass
...
default_pass_scheme = SHA512-CRYPT
...
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
...

Nun noch ein paar Änderungen an Benutzern und Zugriffen:

sudo chown -R vmail:dovecot /etc/dovecot
sudo chmod -R o-rwx /etc/dovecot

Nehmt folgende Änderungen an der Datei /etc/dovecot/conf.d/10-master.conf vor:

Achtet bitte auf korrekte Formattierung bei den {geschweiften Klammern}. Schnell vergisst man diese korrekt zu schliessen

...
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
  ...
}
...
service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}
...

Zusätzlich in der selben Datei sucht nach service lmtp und nehmt folgende Einstellungen vor:

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

Dann sucht nach service auth und macht die gezeigten Einstellungen:

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

  unix_listener auth-userdb {
    mode = 0600
    user = vmail
  }
...
  user = dovecot
}
...

In der service-auth-worker section wird user unkommentiert und auf vmail gesetzt:

...
service auth-worker {
  ...
  user = vmail
}

Nun binden wir das bereits im Postfix aktive Zertifikat samt Key in Dovecot ein:

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

..
# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
ssl = required
...
ssl_cert = </etc/letsencrypt/live/example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/example.com/privkey.pem

Zu guter letzt startet ihr noch den dovecot neu:

sudo systemctl restart dovecot

Testen des Mailservers:

Nun ist es an der Reihe zu testen, ob unser Postfix in der Lage ist, Mails zu versenden. Dazu benutzen wir das CMD Tool mailutils

sudo apt-get install mailutils

Wir nehmen den anschliessenden Befehl, um von der Kommandozeile eine Mail an einen externen Empfänger zu senden, wie z.B. an eine Gmail-Adresse:

echo "Email body text" | sudo mail -s "Email subject line" recipient@gmail.com -a From:test@example.com

Schaut nun nach, ob die Mail bei eurem extern Anbieter angekommen ist. Falls Ja, dann drückt auf „Antworten„. So könnt ihr gleich testen, ob euer Postfix die Mail auch korrekt eingeliefert bekommt. Dies checkt ihr, indem folgender Befehl genutzt wird:

sudo mail -f /var/mail/vhosts/example.com/email1

Achtung: Ihr müsst vorher bei euren DNS Anbieter die korrekten Werte für z.B. den MX Record gesetzt haben, ansonsten weiss Google nicht, wohin er die Mails schicken soll.

Einrichten eines Mailclients:

Zum testen sollte im Prinzip jeder Mailclient funktionieren. Ich habe Thunderbird verwendet.

  • Username = eure Hauptmailadresse, z.B. test@example.com
  • Password = das Passwort, für welches ihr den Hashes erstellt hattet
  • Server = wie im DNS angegeben, z.B. mail.example.com
  • IMAPs = es wird der Port 993 genutzt und die Einstellung auf SSL/TLS gesetzt
  • SMTP = der Port ist 587 und die SSL Security muss auf STARTTLS gstellt werden

Achtung: Thunderbird wird anfangs versuchen, die Accounteinstellungen automatisch zu finden. Dies wird aber fehlschlagen. Danach lassen sich o.g Werte manuell eintragen.


6.)Spamassassin

Als erstes installieren wir die nötigen Pakete:

sudo apt-get install spamassassin spamc

Dann noch einen Benutzer spamd anlegen:

sudo adduser spamd --disabled-login

Die Datei /etc/default/spamassassin wird wie folgt angepasst:

...

HOMEDIR="/home/spamd/"

OPTIONS="--create-prefs --max-children 5 --username spamd --helper-home-dir ${HOMEDIR} -s ${HOMEDIR}spamd.log"

PIDFILE="${HOMEDIR}spamd.pid"

...

CRON=1

Nun noch die /etc/spamassassin/local.cf konfigurieren:

...

rewrite_header Subject ***** SPAM _SCORE_ *****
report_safe             0
required_score          5.0
use_bayes               1
use_bayes_rules         1
bayes_auto_learn        1
skip_rbl_checks         0
use_razor2              0
use_dcc                 0
use_pyzor               0

...

Ob ihr razor2, dcc oder pyzor zur weiteren Spamerkennung einsetzen wollt hängt vom persönlichen Bedürfnis ab.

An dieser Stelle schaut euch mal die Seite www.spamhaus.com an. Dort erhaltet ihr Infos, wie man deren RBLs ( Real Time Blacklists ) in Postfix einbindet

Als nächstes passt ihr noch die /etc/postfix/master.cf an, sodass eingehende mails auch auf SPAM geprüft werden:

...

smtp      inet  n       -       -       -       -       smtpd
-o content_filter=spamassassin

...

spamassassin unix -     n       n       -       -       pipe
  user=spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}

Nun aktivieren wir spamassassin, starten ihne und den postfix gleich auch noch:

sudo systemctl start spamassassin
sudo systemctl enable spamassassin

sudo systemctl restart postfix


7.)Clamav Virenprüfung

An dieser Stelle konfigurieren wir noch die Einbindung von clamav in postfix, sodas eingehende Mails zusätlich noch auf das Vorhandensein von Viren geprüft werden. Dazu installiert ihr folgende Pakete:

sudo apt install clamav clamsmtp

Anschliessend prüfen wir die Datei /etc/clamsmtpd.conf auf folgende Einträge bzw. unkommentieren die Zeilen, wie unten zu sehen:

OutAddress: 10025
Listen: 127.0.0.1:10026
ClamAddress: /var/run/clamav/clamd.ctl
Header: X-AV-Checked: ClamAV using ClamSMTP
TempDirectory: /var/spool/clamsmtp
PidFile: /var/run/clamsmtp/clamsmtpd.pid
Quarantine: on
User: clamsmtp
VirusAction: /etc/clamav/script.sh

IM Falle des Fundes eines Viruses werden wir via Mail benachrichtigt. Dazu haben wir, wie in der letzten Zeile geschrieben, ein Skript deklariert. Dieses Skript erstellen wir nun unter /etc/clamav/script.sh und fügen den nachstehenden Inhalt ein und passen es den eigenen Bedürfnissen nach an:

#!/bin/sh
DOMAIN=example.com
ADMIN=user@example.com
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
LINE="-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
if [ X`echo $SENDER | egrep $DOMAIN` != "X" ];
then MAILTO=$SENDER,$ADMIN
else MAILTO=`echo "$RECIPIENTS" | egrep $DOMAIN | tr '\n' ','`$ADMIN
fi

(echo "Virus name: $VIRUS"
echo "Sender: $SENDER"
echo "Recipient(s): $RECIPIENTS"
echo
if [ "x$EMAIL" != "x" ] && [ -f $EMAIL ]
then
echo "Quarantined to: $EMAIL"
fi
) | cat -v | mail -s "$VIRUS found on mailserver" $MAILTO 

Das Skript braucht noch die Rechte zum ausführen:

chmod +x /etc/clamav/script.sh

Zu guter letzt nur noch den clamav server neu starten:

sudo systemctl restart clamsmtp

Postfix muss jetzt noch wissen, dass es Mails an clamsmtpd übergeben soll. Dazu fügen wir folgendes in die /etc/postfix/master.cf zusätzlich ein:

scan unix - - n - 16 smtp
  -o smtp_send_xforward_command=yes

127.0.0.1:10025 inet n - n - 16 smtpd
  -o content_filter=
  -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
  -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks_style=host
  -o smtpd_authorized_xforward_hosts=127.0.0.0/8


7.)Dovecot-Sieve Filter

Mit Sieve sind wir in der Lage, eingehende Mails nach bestimmte Mustern zu filtern. Erkennt Sieve z.B., dass ein Email, nachdem sie durch den Spamfilter gelaufden ist, im Betreff *****SPAM***** stehen hat, oder dex X-SPAM-TAG auf Yes steht, dann kann diese Mail direkt in ein dafür vorher definiertes Verzeichnis verschoben werden.

Zum Anfang installiert ihr das nötige Paket:

sudo apt install dovecot-sieve

Nun passt ihr die Datei /etc/dovecot/conf.d/20-lmtp.conf an:

protocol lmtp {
    # Space separated list of plugins to load (default is global mail_plugins).
    mail_plugins = $mail_plugins sieve
}

Als nächstes werden zusätzliche Einstellungen in der /etc/dovecot/dovecot.conf vorgenommen:

plugin {
    sieve_before = /var/vmail/sieve/spam-global.sieve
    sieve_dir = /var/vmail/%d/%n/sieve/scripts/
    sieve = /var/vmail/%d/%n/sieve/active-script.sieve
}

Die Verzeichnis-und Dateinamen könnt ihr wennn gewünscht so übernehmen, müsst dann aber dafür sorgen, diese noch anzulegen:

cd /var/vmail
mkdir sieve
cd sieve
touch spam-global.sieve
chown -R vmail:vmail /var/vmail/sieve/

Der Eintrag sieve-before definiert ein Skript, welches noch vor eventuellen Userskripten ausgeführt wird. Es hat somit die höchste Priorität. In nachfolgenden Beispiel soll dieses Skript erkennen, ob die Mail als SPAM eingestuft wurde und diese dann in das Verzeichnis ***SPAM*** verschieben. Dieses Verzeichnis muss in der Mailbox bereits existieren.

require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
  fileinto "***SPAM***";
}

Zum Schluss starten wir dovecot neu, damit diese Änderungen wirksam werden.

sudo systemctl restart dovecot


8.)OpenDKIM

DKIM ist ein Email-Authentisierungslösung, die Sender und Empfänger vor SPAM, Phishing und Spoofing schützt. Es basiert auf einer Public Key Kryptografie.

Der Email-Versender, also unser Postfix, signiert mit seinem private key jede ausgehende Mail. Der Empfänger kann anhand des öffentlichen Schlüssels ( im DNS hinterlegt ) überprüfen, ob die Mail Signatur vom rechtmässigen Absender kommt. I.d.R sind Mailserver so konfiguriert, dass sie diesen Prozess einhalten. Dadurch, dass die Authentizität des Absenders bestätigt wurde, wird der Mail ein deutlich kleinerer SPAM Scoring Wert zugeordnet. Praktisch gesehen bedeutet dies, dass unsere Mails mit geringerer Wahrscheinlichkeit als SPAM markiert werden. Dies steigert unsere Reputation.

OpenDKIM ist die Open Source Lösung und lässt sich wie folgt installieren:

sudo apt install opendkim 

Im nächsten Schritt editieren wie die Datei /etc/opendkim.conf:

Mode                   sv
Domain                 example.com
RequireSafeKeys        False
Keyfile                /etc/opendkim/keys/example.com/default.private  
KeyTable               /etc/opendkim/KeyTable
SigningTable           refile:/etc/opendkim/SigningTable
ExternalIgnoreList     refile:/etc/opendkim/TrustedHosts
InternalHosts          file:/etc/opendkim/TrustedHosts

In der gleichen Datein existiert ein Eintrag der bestimmt, auf welchem Port OpenDKIM läuft. Standardmässig ist dies der Port 8891:

 Socket for the MTA connection (required). If the MTA is inside a chroot jail,
# it must be ensured that the socket is accessible. In Debian, Postfix runs in
# a chroot in /var/spool/postfix, therefore a Unix socket would have to be
# configured as shown on the last line below.
#Socket                 local:/run/opendkim/opendkim.sock
Socket                  inet:8891@localhost
#Socket                 inet:8891
#Socket                 local:/var/spool/postfix/opendkim/opendkim.sock

PidFile                 /run/opendkim/opendkim.pid

Als nächstes editieren wir die Datei /etc/opendkim/SigningTable Diese Datei weisst das System an, ausgehende Mails mit einer bestimmten Domain zu signieren, hier im Bespiel ist es example.com:

*@example.com default._domainkey.example.com

Nun passen wir die /etc/opendkim/KeyTable an. Dort wird der Pfad des private keys angegeben.

default._domainkey.example.com example.com:selector:/etc/opendkim/keys/example.com/default.private

In der /etc/opendkim/TustedHosts fügen wir unsere Domain ein:

127.0.0.0.1
::1
*.example.com

Jetzt ist es an der Zeit, unseren key zu generieren. Als erstes legen wir das Verzeichnis an:

sudo mkdir /etc/opendkim/keys/example.com

Und jetzt diesen Befehl:

sudo opendkim-genkey -b 1024 -d example.com -D /etc/opendkim/keys/example.com -s default -v

Die Schlüsselstärke ist in dem Bespiel auf 1024 bit gesetzt. Mehr geht natürlich immer und erhöht demnach auch die Sicherheit des Schlüssels.

Wir schützen das /etc/opendkim/keys Verzeichnis, indem wir den Benutzer opendkim zum Besitzer machen:

sudo chown opendkim:opendkim /etc/opendkim/keys -R 

Den privaten key haben wir nun an der richtigen Stelle. Als nächstes müssen wir noch den öffentliche Schlüssel im DNS veröffentlichen. Diesen öffentlichen Schlüssel ruft man folgendermassen ab:

root@mail:~# cat /etc/opendkim/keys/example.com/default.txt 

default._domainkey	IN	TXT	( "v=DKIM1; h=sha256; k=rsa; "
	  "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0ebeOixh5A92cfkbogw9YY8WwbgkyHI4I9dIrUc6pBcTEMhIiCIxqgM8xXhwU139FJp6/2tMrAiSbGXSL6MKf4Bp7/Ni3WnSluV2CaRf1Nn2ncmzn8kP5VfMukALLeRePaZODkhFIbz2JXqx6aqwpL5EUMdwQYNEHS9HT+Uf4RwIDAQAB" )  ; ----- DKIM key default for example.com

Der relevante Teil aus der /etc/opendkim/keys/example.com/default.txt ist:

v=DKIM1; h=sha256; k=rsa; "
	  "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0ebeOixh5A92cfkbogw9YY8WwbgkyHI4I9dIrUc6pBcTEMhIiCIxqgM8xXhwU139FJp6/2tMrAiSbGXSL6MKf4Bp7/Ni3WnSluV2CaRf1Nn2ncmzn8kP5VfMukALLeRePaZODkhFIbz2JXqx6aqwpL5EUMdwQYNEHS9HT+Uf4RwIDAQAB

Im öffentlichen DNS der eigenen Doamin wird ein neuer Eintrag vom Typ TXT angelegt. Der (Host) Name ist default._domainkey, TTL kann auf Auto stehen bleiben. Als Wert bzw. Inhalt ist obiger Code einzutragen.

Hier mein Eintrag aus dem DNS:

Im Folgenden müssen wir noch Postfix beibringen, dass ausgehende Mails an OpenDKIM übergeben werden. Dies wird durch nachstehenden Eintrag in der /etc/postfix/main.cf erreicht:

smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters milter_default_action = accept 

Zu guter letzt starten wir opendkim und postfix neu:

sudo systemctl restart opendkim
sudo systemctl restart postfix


9.)Server absichern

In den allermeisten Fällen wird der Mailserver direkt im Internet hängen. Um die Sicherheit zu erhöhen wäre es ratsam, auch dort eine Firewall vorzuschalten, wie z.B. Pfsense Community edition. Viele Hoster lassen dieses Szenario zu. Der Vorteil liegt klar auf der Hand. Auf der Pfsense lässt sich der Zugriff zum Mailserver weiter einschränken bzw. überwachen. Durch den Einsatz von Snort lassen sich Angriffe erkennen und die IP der Angreifer sperren. Auch liesse sich durch Pfblocker NG der Zugriff nach Geolocations einschränken.

Natürlich gibt es dies nicht zum Nulltarif. Der zusätliche Server will bezahlt werden. Wer diese Kosten scheut, bzw. aus anderen Gründen davon absieht, sollte folgende Tipps zur Grundabsicherung des Servers berücksichtigen.

Aktivieren von fail2ban:

Fail2ban ist ein tool, welches definierte logs nach verdächtigen Aktivitäten, wie fehlgeschlagene Logins, untersucht und entsprechend den Absender blockieren ( via iptables ) kann. Dies reduziert Brute-Force Attacken enorm.

Unter diesem Link findet ihre meine anleitung zu fail2ban.

Einspielen von Updates:

Das regelmässige Einspielen von Updates ist für die allgemeine Sicherheit essentiell. Entweder stellen wir uns einen Wecker, der uns mindestens 1x die Woche daran erinnert, oder wir lassen uns automatisch via Email benachrichtigen, sobald ein Update für das System bereitsteht, bzw. das Update automatisch einspielen. Letzters ist nicht ganz ohne Risiko, da ein Update immer auch die Gefahr in sich birkt, etwas kaputt zu machen.

Ein nütliches Tool für diese Aufgabe ist cron-apt, welches bei Ubuntu vorhanden ist.

Apache mit Modsecurity absichern:

Wer dem Link zum installieren von Nextcloud gefolgt ist, der hat neben Postfix nun auch Apache2 auf seinem System. Apache2 liefert sog. mods mit. Eines davon nennt sich security2. Es lässt sich einfach über folgenden Befehl aktivieren:

sudo a2enmod security

Zu modesecurity habe ich bereits einen Artikel geschrieben.

SSH Daemon absichern:

Viele Angriffsversuche, gerade Brute-Force Attacken, zielen auf den SSH Dienst. Aus diesem Grund ist es ratsam, den SSH Dienst zu härten. Dazu sollte man das root Login abstellen und die Authentisierung mittels Key aktivieren.

Um eine schwache Konfiguration auszumerzen existiert ein SSH Hardening Guide.

Firewall nutzen:

Ubuntu bieten die Möglichkeit, die intergrierte Firewall zu nutzen. Diese nennt sich UFW. Hier wird gut beschrieben, wie diese zu nutzen ist.

Monitoring:

Ein Überwachen des Systems, z.B. mittels checkmk, kann ebenfalls zur Sicherheit beitragen, da z.B. neue Systemprozesse, die vom Angreifer gestaret werden, erkannt und gemeldet werden können. Auch eine übermässige Systemlast, ebenfalls durch Angreifer verurssacht, liese sich so schnell erkennen. Darüber hinaus existieren noch weitere Tools, die durch Überwachung einen enormen Sicherheitsgewinn bieten. Wazuh wäre definiv ein wichtiges.

Natürlich sind oben genante Massnahmen nicht abschliessend, aber sie sollten für eine Grundabsicherung ausreichend Schutz bieten.

Security Audit:

Abschliessen sei noch das Security Audit erwähnt. Eine gute und auch kostenlose Variante stellt der Greenbone Security Assistant bereit. Mit dieser Art von Audit lassen sich viele Lücken, aber auch Fehler in der Konfiguration finden.


To do’s:

Ganz oben auf meiner Liste steht nocht die Verbesserung der Möglichkeit, neue Benutzer, Aliase und Domänen in MySQL anzulegen. Wir hatten uns ja in diesem Tutorial auf die Kommandozeile beschränkt. Für ein kleines System ist dies nicht so schlimm, aber komfortabler wäre es definitiv, dies mittels eines Web Interfaces zu erledigen.

Zusätlich werde ich bei Gelegenheit die Option prüfen, wie man im Thunderbird mittels Plugins eigene Sieve Filter erstellen kann.

Sollte euch etwas unklar sein, oder ihr habt Fehler gefunden, so nutzt gerne die Kommentarfunktion.

Print Friendly, PDF & Email
Abonnieren
Benachrichtige mich bei

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x