Dedicated Server als Webserver und Mailserver einrichten (Version Juli 2003)

Die aktuelle Version dieses Artikels finden Sie hier.

 

Wer nur mal eben drei Seiten, ein Dutzend Photos und ein schwach frequentiertes Gästebuch ins Internet stellen will, ist sicher mit einem Webhosting-Angebot für EUR 9,95 gut versorgt. Wer einen größeren Auftritt will, mehr Flexibilität braucht und auch seinen Mailverkehr nicht in fremde Hände legen will, bekommt seinen eigenen Server im Internet heute zu phantastisch günstigen Preisen.

Ich selbst habe Erfahrungen mit einem amerikanischen Anbieter von Dedicated Servern gemacht, der offenbar mit jeder Facette seines Geschäfts erhebliche Probleme hatte. Ich bin kurzerhand umgestiegen zu einem deutschen Anbieter, der sehr erfolgreicher Vorreiter im Lowcost-Segment ist, und zwar nicht der allerbilligste ist, aber gute Kritiken in der Presse bekommen hat. Soviel vorweg: Ich hatte bisher keinen Grund zu klagen.

Einige Dinge sind zu beachten:

  1. Man muß ein wenig von Linux verstehen.

  2. Die eingesetzten Hardwarekomponenten sind für diesen Preis kaum Erste Wahl. Man sollte seine Daten gut sichern und auch etwa wissen, was man zum Einrichten des Servers alles getan hat, ohne bei der zweiten Installation wieder alle Howtos suchen und studieren zu müssen. Es ist auch immer empfehlenswert, das Verzeichnis /etc mit seinen Unterverzeichnissen aufzuheben.

  3. Man sollte seinen Server im Auge behalten. Wer sich überhaupt nicht erlauben kann, im Internet nicht erreichbar zu sein, kommt mit einem Dedicated Server-Billigangebot nicht aus. Wer nicht länger als 6 Stunden offline sein will, sollte die Anwesenheit seines Servers und die korrekten Grundfunktionen des Mailsystems und des Webservers automatisiert prüfen. (Das ist aber nicht Gegenstand dieses Artikels.)

  4. Man muß sehr achtgeben, daß man nicht durch einen unbedachten Schritt seinen Server außer Betrieb setzt. Fehler beim Konfigurieren des Paketfilters sind dafür bevorzugte Kandidaten. Wirklich ärgerlich ist es, wenn solche Fehlkonfigurationengleich nach dem Neustart wieder wirksam werden.

Als Betriebssystem empfehle ich Debian. Auf dem Schreibtischarbeitsplatz taugt es überhaupt nichts, die Debian-Leute haben bislang andere Prioritäten als die graphische Oberfläche und Treiberunterstützung. Für Debian spricht die konservative Entwicklungsphilosophie, die ich auch bei OpenBSD schätze, und das ausgefeilte Paketkonzept, das aber nicht RPM-kompatibel ist. Für Server ist Debian hervorragend.

Grundinstallation

Wir haben vom Provider einen SSH-Zugang mit Root-Paßwort bekommen. Das wird jetzt sofort geändert. Es loggt sich dann in Zukunft nur noch ein normaler User ein, aber nicht über Telnet, sondern über die Secure Shell (SSH) mit Protokollversion 2. Diese normale Nutzer wird dann Root mit dem Kommando

su -

Unter Windows gibt es als SSH-Client das Programm "putty".

Nutzer

Zuerst wird ein normaler Nutzer angelegt. Das Root-Paßwort wird dabei auch gleich mit geändert.

groupadd -g 1000 mygroup
adduser --gid 1000 --uid 1000 myself
passwd myself
passwd root

Der Shell-Prompt wird mit einigen nützlichen Informationen versehen, die die Orientierung auf dem vollgepflasterten Bildschirm erlauben:

cd /root
vi .bash_profile
PATH=/usr/local/bin:/usr/bin:/bin
[ X$USER = Xroot ] && PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
export PATH HOME TERM
umask 022
alias ll='ls -laF'
PS1A=`hostname|sed -e "s/\([^.]*\).*/\1/"`
PS1="$PS1A $USER "'`date +%H:%M` $PWD'
[ X$USER = Xroot ] && PS1="$PS1 # " || PS1="$PS1 $ "

cp .bash_profile ~myself
chown myself.mygroup ~myself/.bash_profile

