Tag Archiv für Postfix

Scripte zum Erstellen und Erneuern von Letsencrypt Zertifikaten

Vor längerer Zeit (2016) habe ich nach Scripten oder OpenSource Software zum Erstellen und Erneuern von Letsencrypt Zertikaten gesucht, da ich nach dem Ende von StartSSL auf die Letsencrypt Zertikate umgestiegen war und diese nicht nur für Webseiten, sondern auch für Postfix, Dovecot und Vsftpd nutze.
Leider habe ich nichts gefunden, was meine Anforderungen entsprach und habe daher die Scripte selber geschrieben. Ausgangspunkt war der FreeBSD Port von acme-tiny. Zunächst entstand das Basisscript zum Erstellen der Zertifikate, auch wenn noch kein einziges vorhanden war, indem ich zunächst eine sub.domain.tld.cnf mit den openssl Basisdaten erstelle.

Wobei, noch davor muß als erstes ein eigener account.key erzeugt werden, wie es auch auf der acme-tiny Seite erklärt ist:

openssl genrsa 4096 > account.key

Dann kann man ein Zertikat mit folgendem Script erstellen:

#!/usr/local/bin/bash
#
# Dirk Dettmering
#
# Version 0.13 
# 23.01.2019
#

USAGE="Syntax: $0 domain.tld altdomain.tld subdomain.domain.tld
       Erster Parameter ist die primaer geschuetzte Domain und
       dann kommen die alternativen Domainnamen"

if [ "$#" == "0" ]; then
    echo "$USAGE"
    exit 1
fi

# Variablen für Einstellunge:
KEYDIR="/usr/local/etc/letsencrypt"
#KEYDIR="/usr/local/etc/letstest"
ACMETINY="/usr/local/bin/acme_tiny"
# Verzeichnis für die ACME-Challenge (Port 80!!!, nicht 443!!!)
ACMEDIR="/usr/local/www/challenges/"
# ACMEDIR="/usr/local/www/challenges/.well-known/acme-challenge/"
# Standard-Unterverzeichnis für die ACME-Challenge (Port 80!!!, nicht 443!!!)
# ACMESUBDIR=".well-known/acme-challenge/"

# Benutzer Variablen für Einstellungen
ACCOUNTKEY=$KEYDIR/account.key
DOMAIN="$1"
shift
for num
    do
	ALTDOMAINS=$ALTDOMAINS" "$num
done

BACKUPDIR=$KEYDIR/backup/$DOMAIN/`date +%Y-%m-%d`
LOG=$KEYDIR/logs/$DOMAIN.log
LOGtmp=$KEYDIR/logs/$DOMAIN_tmp.log

# SSL-Konfiguration:
SSLCNF=$KEYDIR/$DOMAIN/$DOMAIN.cnf
COUNTRY="DE"
STATEORPROVINCENAME="Hessen"
CITY="Musterstadt"
ORGANIZATIONNAME="Musterfirma"
ORGANIZATIONALUNITNAME="IT-Abteilung"
EMAIL="cert-admin@domain.tld"
#
# Servicerestarts:
HTTPRESTART="/usr/local/sbin/apachectl graceful"
IMAPRESTART="service dovecot restart"
SMTPRESTART="service postfix restart"
CHOWN="root:wheel"
# Weitere Vaiablen (Diese müssen im Normallfall nicht geändert werden)
CHMOD="644"
# Wird auf false gesetzt, wenn was schief läuft
CRTOK=true
# Ende der Benutzer-Variablen.

# Ab hier beginnt das Script.

# Es wird geprüft, ob acme-tiny vorhanden ist
if [ ! -f $ACMETINY ]; then
    echo "ACME_TINY nicht gefunden"
    exit 2
fi

# Datum und Variablen werden ins LOG geschrieben
echo "--- Start ---" >$LOG
date >>$LOG
echo "Domain: $DOMAIN" >>$LOG
echo "Accountkey: $ACCOUNTKEY" >>$LOG
echo "------------------------" >>$LOG

# Ordner fü die Domain erstellen, falls nocht nicht vorhande:
if [ ! -d $KEYDIR/$DOMAIN ]; then
    mkdir -p $KEYDIR/$DOMAIN
fi

