Beiträge mit dem Tag apache

fail2ban – die phpMyAdmin-Sucher bannen

Erstellt von am Freitag, 1 April, 2011

Schaut man sich bei Langeweile mal die Datei [/var/log/apache2/error.log] an, finden sich oft Einträge in der abgebildeten Form.

[error] [client 91.121.xxx.xxx] File does not exist: /var/www/PMA
[error] [client 91.121.xxx.xxx] File does not exist: /var/www/dbadmin
[error] [client 91.121.xxx.xxx] File does not exist: /var/www/pma
[error] [client 91.121.xxx.xxx] File does not exist: /var/www/dbadmin

Irgendwelche Spaßvögel versuchen hier also tapfer das phpMyAdmin-Verzeichnis zu finden – oder auch andere Sachen, wie etwa RoundCube, Foren-Verzeichnisse usw.

Da derartige unnötigen Log-Einträge auf Dauer einfach nur die Übersicht kaputtmachen und irgendwie schlichtweg nerven, wollte ich die gerne künftig weitgehend unterbinden. Nur wie?

fail2ban bringt’s

Des Admins Freund ist hier fail2ban, ein Tool, welches es erlaubt, basierend auf bestimmten Filterregeln Logfiles zu prüfen und bei einem auf den Filter passenden Fund eine bestimmte Aktion auszuführen. fail2ban bringt dabei einige vordefinierte Regeln mit, netterweise auch schon für mein spezielles Problemchen. In der Standard-Einstellung ist die Regel jedoch nicht aktiv – und dazu leider in der Version von fail2ban, die mit Debian Squeeze verfügbar ist, auch noch fehlerhaft. Also ist Nacharbeit angesagt…

filter.d/apache-nohome.conf

Hauptsächlich wichtig zur Konfiguration von fail2ban ist die [/etc/fail2ban/jail.conf] und die einzelnen Dateien unter [/etc/fail2ban/filter.d/].

Der für mich notwendige Filter ist in der Datei [/etc/fail2ban/filter.d/apache-nohome.conf] hinterlegt – das sieht dann so aus:

# Fail2Ban configuration file
#
# Author: Yaroslav O. Halchenko <debian@onerussian.com>
#
# $Revision: 716 $
#

[Definition]

# Option: failregex
# Notes.: regex to match failures to find a home directory on a server, which
# became popular last days. Most often attacker just uses IP instead of
# domain name -- so expect to see them in generic error.log if you have
# per-domain log files.
# Values: TEXT
#
# failregex = [[]client <HOST>[]] File does not exist: .*/~.*
failregex = [[]client (?P<host>\S*)[]] File does not exist:

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

Die wichtige Zeile ist dabei normalerweise diese hier (von fail2ban vorgegeben):

failregex = [[]client <HOST>[]] File does not exist: .*/~.*

Anhand dieses netten regulären Ausdrucks checkt nun fail2ban die error-Logs auf Einträge in denen der String “File does not exist” vorkommt. Testen kann man das mit dem Tool fail2ban-regex etwa wie folgt:

fail2ban-regex /var/log/apache2/error.log '[[]client <HOST>[]] File does not exist: .*/~.*'

Hier stellte sich bei mir dann Überraschung ein – es wurden keine Treffer gefunden und das trotz deutlich mehr als 100 vorhandenen Einträgen in dieser Form! Irgendwas läuft da also schief. Nur was? Es kann an sich ja nur der reguläre Ausdruck sein… Also einmal den Spürhund Google befragen – und siehe da, da ist tatsächlich ein Fehler drin.

Der korrekte Ausdruck muss wie folgt aussehen, dann funktioniert das auch:

failregex = [[]client (?P<host>\S*)[]] File does not exist:

[Update]

Unter folgendem Link ist auch noch mal eine Config genannt, bei der gezielt auf bestimmte Ordnernamen geprüft wird:

http://www.foosel.org/blog/2008/04/banning_phpmyadmin_bots_using_fail2ban

Außerdem hier noch einige Beispiele direkt aus dem Fail2Ban Wiki:

http://www.fail2ban.org/wiki/index.php/Apache

[Update Ende]

So, damit ist der Filter definiert. Damit fail2ban den Filter auch nutzt, geht’s nun zur jail.conf