SSH-Zugang

Zu putty gehört "puttygen", mit dem ein Schlüsselpaar generiert wird.

Um den Linux-Server auf SSH vorzubereiten, fügt man in dem SSH-Konfigurationsfile ein paar Zeilen ein bzw. ändert einige Zeilen:

vi /etc/ssh/sshd_config
Protocol 2
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
AllowUsers myself
ClientAliveInterval 15
ClientAliveCountMax 3

Nur der Nutzer myself ist zugelassen. Für diesen muß noch etwas in seinem Heimatverzeichnis getan werden:

cd ~myself
mkdir .ssh
cd .ssh
vi authorized_keys
ssh-rsa AAAAdhjdneihwgdhwgvjkh/IUZHGO?iubnmpo5ij3m9hhc/876ghm9gh395p086ghm590ghpo5ibnm3pcv
IUNfbuhgbujzn87n98g*ohnbIUN/oiun897m095487tzncuoiguo394c85m comment

Die Zugriffsrechte sind wichtig:

chown myself.myself * .
chmod 600 *
chmod 700 .

Jetzt wird der SSH-Zugang getestet. Bevor das funktioniert hat, wird das aktuelle Putty-Terminalfenster nicht geschlossen. Danach wird der Zugang zum Server nur noch für den Besitzer des richtigen Schlüssels erlaubt:

vi /etc/ssh/sshd_config
PasswordAuthentication no

Paketfilter

Als nächste dringende Sicherheitsmaßnahme werden Paketfilterregeln angelegt. Welche benötigt werden, hängt natürlich von den verwendeten Protokollen ab. In dem hier beschriebenen Einsatzszenario reicht folgendes:

vi /etc/iptables.active.sh
#!/bin/sh
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -m icmp --icmp-type 5 -j DROP
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 110 -j ACCEPT
iptables -A INPUT -p tcp --dport 995 -j ACCEPT

sowie:

vi /etc/iptables.inactive.sh
#!/bin/sh
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

Aktiviert wird das mit einer Reihe von Kommandos:

chmod 750 /etc/iptables.active.sh
/etc/iptables.active.sh
/etc/init.d/iptables save active
chmod 750 /etc/iptables.inactive.sh
/etc/iptables.inactive.sh
/etc/init.d/iptables save inactive
/etc/init.d/iptables start
cd /etc/rc2.d
ln -s ../init.d/iptables S95iptables

Achtung: Nie die iptables-Kommandos einzeln eingeben, sondern immer nur en bloc als Shellscript. Sonst hat man sich schnell ausgesperrt und ist auf die gute Laune des Providers angewiesen.

Zusatzpakete

Es ist an der Zeit, etwas Software nachzuinstallieren.

dselect

Es wird ausgewählt:

kernel-source-2.4.xx
less

Nach Auslösen des Installationsvorgangs wird möglicherweise eine größere Anzahl abhängiger Packages installiert. Das ist Sinn dieser Übung. Ansonsten brauchen wir die Kernelquellen in unserem Anwendungsfall nicht. Der Neubau eines Kernels ist auf einem Rechner, bei dem man keinen Zugang zur Konsole hat, ein unterhaltsames Abenteuer mit ungewissem Ausgang.

Es folgen im nächsten Durchgang weitere Softwarepakete:

dselect
ntp-refclock
mysql-server
libpam-mysql
openssl
postfix-tls
postfix-mysql
libsasl-digestmd5-plain
krb5-user
courier-pop-ssl
courier-authmysql
apache
libapache-mod-auth-mysql
spamassassin
vsftpd

Uhrzeit

Der Server sollte immer die korrekte Uhrzeit haben. Das ist, wie es sich für Server gehört, nicht die lokale Ortszeit oder gar eine Sommerzeit, sondern UTC. Die Einstellung erfolgt mit

tzconfig
... UTC

date MMDDhhmm

Der NTP-Dämon sorgt für regelmäßige Synchronisation mit Timeservern im Internet.

vi /etc/ntp.conf
server ptbtime1.ptb.de version 3
server ptbtime2.ptb.de version 3
server ntps1-0.cs.tu-berlin.de version 3
server ntps1-0.uni-erlangen.de version 3
server ntp0.fau.de version 3

/etc/init.d/ntp restart

Logging