# Backup-Ordner fuer aktuelle Zertifikate wird erstellt
if [ -s $KEYDIR/$DOMAIN/$DOMAIN.pem ] && [ ! -d $BACKUPDIR ]; then
    mkdir -p $BACKUPDIR
    mv -f $KEYDIR/$DOMAIN/lets-encrypt-x3-cross-signed-intermediate.pem $BACKUPDIR > /dev/null 2>&1
    mv -f $KEYDIR/$DOMAIN/$DOMAIN.crt $BACKUPDIR > /dev/null 2>&1
    mv -f $KEYDIR/$DOMAIN/$DOMAIN.csr $BACKUPDIR > /dev/null 2>&1
    mv -f $KEYDIR/$DOMAIN/$DOMAIN.pem $BACKUPDIR > /dev/null 2>&1
    mv -f $KEYDIR/$DOMAIN/$DOMAIN-chain.pem $BACKUPDIR > /dev/null 2>&1
fi

# Es wird geprüft, ob der ACCOUNT-Key existiert.
if [ ! -f $ACCONTKEY ]; then
    echo "Account Key $ACCOUNTKEY nicht vorhanden" >> $LOG 2>&1
    echo "Key kann mit dem folgenden Befehl erstellt werden:" >> $LOG 2>&1
    echo "openssl genrsa 4096 > $ACCOUNTKEY" >> $LOG 2>&1
    exit 3
fi

# prüfen, ob die Domain erreichbar ist:
if /usr/bin/nc -z $DOMAIN 80 > /dev/null 2>&1; then
    echo "Domain erreichbar" >>$LOG 2>&1
else
    echo "Domain nicht erreichbar" >>$LOG 2>&1
    exit 4
fi

# Private Key der Domain erstellen, wenn noch nicht vorhanden:
if [ ! -f $KEYDIR/$DOMAIN/$DOMAIN.key ]; then
    openssl genrsa 4096 > $KEYDIR/$DOMAIN/$DOMAIN.key 2>>$LOG 2>&1
fi

# Config-Datei für CSR erstelen, wenn noch nicht vorhanden:
if [ ! -f $SSLCNF ]; then
    echo "[ req ]
    distinguished_name = req_distinguished_name
    string_mask = nombstr
    # The extensions to add to a certificate request
    req_extensions = v3_req
    # GWDG default options for certificate request
    [ req_distinguished_name ]
    countryName = Country Name (2 letter code)" > $SSLCNF
    echo -n "countryName_default = " >> $SSLCNF
    echo $COUNTRY >> $SSLCNF
    echo "countryName_min = 2" >> $SSLCNF
    echo "countryName_max = 2" >> $SSLCNF
    echo "stateOrProvinceName = State or Province Name (full name)" >> $SSLCNF
    echo -n "stateOrProvinceName_default = " >> $SSLCNF
    echo $STATEORPROVINCENAME >> $SSLCNF
    echo "localityName = Your City" >> $SSLCNF
    echo -n "localityName_default = " >> $SSLCNF
    echo $CITY >> $SSLCNF
    echo "0.organizationName = Organization Name (eg, company)
    0.organizationName_default = "$ORGANIZATIONNAME >> $SSLCNF
    echo "organizationalUnitName = Organizational Unit Name (eg, section)
    organizationalUnitName_default = "$ORGANIZATIONALUNITNAME >> $SSLCNF
    echo "commonName = Common Name (e.g. server FQDN or YOUR name)" >> $SSLCNF
    echo "commonName_max = 64" >> $SSLCNF
    echo -n "commonName_default = " >> $SSLCNF
    echo $DOMAIN >> $SSLCNF
    echo "emailAddress = Email Address" >> $SSLCNF
    echo "emailAddress_max = 64" >> $SSLCNF
    echo -n "emailAddress_default = " >> $SSLCNF
    echo $EMAIL >> $SSLCNF 
    echo "[ v3_req ]" >> $SSLCNF
    echo -n "subjectAltName = DNS:" >> $SSLCNF
    echo -n $DOMAIN >> $SSLCNF
fi

for SUB in $ALTDOMAINS; do
    echo -n ", DNS:" >> $SSLCNF
    echo -n $SUB >> $SSLCNF
done