jail.conf

[apache-nohome]
enabled = true
port = http
filter = apache-nohome
logpath = /var/log/apache*/*error.log
bantime = 604800
maxretry = 3

bantime gibt dabei an, für wie viele Sekunden eine IP gesperrt werden soll, wenn der Filter greift. Ich bin der Meinung, erwähnten Spaßvögeln soll für eine Woche der Spaß vergehen, daher setze ich die bantime auf 604800 Sekunden.

maxretry wiederum bestimmt, wie oft der Fehler auftreten darf, bevor die Sperre aktiviert wird.

Damit fail2ban die geänderte config berücksichtigt fehlt nur noch ein kurzer Neustart des Dienstes:

/etc/init.d/fail2ban restart

Erfolgs-Kontrolle

Das war’s auch schon – versucht nun jemand das phpMyAdmin-Verzeichnis oder irgendeine beliebige andere Anwendung im Webspace zu finden, ist nach 3 Versuchen Schluss mit lustig.

Kontrollieren lässt sich der Erfolg in der Datei [/var/log/fail2ban.log], hier finden sich bei einem Treffer Einträge ähnlich diesen hier:

fail2ban.actions: WARNING [apache-nohome] Ban 211.220.194.217
fail2ban.actions: WARNING [apache-nohome] Ban 41.203.119.18
fail2ban.actions: WARNING [apache-nohome] Ban 114.207.245.190

Schon werden die anfangs genannten Einträge im Apache Error-Logfile deutlich seltener auftreten, denn nach 3-maligem Auftreten sperrt ja nun fail2ban. Habe fertig!

Plesk 9 und PHP 5.2.13/5.3 – so geht’s

Erstellt von am Mittwoch, 12 Mai, 2010
php_5-2-13_dotdeb

PHP 5.2.13 über dotdeb.org installiert

Das Plesk Panel von Parallels ist eine (meiner Meinung nach) recht angenehme Variante, einen Web-Server zu verwalten. Alltägliches, wie z. B. das Einrichten einer neuen E-Mail-Adresse, das Anlegen einer Subdomain oder ähnliche Aufgaben lassen sich mit wenigen Klicks bewerkstelligen. Besonders angenehm ist auch, dass sich in den “Webhosting-Einstellungen” einer Domain jederzeit die PHP-Einbindung wählen lässt: die Standard-Variante als Apache-Modul (mod_php) oder doch lieber per fastcgi.

Der Vorteil bei fastcgi ist dabei, dass dann gleich auch die Erweiterung suexec aktiv geschaltet wird, was dazu führt, dass PHP-Skripte mit den Rechten des FTP-Users, dem die Skripte gehören, ausgeführt werden. Das ist äußerst praktisch – sonst teilweise recht nervige Update-Prozeduren von z. B. WordPress Themes/Plugins laufen einfach so durch.

Das Problem

Wie überall bei Software gibt es natürlich auch bei Plesk verschiedenste Punkte, an denen der Spaß aufhört und man die Komplexität des Systems verflucht. Dabei spielt vor allem die als Standard mit Plesk installierte PHP-Version eine große Rolle. Einerseits, weil ein auf Sicherheit bedachter Admin logischerweise gerne Updates einspielen würde – andererseits, weil bestimmte PHP-Funktionen nun mal erst ab einer bestimmten Version verfügbar sind. Selbst die neueste Plesk-Version 9.5.1 bringt je nachdem, auf welchem System sie eingesetzt wird, aber nur veraltete PHP-Versionen mit bzw. zieht sich diese aus den Repositories der Distribution. Möchte man aber aus zuvor erwähnten Gründen eine aktuellere PHP-Version einsetzen, fängt’s an haarig zu werden.

Wichtige Info:

Wer auch immer das liest – bitte beachte, dass ich hier nur meine “Odyssee” schildere und wie es dann letztlich funktioniert hat. Dieser Beitrag will kein Tutorial sein! Bitte daher nicht einfach irgendeinen der Schritte nachvollziehen, ohne vorher den gesamten Artikel gelesen zu haben – könnte nämlich zu extrem unerwünschten Ergebnissen führen… Danke Anke. :-)

Ein Ansatz…

Mein erster Gedanke war: Das kann doch nicht so schwer sein! Ich lade mir einfach die Quellen einer aktuellen PHP-Version, kompiliere die selbst und schiebe sie Plesk unter. Gedacht, umgesetzt, … gescheitert. Bei der Umsetzung wird das Ganze nämlich schon lustig. Wer so was schon mal gemacht hat weiß, dass so ein configure-Befehl sehr mächtig ist bzw. eine Menge Optionen mitbringt. Bei PHP ist es besonders wichtig, denn schließlich sollen alle derzeit auf dem System aktiven Erweiterungen auch in der neu kompilierten Version mit drin sein!

Nun ja, erster Schritt: Unter http://www.php.net/downloads.php#v5 die gewünschte PHP-Version geladen (hier 5.2.13), entpackt und mal eben die möglichen Schalter des “configure” angezeigt.

wget http://de3.php.net/get/php-5.2.13.tar.gz/from/this/mirror
tar xvzf php-5.2.13.tar.gz
rm php-5.2.13.tar.gz
cd php-5.2.13
./configure --help | less

Der letzte Befehl gibt die Hilfe und damit auch die möglichen Optionen/Schalter für den “configure”-Befehl für PHP aus. Eine schnelle Zählung ergibt mal eben schlappe 219 Optionen. Nun wäre allein das ja nicht so tragisch, wenn man weiß, wie die aktuelle Konfiguration aussieht. Dann würde es ausreichen, die korrekten Optionen zu setzen und configure auszuführen. Nur: wie lässt sich die aktuelle Konfiguration verlässlich herausfinden? Mit welchen Erweiterungen wurde das derzeit installierte PHP kompiliert?

Configure-Gerätsel

Bei einigen Webhostern wird über den PHP-Befehl phpinfo(); auch der “Configure Command” mit ausgegeben. Mit dieser Info hat man schon mal so gut wie gewonnen. Denn diese Anzeige gibt nun mal genau aus, wie PHP konfiguriert wurde. Ein simples copy & paste sollte also ausreichen, um die neue PHP-Version auf den Weg zu bringen.

Das ist leider bei einer Plesk-Installation in der Regel nicht der Fall – hier fehlt der “Configure Command” in der phpinfo()-Ausgabe. Also wo bekommt man diese Info dann her? Selbst wenn man sämtliche in der über phpinfo ausgegebenen Aufstellung angezeigten Module und Erweiterungen durchforsten würde, kann man daraus nicht zuverlässig den Configure-Befehl ableiten.

Ich habe auf diesem Weg zwei Tage vergeudet – mehrere Stunden intensiver Google-Suche eingeschlossen und bin zu keiner zufriedenstellenden Lösung gekommen, wie man an diese Information kommt. Zwar gibt es alle möglichen sehr informativen Anleitungen, wie PHP auf diesem Weg zu konfigurieren und installieren ist. So fand ich bspw. diese Anleitung sehr hilfreich: Websiteentwicklung: PHP: Installation: UNIX-artige_Systeme. Mein großes Fragezeichen war damit aber immer noch nicht beantwortet.

Ein anderer Ansatz

Weil mir irgendwann die Lust verging und ich auch mal wieder was anderes zu tun hatte, als stundenlang verzweifelt nach einer Antwort zu suchen, musste eine andere Lösung her. Mir fiel wieder ein, dass ich irgendwo mal vorkompilierte Installationspakete für aktuelle PHP-Versionen für die verschiedenen Linux-Distributionen gefunden hatte. Also noch mal eben danach gesucht und siehe da, dotdeb.org führt unter dem Link http://www.dotdeb.org/mirrors/ eine Liste der verschienden Spiegelserver für Debian-basierte Server. Demnach auch für mich – welch Freude!

Damit diese Quellen verwendet werden, ist nur eine kurze Anpassung der Datei “/etc/apt/sources.list” erforderlich:

nano /etc/apt/sources.list

Hier habe ich dann an’s Ende die Mirrors von dotdeb.org für Deutschland eingefügt.

deb http://ftp.hosteurope.de/mirror/packages.dotdeb.org/ stable all
deb-src http://ftp.hosteurope.de/mirror/packages.dotdeb.org/ stable all
deb http://dotdeb.netmirror.org/ stable all
deb-src http://dotdeb.netmirror.org/ stable all

Wieder mal gedacht, jetzt ist alles toll – und über “apt” ein update & upgrade ausgeführt:

apt-get update && apt-get upgrade

Und siehe da – es gibt Updates für PHP auf die von mir gewünschte Version 5.2.13. Installieren? Ja klar! Bei der Installation gab’s keine Schwierigkeiten, alle Abhängigkeiten wurden erfüllt, so soll’s sein. Auf die Frage hin, ob die vorhandenen Konfigurationsdateien beibehalten werden sollen, antworte ich natürlich mit “Ja” – schließlich sollen die Einstellungen so bleiben, wie sie sind!

Dann der große Test – was sagt phpinfo? Yeah, auch hier sieht’s gut aus: “PHP Version 5.2.13″ wird angezeigt. Soweit so gut.

Was folgt, ist… Ernüchterung. Aus welchen Gründen auch immer – mein Blog läuft nicht mehr. Eine kurze Nachforschung ergibt: PHP wurde zwar aktualisiert, aber trotz der Entscheidung, die Konfigurationsdateien wie gehabt zu behalten, wurde die MySQL-Erweiterung nicht bzw. nicht korrekt installiert.

Toll – auf diesem Weg also auch kein Erfolg gehabt. PHP ist zwar aktuell, aber die Installation ist zerschossen. Was nun?

Unkonventionell und unpraktisch – aber endlich eine Lösung

Die Lösung ergab sich letztlich durch den Umstand, dass ein Update von Plesk vor der Tür stand. Momentaner Stand war Plesk 9.3 – die neue Version Plesk 9.5.1 sollte installiert werden. Da neue Plesk-Versionen mit Vorsicht zu genießen sind, gerade, wenn diese als Upgrade von einer kleineren Version ausgeführt werden, habe ich das Ganze erst einmal auf den späten Abend verschoben.

Abends stand dann erst mal eine Sicherung des Servers an, Blog + Datenbank exportieren und dann… einfach mal eben eine Neuinstallation des Servers mit Minimal-System. Gut dass das kein Produktiv-System mit anderen Usern drauf ist, sondern halt einfach nur ein privater Blog drauf läuft. Da ist sowas schon mal eben vertretbar.

Nach der Neuinstallation des Systems kurz eben einmal die Updates ziehen und los geht’s. Da das PHP-Update bei einer vorhandenen Plesk-Installation scheiterte, dachte ich mir, schiebe ich Plesk doch einfach schon während der Installation die neue PHP-Version unter! Und so hat’s dann auch funktioniert.

Kurz bei Parallels unter “http://www.parallels.com/de/download/plesk/products/” einen Account angelegt und den “autoinstaller” für meine Distribution herunter geladen. Dann die “sources.list” angepasst und den Installer von Plesk gestartet…

wget __link_zur_gewünschten_Plesk_Version__
nano /etc/apt/sources.list   # Sources von dotdeb.org, wie beschrieben
chmod +x __heruntergeladene_plesk_datei__    # herunterladene Datei ausführbar machen
./__von_parallels_heruntergeladene_datei__   # autoinstaller starten

Hangelt man sich nun durch das Menü des Autoinstallers und lässt die Installation dann durchlaufen, zieht sich das Plesk-Tool brav aus den Quellen die aktuelle PHP-Version und installiert diese. Heureka!

Abschließend stand dann noch an, das Datenbank-Backup und die Blog-Daten wieder einzuspielen und einzurichten, was dann relativ schnell erledigt war. Komfortabler geht es natürlich über den Plesk-Backup-Manager. Nutzt man diesen, um z. B. einmal pro Tag eine automatische Sicherung des gesamten Servers, soweit es Plesk betrifft, durchzuführen, so braucht man nach der Neuinstallation einfach nur wieder die Daten des FTP-Servers einzutragen, auf dem das Backup liegt. Gibt Plesk noch eben den Auftrag das Backup zurückzuspielen und schon steht die Einrichtung wieder.

Das Beschriebene lässt sich natürlich statt mit PHP 5.2.13 auch genauso mit PHP 5.3.2 durchführen.

Fazit:

Ob sich der ganze Aufwand lohnt / gelohnt hat, ist die Frage. Ich denke schon – immerhin habe ich nun die neueste PHP-Version am Laufen. Seitdem funktioniert auch FastCGI und suexec ohne Probleme. Und falls zukünftig irgendwann mal wieder eine Serverneuinstallation ansteht, weiß ich nun, das Plesk von Anfang an die korrekte Version untergeschoben bekommen muss, damit es läuft ohne zu meckern.

Es bleiben allerdings noch offene Fragen:

  • Wie vertrauenswürdig sind die Quellen von dotdeb.org? Sind die “produktiv-System-tauglich”?
  • Wieso hat die Installation der Pakete von dotdeb.org im laufenden Betrieb versagt, obwohl ich die bestehenden Config-Files beibehalten habe?
  • Warum finde ich verflixt noch eins keine Info dazu, wie ich mir den “Configure Command” der jeweils aktuell installierten PHP-Version anzeigen lassen kann, wenn dieser nicht per phpinfo() auftaucht?
  • Und wenn ich dann diese Info irgendwann mal finden sollte… wird das Kompilieren und Installieren der dann aktuellen PHP-Version sauber vonstatten gehen oder wird’s wieder scheitern?

Für Infos bin ich dankbar – nutzt bitte einfach die Kommentar-Funktion. Danke :-)

Apache + PHP: stop talking!

Erstellt von am Samstag, 14 November, 2009

Apache + PHP

Bei einer kürzlichen Kontrolle

des Apache-Logfiles fielen mir massenweise folgender Meldungen auf:

[Sat Nov 07 12:00:49 2009] [error]
[client xxx.xxx.xxx.xxx] client sent HTTP/1.1 request without hostname
(see RFC2616 section 14.23): /w00tw00t.at.ISC.SANS.DFind:)

Da man Anfragen an einen Server ja in der Regel nicht ohne Grund stellt, ist natürlich die Frage: Was gibt denn der Server für Infos als Header raus, wenn ein HTTP-Request gestellt wird?

Wie ich feststellen musste, sind das in der Standard-Konfiguration jede Menge Infos! Darunter unter Anderem:

  • verwendetes Betriebssystem
  • verwendeter HTTP-Server mit Versionsnummer
  • installierte Mods, wie z. B. Python, SSL, Perl, etc. sowie die jeweilige Version
  • bei Aufruf einer PHP-Seite auch die PHP-Version

Kurz darüber nachgedacht… Wen gehen diese Daten etwas an? Tja, aus Sicherheitsgründen eigentlich niemanden, der nicht direkt aus Verwaltungsgründen oder Programmierfragen etwas mit dem Server zu tun hat. Also – wie bringe ich Apache und PHP bei, nicht so zu tratschen?

Die Lösung

sind zwei Einträge in den Konfigurationsdateien von Apache und PHP.

Zuerst der Eintrag für den Apache – wieviele Infos der Apache preisgeben darf legt man über den Eintrag “ServerTokens” fest. Den kann man z. B. einfach ganz in die letzte Zeile der Datei /etc/apache2/apache2.conf schreiben.

Fünf Einstellungen stehen dabei zur Auswahl:

  • Kein Eintrag oder auskommentiert = Produktname + Version, Betriebssystem und Module
  • OS = Produktname + Version und Betriebssystem
  • Min = Nur Produktname + Version
  • ProductOnly = Nur Produktname
  • Major = Nur Produktname + Haupt-Versionsnummer

Also würde bspw. ein Eintrag in der Form “ServerTokens ProductOnly” dafür sorgen, dass im Header nur noch die Info “Server = Apache” mitgesendet wird.

Die zweite Änderung betrifft die Datei /etc/php5/apache2/php.ini – hier sucht man sich den Eintrag “expose_php =” und setzt diesen auf den Wert “Off“.

Abschließend

folgt noch ein Neustart des Apache-Servers über den Befehl “/etc/init.d/apache2 restart” und schon hat das Getratsche – wie im Bild zu sehen – ein Ende.

ScreenShot Antwort-Header

ScreenShot Antwort-Header