Logging ist ein geeignetes Mittel, um die Gesundheit des Servers da draußen zu überwachen. Man kann lokal auf den Server loggen und regelmäßig nachsehen. Man kann auch auf einen Server loggen, der zuhause über eine dynamische IP-Adresse erreichbar ist. Das ist unter zweierlei Hinsicht nicht ganz befriedigend:

Ich habe beschlossen, diese Einschränkungen vorerst zu akzeptieren. Die Vorteile, alle Logs in ein eiziges File zu konsolidieren, überwiegen für mich die Nachteile. Die Syslog-Konfigurationsdatei des Servers enthält nur eine Zeile, der Rest wird gelöscht.

vi /etc/syslog.conf
*.* @beimir.dnsalias.net

Email

Sie betreiben Ihren Mailserver selbstverständlich als vollwertigen SMTP-Relay. Freilich können Sie Ihre Post auch über den Mailserver der Telekom schicken. Aber die freie Wählbarkeit der Absenderadresse kostet extra. Und zumindest früher war nicht zu vermeiden, daß die Telekom Ihre T-Online-Kennung einfach mit in den Email-Header einfügte. Wir beugen uns keinem Diktat und haben ja schon einen Dedicated Server dafür bezahlt, autark sein zu dürfen.

Dieser Relay ist natürlich nur für Sie und andere authentifizierte Benutzer zugänglich. Sonst haben Spammer nach spätestens zwei Tagen das weit offene Scheunentor entdeckt, Ihre Domain gerät in Verruf, und Sie können sich damit unter anständigen Menschen nicht mehr sehen lassen. Also Paßwort, wenn man senden will. Und daß Sie beim Abrufen von Email ein Paßwort angeben müssen, ist selbstverständlich.

Weiter: Damit Emailinhalte und Paßworte nicht im Klartext durch das Netz geistern, wird jede Verbindung über SSL bzw. TLS verschlüsselt. Wenn Sie Outlook benutzen, brauchen Sie sich keine Sorgen zu machen, ob das alles auch von Ihrem Arbeitsplatz aus funktioniert: Outlook beherrscht Paßworte, Verschlüsselung etc.

Als SMTP-Server kommt hier Postfix zum Einsatz. Der POP3-Dämon ist Courier, das Ihnen auch mit minimalen Abwandlungen als IMAP-Server zur Verfügung stehen kann. Den sollten Sie aber nicht nutzen, denn man lagert keine größeren Mengen Post im feindlichen Internet. Ich selbst betreibe zwei Mailserver: einen "draußen", von dem hier gerade die Rede ist, und einen "drin" hinter der Firewall. Das hier vorgestellte Konzept ist aber auf den internen zweiten Mailserver nicht angewiesen. Man kann auf seinen Mailserver auch mit dem Notebook von irgendwo unterwegs zugreifen.

Es gibt eine Reihe verschiedener Speichermöglichkeit für die Informationen, die ein Mailserver braucht (Nutzernamen, Paßworte, Aliase, Mailboxnamen etc.). Ich benutze für Postfix und Courier durchgehend MySQL, da dies übersichtlich und wartungsfreundlich ist.

Schlüsselgenerierung

Die SSL-/TLS-Schlüssel zur Absicherung des Email-Verkehrs liegen je nach Linux-Distribution unter /usr/share/ssl oder unter /etc/ssl. Wir gehen hier vom ersten Fall aus; andernfalls sind einige der nachfolgenden Konfigurationsdateien sinngemäß anzupassen. Auf eine Erläuterung der einzelnen Kommandos verzichte ich hier. Unter http://httpd.apache.org/docs-2.0/ssl/ssl_faq.html gibt es eine gute Erläuterung.
Zuerst erzeugen wir eine private Certification Authority (CA):

cd /usr/share/ssl
openssl genrsa -des3 -out ca.key 1024
openssl req -new -x509 -days 3653 -key ca.key -out ca.crt
... (einige Phantasieangaben zu Standort und Organisation)

Danach erzeugen wir einen Schlüssel für den Mailserver:

openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
... (einige Phantasieangaben zu Standort und Organisation)

Wenn wir, wie im Bild gezeigt, dazu noch einen internen Mailserver betreiben wollen, barucht dieser ebenfalls einen Schlüssel:

openssl genrsa -des3 -out iserver.key 1024
openssl req -new -key iserver.key -out iserver.csr
... (einige Phantasieangaben zu Standort und Organisation)