# CSR wird erstellt
# openssl req -new -sha256 -key /etc/ssl/letsencrypt/domain.key -subj "/C=US/O=Acme/CN=example.com" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:www.example.com,DNS:static.example.com")) -out /etc/ssl/letsencrypt/example.com/domain.csr
openssl req -new -sha256 -key $KEYDIR/$DOMAIN/$DOMAIN.key -batch -config $KEYDIR/$DOMAIN/$DOMAIN.cnf -out $KEYDIR/$DOMAIN/$DOMAIN.csr >> $LOG 2>&1

# CSR von Lets-Encrypt signieren lassen
/usr/local/bin/python2.7 $ACMETINY --account-key $ACCOUNTKEY --csr $KEYDIR/$DOMAIN/$DOMAIN.csr --acme-dir $ACMEDIR > $KEYDIR/$DOMAIN/$DOMAIN.crt
RESULT=$?
if [ ! $RESULT == 0 ];then
    echo "Signierung nicht erfolgreich!" >>$LOG
    echo "Signierung nicht erfolgreich!"
    exit $RESULT
else
    echo "Signierung erfolgreich!" >>$LOG
fi

# Append the Let's Encrypt intermediate cert to your cert
/usr/local/bin/wget -q -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > $KEYDIR/$DOMAIN/lets-encrypt-x3-cross-signed-intermediate.pem 2>>$LOG 2>&1
cat $KEYDIR/$DOMAIN/$DOMAIN.crt $KEYDIR/$DOMAIN/lets-encrypt-x3-cross-signed-intermediate.pem >> $KEYDIR/$DOMAIN/$DOMAIN-chain.pem