Beide Schlüssel (*.csr) signieren wir mit unserer eigenen CA. Dazu gibt es ein Script im Internet, das ich hier wiedergebe:

#!/bin/sh
##
## sign.sh -- Sign a SSL Certificate Request (CSR)
## Copyright (c) 1998-1999 Ralf S. Engelschall, All Rights Reserved.
##

# argument line handling
CSR=$1
if [ $# -ne 1 ]; then
    echo "Usage: sign.sign <whatever>.csr"; exit 1
fi
if [ ! -f $CSR ]; then
    echo "CSR not found: $CSR"; exit 1
fi
case $CSR in
    *.csr ) CERT="`echo $CSR | sed -e 's/\.csr/.crt/'`" ;;
    * ) CERT="$CSR.crt" ;;
esac

# make sure environment exists
if [ ! -d ca.db.certs ]; then
    mkdir ca.db.certs
fi
if [ ! -f ca.db.serial ]; then
    echo '01' >ca.db.serial
fi
if [ ! -f ca.db.index ]; then
    cp /dev/null ca.db.index
fi

# create an own SSLeay config
cat >ca.config <<EOT
[ ca ]
default_ca= CA_own
[ CA_own ]
dir= /etc/ssl
certs= /etc/ssl/certs
new_certs_dir= /etc/ssl/ca.db.certs
database= /etc/ssl/ca.db.index
serial= /etc/ssl/ca.db.serial
RANDFILE= /etc/ssl/ca.db.rand
certificate= /etc/ssl/certs/ca.crt
private_key= /etc/ssl/private/ca.key
default_days= 3653
default_crl_days= 30
default_md= md5
preserve= no
policy= policy_anything
[ policy_anything ]
countryName= optional
stateOrProvinceName= optional
localityName= optional
organizationName= optional
organizationalUnitName= optional
commonName= supplied
emailAddress= optional
EOT

# sign the certificate
echo "CA signing: $CSR -> $CERT:"
openssl ca -config ca.config -out $CERT -infiles $CSR
echo "CA verifying: $CERT <-> CA cert"
openssl verify -CAfile /etc/ssl/certs/ca.crt $CERT

# cleanup after SSLeay
rm -f ca.config
rm -f ca.db.serial.old
rm -f ca.db.index.old

# die gracefully
exit 0

Damit keine Abfrage einer Paßphrase beim Start des Mailservers kommt, wird sie aus dem privaten Serverschlüssel gelöscht. Der ungeschützte Schlüssel muß dann auf jeden Fall unlesbar für alle außer Root sein.

cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
chmod 400 server.key

Dasselbe ggf. auf dem internen Mailserver mit iserver.key wiederholen. Die Schlüssel gut sichern. Zertifikate (*.crt) gehören in das Unterverzeichnis ./certs, private Schlüssel (*.key) gehören in das Unterverzeichnis ./private. Die nicht auf dem Server benötigten privaten Schlüssel von dort löschen.

Zu guter Letzt notieren wir uns noch den "Fingerprint" vom Schlüssel iserver.crt:

openssl x509 -noout -fingerprint -in iserver.crt

Courier POP3 mit SSL

Courier wird angewiesen, seine Authentifizierungsinformationen aus der MySQL-Datenbank zu beziehen. Außerdem erfährt der POP3-Server, mit welchem Schlüssel er die Übertragung sichern soll.

vi /etc/courier/authdaemonrc
authmodulelist="authmysql authuserdb authpam"
daemons=3

vi /etc/courier/authmysqlrc
MYSQL_SERVER localhost
MYSQL_USERNAME postfix
MYSQL_PASSWORD streng_gemein
MYSQL_DATABASE postfix
MYSQL_USER_TABLE mailbox
MYSQL_CRYPT_PWFIELD password
MYSQL_CLEAR_PWFIELD clearpass
MYSQL_UID_FIELD uid
MYSQL_LOGIN_FIELD username
MYSQL_HOME_FIELD home
MYSQL_NAME_FIELD name
MYSQL_MAILDIR_FIELD maildir

vi /etc/courier/pop3d-ssl
TLS_CERTFILE=/usr/share/ssl/private/server.key

Postfix mit TLS und SASL

Jetzt wird Postfix konfiguriert. Dabei ist übrigens von einem Nutzer "spam" die Rede. Dieser bekommt alle eingehenden Mails mit unbekanntem Adressaten. (Wir schicken nie etwas zurück, schon gar kein "Nutzer unbekannt". Der Feind soll so wenig wie möglich erfahren.) Der Nutzer spam ist derselbe, der auch allen Spam von Spamassassin zugestellt bekommt.

vi /etc/postfix/main.cf
smtpd_banner = $myhostname ESMTP $mail_name
setgid_group = postdrop
biff = no
append_dot_mydomain = no
myorigin = mydomain.net
mydomain = mydomain.net
myhostname = mail.mydomain.net
mydestination = mydomain.net, mail.mydomain.net
# Hier die eigene feste IP-Adresse eintragen:
mynetworks = nnn.nnn.nnn.nnn, 127.0.0.0/8
recipient_delimiter = +
local_recipient_maps =
luser_relay = spam@mydomain.net
relay_domains = $mydestination
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, permit_tls_clientcerts, reject_unauth_destination
# Diese Zeile sorgt dafür, daß unser interner Mailserver diesen Mailserver als Relay nutzen darf.
# Er weist sich durch sein TLS-Zertifikat aus:
relay_clientcerts = mysql:/etc/postfix/mysql_relay_clientcerts.cf
alias_maps = mysql:/etc/postfix/mysql_alias_maps.cf
alias_database = mysql:/etc/postfix/mysql_alias_maps.cf
home_mailbox = Maildir/
mailbox_size_limit = 150000000
message_size_limit = 134217728
bounce_size_limit = 50000
header_size_limit = 102400
unknown_local_recipient_reject_code = 450

# SASL support:
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = mail.mydomain.net
broken_sasl_auth_clients = yes

# TLS support:
smtpd_use_tls = yes
#smtpd_tls_auth_only = yes
smtpd_tls_ask_ccert = yes
smtpd_tls_key_file = /usr/share/ssl/private/server.key
smtpd_tls_cert_file = /usr/share/ssl/certs/server.crt
smtpd_tls_CAfile = /usr/share/ssl/certs/ca.crt
smtpd_tls_CApath = /usr/share/ssl/certs
smtpd_tls_loglevel = 1
#smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

vi /etc/postfix/master.cf
#smtp inet n - - - - smtpd
# aendern zu:
smtp inet n - n - - smtpd

vi /etc/postfix/mysql_alias_maps.cf
user = postfix
password = streng_geheim

hosts = localhost
dbname = postfix
table = alias
select_field = goto
where_field = address

vi /etc/postfix/mysql_relay_clientcerts.cf
user = postfix
password = streng_geheim
hosts = localhost
dbname = postfix
table = relayclients
select_field = clientname
where_field = fingerprint

vi /usr/lib/sasl/smtpd.conf
pwcheck_method: pam

vi /etc/postfix/sasl/smtpd.conf
pwcheck_method: pam

vi /etc/pam.d/smtp
auth required pam_mysql.so user=postfix passwd=streng_geheim db=postfix table=mailbox usercolumn=username passwdcolumn=clearpass crypt=0

chmod 644 /etc/pam.d/smtp

An der letzten Zeile sollte Ihnen etwas auffallen. Die Datei ist für alle lesbar, aber das MySQL-Paßwort für die Postfix-Datenbank steht darin. Da Postfix immer mit den Rechten des jeweiligen Mailempfängers auf diese Datei zugreift, muß diese Datei für jeden Nutzer lesbar sein. Kanonisch müßte es dafür ein Programm "authmysqld" geben, das habe ich aber noch nicht gefunden. Ich bin für Hinweise dankbar. Einstweilen trösten wir uns damit, daß sich ohnehin kein Fremder auf unserem Server einloggen darf.

Die SASL-Authentifizierung (siehe /usr/lib/sasl/smtpd.conf und /etc/pam.d/smtp) ist so eingestellt, daß für POP3-Emailabruf und SMTP-Senden dasselbe Paßwort vom Nutzer verlangt wird. Siehe dazu auch die Outlook-Bedienungsanleitung.

Postfix-Datenbank in MySQL

Das folgende Script wird ausgeführt mit:

mysql <postfix_fill.sql

Es füllt die Datenbank mit allen Werten, die von Postfix und Courier benötigt werden.

CREATE DATABASE postfix;

 