# Rechte
/usr/sbin/chown -R $CHOWN $KEYDIR/$DOMAIN 
/bin/chmod -R $CHMOD $KEYDIR/$DOMAIN/*

# Jetzt kommen die Prüfungen, ob das CRT OK ist.
if [ `grep -c CERTIFICATE $KEYDIR/$DOMAIN/$DOMAIN-chain.pem` = 6 ]; then
    echo "Zertifikat ist OK" >>$LOG
    # PEM-Datei wird erstellt (PEM = KEY + CRT)
    cat $KEYDIR/$DOMAIN/$DOMAIN.key >$KEYDIR/$DOMAIN/$DOMAIN.pem
    cat $KEYDIR/$DOMAIN/$DOMAIN-chain.pem >>$KEYDIR/$DOMAIN/$DOMAIN.pem
else
    CRTOK=false
    echo "Zertifikat ist Fehlerhaft" >>$LOG
    exit 7
fi

# Hier wird anhand des Prüfungsergebnisses weiter entschieden
if $CRTOK; then
    # CRT ist OK

    # Webserver neu Starten!
    # $HTTPRESTARTCMD 2>/dev/null >/dev/null
    $HTTPRESTARTCMD  > /dev/null 2>&1
    # Mailserver neu Starten!
    $IMAPRESTART > /dev/null 2>&1
    #$SMTPRESTART > /dev/null 2>&1
else
    # Fehler beim CRT
    mkdir -p $KEYDIR/failed/$DOMAIN-`date +%Y-%m-%d-%H-%M`
    mv $KEYDIR/$DOMAIN/* $KEYDIR/failed/$DOMAIN_`date +%Y-%m-%d_%H-%M`
    exit 5
fi

Das Script ruft man dann wie folgt auf:

~/bin/cert-create.sh www.domain.tld domain.tld subdomain.domain.tld

Im vHost des Apache habe ich die Letsencrypt Challenge mit einem Include vorbereitet:

Die Datei /usr/local/etc/apache24/Includes/acme.conf hat folgenden Inhalt:

# Let's Encrypt acme-client:
Alias /.well-known/acme-challenge /usr/local/www/challenges
#Alias /.well-known/ /usr/local/www/challenges
<Directory /usr/local/www/challenges>
   Options None
   AllowOverride None
   Order deny,allow
   #Allow from all
   Require all granted
   Header add Content-Type text/plain
</Directory>

Und wird in der vHost Konfiguration eingebunden:

<VirtualHost *:80>
ServerName www.domain.tld
ServerAlias domain.tld
ServerAdmin webmaster@leseratte-linz.de
DocumentRoot /srv/domain.tld/www
ErrorLog /srv/domain.tld/logs/error.log
CustomLog /srv/domain.tld/logs/access.log combined
Alias /.wwwstats_ "/srv/webalizer/domain.tld"
<Directory />
   AllowOverride All
   Options -Indexes
   Require all granted
</Directory>

Include /usr/local/etc/apache24/Includes/acme.conf
# Auf SSL umschreiben:
RewriteEngine On
RewriteCond % 80
RewriteRule ^(.*)$ https://www.domain.tld/$1 [R,L]
</VirtualHost>

Für die SSL Konfiguration gibt es eine weitere Include Datei:

Die SSL vHost Konfiguration:

<VirtualHost *:443>
ServerName www.domain.tld
ServerAlias domain.tld
ServerAdmin webmaster@domain.tld
DocumentRoot /srv/domain.tld/www
ErrorLog /srv/domain.tld/logs/ssl-error.log
CustomLog /srv/domain.tld/logs/ssl-access.log combined
Alias /.wwwstats_ "/srv/webalizer/domain.tld/"
Include /usr/local/etc/apache24/Includes/acme.conf
<Directory />
   AllowOverride All
   Options -Indexes
   Require all granted
</Directory>

Include /usr/local/etc/apache24/Includes/ssl.conf
SSLCertificateFile /usr/local/etc/letsencrypt/www.domain.tld/www.domain.tld.crt
SSLCertificateKeyFile /usr/local/etc/letsencrypt/www.domain.tld/www.domain.tld.key
SSLCertificateChainFile /usr/local/etc/letsencrypt/www.domain.tld/www.domain.tld-chain.pem
</VirtualHost>

Die Datei /usr/local/etc/apache24/Includes/ssl.conf:

# generated 2019-09-10, https://ssl-config.mozilla.org/#server=apache&server-version=2.4.39&config=intermediate
# https://ssl-config.mozilla.org/
# requires mod_ssl, mod_socache_shmcb, mod_rewrite, and mod_headers
# enable HTTP/2, if available
Protocols h2 http/1.1

# HTTP Strict Transport Security (mod_headers is required) (63072000 seconds)
Header always set Strict-Transport-Security "max-age=63072000"
<IfModule mod_ssl.c>
  SSLEngine on
  SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  SSLCipherSuite "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECD
  SSLHonorCipherOrder on
  SSLHonorCipherOrder     off
  SSLSessionTickets       off
  SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
  <IfModule mod_headers.c>
    Header always set Strict-Transport-Security: "max-age=15768000"
  </IfModule>
</IfModule>

Die Konfigurstionsdateien für postfix, dovecot undvsftpd mit SSL spare ich mir hier. Dazu gibt es genug Quellen im Netz.

Mit dem Scrpit acme-update.sh erneuere ich wöchentlich die Letsencrypt Zertifikate:

#!/usr/local/bin/bash
#
# Dirk Dettmering
#
# 0.8 02.12.2016
#

# Servicerestarts:
HTTPRESTART="/usr/local/sbin/apachectl graceful"
FTPRESTART="service vsftpd restart"
IMAPRESTART="service dovecot restart"
SMTPRESTART="service postfix restart"

DATUM=`date +%d-%m-%Y`
STEMPEL=`date +%d-%m-%Y' '%H:%M`
DOMAINLIST="/usr/local/etc/letsencrypt/domains.txt"
TLOG="/tmp/acme-update.log"
LOG="/usr/local/etc/letsencrypt/logs/update.log"
STATUS=0

echo "#############################################################" >> $LOG
echo "" >> $LOG
echo $DATUM": Update der Zertifikate aller Domänen" >> $LOG

while read line; do
    IFS=" "
    set -- $line
    /usr/local/bin/bash /root/bin/cert-create.sh $1 $2 $3 $4 $5 $6; >> $LOG 2>&1
    RCODE=$?
    echo -e "$line\c" >> $LOG
    if [ $RCODE -ge 1 ]; then
	STATUS=$(($STATUS + $RCODE))
	echo "Status: "$STATUS
	#STATUS="Error"
	echo "Beim Erstellen des Zertifikats ist ein Fehler aufgetreten. Returncode: "$RCODE >> $LOG
    else
	echo ": OK" >> $LOG
    fi
done < /usr/local/etc/letsencrypt/domains.txt

echo "" >> $LOG

if [ $STATUS -eq 0 ]; then
    # Webserver neu Starten!
    $HTTPRESTARTCMD  > /dev/null 2>&1
    RCODE=$?
    if [ $RCODE -ge 1 ]; then
	STATUS="Error"
	echo "Beim Neustart des Apache ist ein Fehler aufgetreten: "$RCODE >> $LOG
    else
	echo "Apache erfolgreich neu gestartet" >> $LOG
    fi
    # FTP Server neu Starten!
    $FTPRESTARTCMD  > /dev/null 2>&1
    RCODE=$?
    if [ $RCODE -ge 1 ]; then
	STATUS="Error"
	echo "Beim Neustart des FTP Servers ist ein Fehler aufgetreten: "$RCODE >> $LOG
    else
	echo "VsFTPD erfolgreich neu gestartet" >> $LOG
    fi
    # Mailserver neu Starten!
    $IMAPRESTART > /dev/null 2>&1
    if [ $RCODE -ge 1 ]; then
	STATUS="Error"
	echo "Beim Neustart von Dovecot ist ein Fehler aufgetreten: "$RCODE >> $LOG
    else
	echo "Dovecot erfolgreich neu gestartet" >> $LOG
    fi
    $SMTPRESTART > /dev/null 2>&1
    if [ $RCODE -ge 1 ]; then
	STATUS="Error"
	echo "Beim Neustart von Postfix ist ein Fehler aufgetreten: "$RCODE >> $LOG
    else
	echo "Postfix erfolgreich neu gestartet" >> $LOG
    fi
else
    echo "Kein Neustart, weil ein Returncode groesser Null war!"
fi
echo "" >> $LOG

Und hier beide Dateien zum Download: letsencrypt-scripte.tar.bz2

Lösung des Problems von Postfix mit der OpenSSL Option ZLIB

Vor knapp 2 Wochen habe ich meinen Mailserver von FreeBSD 9.3 auf FreeBSD 10.2 umgezogen. Ich hatte so ziemlich alles vorher getestet, allerdings nicht die Verschlüsselung des Mailverkehrs von Postfix und Dovecot, weil das offizielle Zertifikat auf den Hostnamen ausgestellt war, der zum Zeitpunkt des Testens noch auf dem alten Server konfiguriert war. Da das offizielle StartSSL Zertifikat 2 Tage nach dem Umzug ausgelaufen wäre, habe ich mir ein neues ausstellen lassen und das dann gleich auf dem neuen Server aktiviert. Als dann der Produktivbetrieb auf dem neuen Server startete, produzierten  die SMTP und SMTPD Prozesse von Postfix plötzlich beunruhigend viele Abstürze mit Signal 11:

Dec 10 16:17:10 saruman kernel: pid 72535 (smtpd), uid 125: exited on signal 11
Dec 10 16:18:49 saruman kernel: pid 72552 (smtp), uid 125: exited on signal 11
Dec 10 16:18:49 saruman kernel: pid 72556 (smtp), uid 125: exited on signal 11
Dec 10 16:18:49 saruman kernel: pid 72557 (smtp), uid 125: exited on signal 11
Dec 10 16:18:50 saruman kernel: pid 72553 (smtp), uid 125: exited on signal 11
Dec 10 16:18:50 saruman kernel: pid 72555 (smtp), uid 125: exited on signal 11
Dec 10 16:18:50 saruman kernel: pid 72551 (smtp), uid 125: exited on signal 11
Dec 10 16:18:50 saruman kernel: pid 72550 (smtp), uid 125: exited on signal 11
Dec 10 16:18:51 saruman kernel: pid 72554 (smtp), uid 125: exited on signal 11
Dec 10 16:19:44 saruman kernel: pid 72542 (smtpd), uid 125: exited on signal 11
Dec 10 16:28:18 saruman kernel: pid 72785 (smtpd), uid 125: exited on signal 11

Nach einigem Ausprobieren (Deaktivieren sämtlicher Postfixerweiterungen wie Postgrey, Amavisd-New, dccifd, policyd-weight), Neukompilieren von Postfix mit allen Paketen, von denen es selber abhängig ist, und natürlich ausgiebigen Netzrecherchen bin ich auf diesen Thread der Postfix-User ML gestoßen und die schon 2 Jahre alte und für ein 2.9er Postfix unter FreeBSD 9.2 vorgeschlagenen Lösung, die OpenSSL Kompression beim Bauen von OpenSSL wegzulassen hat mir aktuell auch noch geholfen. Nachdem ich erst OpenSSL ohne ZLIB Option und dann Postfix neu kompiliert hatte, traten keine Signal 11 Crashs mehr auf.

RBLs für Postfix

Ich wollte schon länger endlich mal die von mir in Postfix genutzten RBLs dokumentieren (das sind direkt die entsprechenden Zeilen aus der main.cf):

reject_rbl_client dynablock.easynet.nl,
reject_rbl_client proxies.blackholes.easynet.nl,
reject_rbl_client ix.dnsbl.manitu.net,
reject_rbl_client relays.bl.kundenserver.de,
reject_rbl_client relays.nether.net,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client list.dsbl.org,
reject_rbl_client psbl.surriel.com,
reject_rbl_client spamguard.leadmon.net,
reject_rbl_client dnsbl.ahbl.org,
reject_rbl_client virbl.dnsbl.bit.nl,
reject_rbl_client all.rbl.kropka.net,
reject_rbl_client dnsbl.njabl.org,
reject_rbl_client cbl.abuseat.org,
reject_rbl_client bl.csma.biz,
reject_rbl_client 0spam.fusionzero.com,
reject_rbl_client aspews.ext.sorbs.net,
reject_rhsbl_sender dsn.rfc-ignorant.org,
check_sender_access hash:/usr/local/etc/postfix/spamlist,
check_policy_service inet:127.0.0.1:12525,
reject_unauth_destination,
permit

 

#  reject_rbl_client sbl.csma.biz,
# scheint nicht mehr zu existieren: reject_rbl_client opm.blitzed.org,
# blockt freebsd.org: reject_rbl_client all.rbl.kropka.net,
# Fuer die kubanischen Emailpartner eines Kunden rausgenommen (24.03.07):
# reject_non_fqdn_sender, #reject_unknown_sender_domain,
# Scheint nicht mehr zu existieren (09.02.07): reject_rbl_client relays.bl.kundenserver.de,
# beide RBLs wurden zusammengefasst reject_rbl_client sbl.spamhaus.org,
# reject_rbl_client xbl.spamhaus.org,
# RBL hatg dicht gemacht: reject_rbl_client relays.ordb.org,
# blocked Volksbank (08.09.06): reject_rbl_client cbl.abuseat.org, testweise reaktiviert
# nicht erreichbar (27.02.06): reject_rbl_client dun.dnsrbl.net,
# reject_rbl_client spam.dnsrbl.net,
# blockt T-Online (27.10.05) reject_rbl_client dnsbl.ahbl.org,
# blockt GMX (07.10.05) reject_rbl_client list.dsbl.org,
# blockt Kunden von XYZ  reject_rbl_client bl.spamcop.net,
# blockt Kunden von YZX reject_rbl_client spamsources.fabel.dk,
# reject_rbl_client kr.rbl.cluecentral.net,
# reject_rbl_client kr.countries.nerd.dk,
# blockt Kunden von ZXY reject_rbl_client cn.rbl.cluecentral.net,
# reject_rbl_client cn.countries.nerd.dk,
# reject_rbl_client korea.services.net,
# reject_rbl_client dnsbl.njabl.org,
# reject_rbl_client relays.bl.kundenserver.de,
# blockt Mailer Uni Marburg: reject_rhsbl_sender dsn.rfc-ignorant.org,
# blockt GMX: reject_rbl_client blackholes.five-ten-sg.com,
# kostenpflichtig: reject_rbl_client dialups.visi.com,
# reject_rbl_client relays.visi.com,
# reject_rbl_client dnsbl.njabl.org,
# warn_if_reject reject_unverified_sender,
# reject_rbl_client dul.dnsbl.sorbs.net,
# reject_rbl_client blackholes.easynet.nl,
# reject_rbl_client bl.spamcop.net,
# eingestellt: reject_rbl_client proxies.relays.monkeys.com,
# reject_rbl_client formmail.relays.monkeys.com,
# eingestellt: reject_rbl_client dialups.relays.osirusoft.com,
# reject_rbl_client inputs.relays.osirusoft.com,
# reject_rbl_client spamhaus.relays.osirusoft.com,
# reject_rbl_client spamsites.relays.osirusoft.com,
# reject_rbl_clientsocks.relays.osirusoft.com, # reject_rbl_client proxy.relays.osirusoft.com,
# reject_rbl_client spews.relays.osirusoft.com,
# reject_rbl_client sg.countries.nerd.dk,
# reject_rbl_client tw.rbl.cluecentral.net,
# reject_rbl_client tw.countries.nerd.dk,
# reject_rbl_client vn.rbl.cluecentral.net,
# reject_rbl_client vn.countries.nerd.dk,
#  kostenpflichtig: reject_rbl_client blackholes.mail-abuse.org,
#  kostenpflichtig: reject_rbl_client relays.mail-abuse.org,

Die RBLs habe ich größtenteils von einer Liste von DECLUDE. Eine weitere Aufstellung von RBLs findet man bei DNSBL.info.

Probleme mit einem Postfix-Mailserver, der seine Userdaten aus einer MySQL-DB holt

Vor ein paar Tagen bekam der Mailserver eines von mir betreuten Root-Servers mehrfach pro Tag Probleme, die sich zunächst in Mails mit Fehlerbenachrichtigungen manifestierten. In diesen Mails, die ein Subject der Art "Postfix SMTP server: errors from unknown[216.1.64.211]" und ungefähr folgendem Inhalt hatten:

Transcript of session follows.

 Out: 220 hostname.server.tld ESMTP Postfix (2.5.5)
 In:  EHLO DougTest
 Out: 250-hostname.server.tld
 Out: 250-PIPELINING
 Out: 250-SIZE 50000000
 Out: 250-ETRN
 Out: 250-STARTTLS
 Out: 250-AUTH LOGIN PLAIN
 Out: 250-AUTH=LOGIN PLAIN
 Out: 250-ENHANCEDSTATUSCODES
 Out: 250-8BITMIME
 Out: 250 DSN
 In:  MAIL FROM:<believersn3@iinet.net.au>
 Out: 250 2.1.0 Ok
 In:  RCPT TO: <username@kundendomain.tld>
 Out: 451 4.3.0 <username@kundendomain.tld>: Temporary lookup failure
 In:  DATA
 Out: 554 5.5.1 Error: no valid recipients
Session aborted, reason: lost connection

Nach ein paar Minuten hat sich dann scheinbar alles wieder normalisiert und es waren nur noch Spuren in den Logs zu finden. Auszug aus den Logdatein: postfix-mysql-problem.log Dieses Problem trat mehrfach pro Tag auf, aber in absolut unregelmäßigen Abständen und mit unterschiedlich häufigen Vorfällen pro Tag. Nach 2 oder 3 Tagen kam es dann auch zu Loginproblemen via POP3 und IMAP, u.a. auch via Webmail, denn auch Cyrus arbeitet hier mit virtuellen Usern via MySQL-DB. Es konnte dann auch keine Mail mehr verschickt werden. Googlen nach "fatal: mysql:/usr/local/etc/postfix/mysql-mydestination.cf(0,lock|fold_fix): table lookup problem" und anderen Symptomen brachte zunächst nichts. Ich habe dann erstmal die Zahl der postfix smtp und amavisd child Prozesse hochgesetzt und gegenseitig angepaßt, da ich erst dachte, daß es vielleicht bei der Zahl der Prozesse die bei Postfix und Amavisd-new sich gegenseitig zuarbeiten, vielleicht klemmt – aber das hatte keinen nennenswerten Erfolg. Erst das Suchen nach "mysql to many connections" brachte mich auf diese Seite und damit der Lösung näher. Eine Überprüfung des Werts von max_connections vom MySQL-Server mit

show variables like 'max_connections';

zeigte dann, daß der Default-Wert des mysql-server 5.0 Ports unter FreeBSD 6.4 sogar nur 100 beträgt. Ich habe ihn dann zunächst mit

set GLOBAL max_connections=500;

vorläufig hochgesetzt und dann durch Einfügen einer Zeile

set-variable=max_connections=500

in der Rubrik [mysqld] der /usr/local/etc/my.cnf den Wert dauerhaft gesetzt. Seitdem ist das Problem nicht wieder aufgetreten. Wie man im Log /var/log/messages sehen kann, findet gleichzeitig ein brute force Eindringversuch statt und da sowohl bei jeder eintreffenden Mail als auch bei jedem Mailabruf mindestens eine MySQL-Abfrage auslöst, treibt das die Zahl der gleichzeitigen Verbindungen erheblich in die Höhe und so kam es durch die wieder ansteigende Spamwelle, den brute force Angriff und die natürlich auch noch stattfindenden MySQL-Verbindungen durch PHP-Webanwendungen zu Situationen, in denen der Default-Wert von 100 Verbindungen nicht ausgereicht hat.