USE mysql;

INSERT INTO db VALUES ('localhost','postfix','postfix','Y','N','N','N','N','N','N','N','N','N');
INSERT INTO user VALUES ('localhost','postfix',password('streng_geheim'),'N','N','N','N','N','N','N','N','N','N','N','N','N','N');

USE postfix;

CREATE TABLE alias (
    address varchar(255) NOT NULL default '',
    goto text NOT NULL,
    domain varchar(255) NOT NULL default '',
    create_date datetime NOT NULL default '0000-00-00 00:00:00',
    change_date datetime NOT NULL default '0000-00-00 00:00:00',
    active tinyint(4) NOT NULL default '1',
    KEY address_2 (address)
) TYPE=MyISAM COMMENT='Virtual Aliases';

INSERT INTO alias VALUES ('MAILER-DAEMON','postmaster','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);
INSERT INTO alias VALUES ('postmaster','root','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);
INSERT INTO alias VALUES ('hostmaster','root','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);
INSERT INTO alias VALUES ('webmaster','root','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);
INSERT INTO alias VALUES ('root','myself','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);
INSERT INTO alias VALUES ('myalias','myself','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);

CREATE TABLE domain (
    domain varchar(255) NOT NULL default '',
    description varchar(255) NOT NULL default '',
    create_date datetime NOT NULL default '0000-00-00 00:00:00',
    change_date datetime NOT NULL default '0000-00-00 00:00:00',
    active tinyint(4) NOT NULL default '1',
    PRIMARY KEY (domain),
    UNIQUE KEY domain (domain)
) TYPE=MyISAM COMMENT='Virtual Domains';

INSERT INTO domain VALUES ('mydomain.net','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);
INSERT INTO domain VALUES ('mail.mydomain.net','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);

CREATE TABLE mailbox (
    username varchar(255) NOT NULL default '',
    uid int(11) NOT NULL default '9999',
    gid int(11) NOT NULL default '9999',
    password varchar(255) NOT NULL default '',
    clearpass varchar(255) NOT NULL default '',
    name varchar(255) NOT NULL default '',
    home varchar(255) NOT NULL default '',
    maildir varchar(255) NOT NULL default '',
    domain varchar(255) NOT NULL default '',
    create_date datetime NOT NULL default '0000-00-00 00:00:00',
    change_date datetime NOT NULL default '0000-00-00 00:00:00',
    active tinyint(4) NOT NULL default '1',
    PRIMARY KEY (username),
    UNIQUE KEY id (username)
) TYPE=MyISAM COMMENT='Virtual Mailboxes';

-- Das verschlüsselte Paßwort wird hier garnicht benötigt,
-- da aufgrund der gesicherten Verbindung zum Mailserver
-- immer Klartextpaßworte übertragen werden.
INSERT INTO mailbox VALUES ('myself',1000,1000,'$1$jhvg67RT$Jhuzhgbfuzgtv8768gKJHB.','geheim','Mein Name','/home/myself','/home/myself/Maildir/','','0000-00-00 00:00:00','0000-00-00 00:00:00',1);

CREATE TABLE relayclients (
    clientname varchar(255) NOT NULL default '',
    fingerprint varchar(255) NOT NULL default ''
) TYPE=MyISAM COMMENT='Certificates for relay clients';

-- Hier gehört der vorhin notierte Fingerprint
-- des internen Mailservers hinein.    
INSERT INTO relayclients VALUES ('mail.intra.mydomain.net','3F:A4:73:BB:3Q:86:C2:02:A7:A7:H6:D1:2E:2D:F4:88');

Spamassassin

Die Nutzer dürfen keine Regel aufstellen, sondern nur vordefinierten Regeln neue Bewertungen zuordnen. Viel wird dabei nicht zu tun sein, denn Spamassassin ist schon sehr ausgefeilt.

vi /etc/mail/spamassassin/local.cf
rewrite_subject 1
subject_tag [SPAM]
fold_headers 0
use_terse_report 0
spam_level_stars 0
check_mx_attempts 3
check_mx_delay 5
allow_user_rules 0
header TO_undisclosed To =~ /undisclosed/i
describe TO_undisclosed To: undisclosed
header SUBJECT_3_minus Subject =~ /---/i
describe SUBJECT_3_minus Subject: ---
header SUBJECT_6_blanks Subject =~ /[ ]{6,}/i
describe SUBJECT_6_blanks Subject: 6 blanks
header SUBJECT_2_exclamation Subject =~ /!!/i
describe SUBJECT_2_exclamation Subject: !!
header SUBJECT_dollar_digit Subject =~ /\$\d/i
describe SUBJECT_dollar_digit Subject: $digit
header SUBJECT_3_dots Subject =~ /\.\.\./i
describe SUBJECT_3_dots Subject: ...
header SUBJECT_question_exclamation Subject =~ /\?!/i
describe SUBJECT_question_exclamation Subject: ?!
header SUBJECT_2_question Subject =~ /\?\?/i
describe SUBJECT_2_question Subject: ??
header SUBJECT_3_underscore Subject =~ /___/i
describe SUBJECT_3_underscore Subject: ___
header SUBJECT_starts_with_asterisk Subject =~ /^Subject:[ ]*[*]+/i
describe SUBJECT_3_starts_with_asterisk Subject: starts with *
header SUBJECT_contains_free Subject =~ /\bfre{2,}\b/i
describe SUBJECT_contains_free Subject: free
header SUBJECT_discount Subject =~ /discount/i
describe SUBJECT_discount Subject: discount
header SUBJECT_herbal Subject =~ /herbal/i
describe SUBJECT_herbal Subject: herbal

vi /etc/default/spamassassin
ENABLED=1

Mailkonfiguration der Nutzer

vi ~myself/.spamassassin/user_prefs

whitelist_from goodfriend@domain.net
blacklist_from *@daily-promotions.net
score TO_undisclosed 5.0
score SUBJECT_3_minus 3.0
score SUBJECT_6_blanks 3.0
score SUBJECT_2_exclamation 3.0
score SUBJECT_dollar_digit 3.0
score SUBJECT_3_dots 3.0
score SUBJECT_question_exclamation 3.0
score SUBJECT_2_question 3.0
score SUBJECT_3_underscore 3.0
score SUBJECT_3_starts_with_asterisk 3.0
score SUBJECT_contains_free 2.0
score SUBJECT_discount 3.0
score SUBJECT_herbal 3.0

vi ~myself/.forward
"| /usr/bin/procmail -t"

Der Nutzer "spam", von dem hier die Rede ist, sollte wirklich existieren. Dessen Post sollte man ab und zu kontrollieren. Manchmal ist ein falscher Treffer dabei. Man will ja keine Freunde verlieren, nur weil der Spamfilter zu gründlich war.

vi ~myself/.procmailrc
:0fw
* < 256000
| /usr/local/bin/spamc

:0:
* ^X-Spam-Status: Yes
{
    :0 c
    * ^Subject[ :][ ]*\/.*$
    | cat >/dev/null; /usr/bin/logger -p mail.info -t "spamassassin spam" "$MATCH"

    :0
    ! spam@mydomain.net
}

:0 c
* ^X-Spam-Status: No
* ^Subject[ :][ ]*\/.*$
| cat >/dev/null; /usr/bin/logger -p mail.info -t "spamassassin good" "$MATCH"

:0:
Maildir/

chown myself.mygroup ~myself/.forward ~myself/.procmailrc
chmod 600 ~myself/.forward ~myself/.procmailrc

maildirmake ~myself/Maildir
chown -R myself.mygroup ~myself/Maildir

Fetchmail

Fetchmail fragt externe Postfächer ab, in der Regel über POP3. Die Konfiguration erfolgt pro Einzelnutzer. Die abgerufenen Mails passieren den eingerichteten Spamfilter. Das ist der Grund, weshalb Fetchmail besser auf dem externen Mailserver läuft, denn sonst müssen Sie zwei Spamfilter pflegen.

crontab -u myself -e

0,15,30,45 * * * * /usr/local/bin/fetchmail 1>/dev/null 2>/dev/null

vi ~myself/.fetchmailrc

poll another.mailserver.net protocol pop3 timeout 30
username "myself_there" password "mypassword_there" is "myself" here
fetchall no keep

Der interne Mailserver

Wenn Sie einen internen Mailserver verwenden, müssen seine Einstellungen natürlich zu dem Vorherigen passen. (Hier sind nur die Zeilen des Konfigurationsfiles gezeigt, die in diesem Zusammenhang interessant sind.)

vi /etc/postfix/main.cf
myhostname = mail.intra.mydomain.net
mydestination = intra.mydomain.net, mail.intra.mydomain.net, beimir.dnsalias.net, localhost

# Hier wird die feste IP-Adresse unseres Mailservers in der DMZ eingetragen:
relayhost = nnn.nnn.nnn.nnn
mynetworks = 10.0.0.0/8, 127.0.0.0/8
local_recipient_maps =
luser_relay = spam@mail.intra.mydomain.net

smtp_use_tls = yes
smtp_tls_key_file = /usr/share/ssl/private/iserver.key
smtp_tls_cert_file = /usr/share/ssl/certs/iserver.crt
smtp_tls_CAfile = /usr/share/ssl/certs/ca.crt
smtp_tls_CApath = /usr/share/ssl/certs
smtp_tls_loglevel = 1
smtp_tls_per_site = hash:/etc/postfix/tls_per_site
tls_random_source = dev:/dev/urandom

Und schließlich:

vi /etc/postfix/ tls_per_site
mail.mydomain.net MUST_NOPEERMATCH

postmap hash:/etc/postfix/tls_per_site

Webserver

Zur Konfiguration des Webservers folgt hier nur ein kleiner Ausschnitt. Der Vorgang ist bei weitem nicht so fehlerträchtig wie die Einrichtung eines Mailservers.

Apache 2 kann ich noch nicht empfehlen.

vi /etc/apache/httpd.conf
NameVirtualHost www.mydomain.net
NameVirtualHost www.myself.mydomain.net

<VirtualHost www.mydomain.net>
    ServerName www.mydomain.net
    DocumentRoot /home/apache/html
    <Directory "/home/apache/html">
        Options FollowSymLinks ExecCGI
        AllowOverride AuthConfig
        Order allow,deny
        Allow from all
    </Directory>
    ServerAdmin webmaster@mydomain.net
    Alias /myself /home/myself/html
    <Directory /home/myself/html>
        Options FollowSymLinks ExecCGI
        AllowOverride AuthConfig
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

<VirtualHost www.myself.mydomain.net>
    ServerName www.myself.mydomain.net
    ServerAlias myself.mydomain.net
    DocumentRoot /home/myself/html
    <Directory "/home/myself/html">
        Options FollowSymLinks ExecCGI
        AllowOverride AuthConfig
        Order allow,deny
        Allow from all
    </Directory>
    ServerAdmin webmaster@mydomain.net
</VirtualHost>

mkdir /home/apache
mkdir /home/apache/html
mkdir /home/apache/cgi-bin
chown -R myself.www-data /home/apache
chmod -R 750 /home/apache

mkdir /home/myself/html
mkdir /home/myself/cgi-bin
chown -R myself.www-data /home/myself/html
chmod -R 750 /home/myself/html

Filetransfer

Filetransfer ist über das SSH-Protokoll mit SFTP möglich. Zu Putty gehört ein Kommandozeilen-Client. Für private Anwendung frei ist der sehr gute SSH Client von http://www.ssh.com. Diese Filetransfers sind genauso sicher wie der Shellzugang über SSH.

Wer auf seinem Rechner noch andere Nutzer beherbergt, sollte ihnen keinesfalls Shellzugang zu dem Server gewähren. Diese Nutzer können ihre HTML-Seiten über ein normales FTP hochladen, wobei die Zugangsmöglichkeiten unbedingt auf das Homeverzeichnis des jeweiligen Nutzers beschränkt sein müssen. Zu empfehlen is vsftpd.

vi /etc/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
connect_from_port_20=YES
async_abor_enable=YES
ascii_upload_enable=YES
ascii_download_enable=YES
chroot_local_user=YES
text_userdb_names=YES
pasv_min_port=60020
pasv_max_port=60039
local_max_rate=8192

Schlußwort

Erwarten Sie nicht, daß es auf Anhieb funktioniert wie hier beschrieben. Wenn man einen Server konfiguriert, schreibt man sich nicht jeden Schritt parallel auf. Manches habe ich hier vielleicht vergessen zu erwähnen. Für Hinweise bin ich stets dankbar. Dankbar bin ich auch für jeden Kommentar "unnütz", es hilft mir aber noch mehr, wenn ich auch in zwei, drei Worten erfahre, wie ich es nützlicher machen könnte.

Viel Erfolg und viel Spaß.