Mit GeoIP auf Fährtensuche
Das Netz ist voll von Spammern und Botnet-Drohnen, die ständig auf der Suche nach Sicherheitslücken, an den Türen der Web-Server rütteln. Sind diese einmal “assimiliert”, starten die Zombiserver bei Bedarf ihre Attacken auf ahnungslose Home-User, oder dienen als Kontrollinstanz für bereits infizierte Spamschleudern im heimischen Wohnzimmer. Sehr oft werden Server im Internet über den Webserver attakiert. Man nutzt Sicherheitslücken im System und schlecht programmierte Scripte als Einstiegsluke. Ich habe die Logfiles (dafür sind sie da) des Apachen meiner Linuxfirewall über lange Zeit genau studiert, um herauszufinden, wie dabei vorgegangen wird. Dabei viel mir auf, daß der erste Kontakt mit Hilfe von BotNetSpidern hergestellt wird, die entweder über das Tornetzwerk [auch hier gibt es ein Kraut gegen=)] oder über Proxyserver (CN, US, RU) operieren. In den Logfiles des Apachen steht entweder die IP-Addresse oder je nach Einstellung der httpd.conf (HostnameLookups =on/off) der DNS-Name des anfragenden Client. Schön wäre es, wenn dort gleich die Herkunft der Anfrage zB. in der Form “DE, Deutschland, Hamburg” stehen würde. Nun, dem kann mit GeoIP abgeholfen werden. Wir werden später sehen, daß sich die Informationen, die uns GeoIP zur Verfügung stellt, auch ganz wunderbar für eine Applikationsfirewall (mod_security) nutzen lassen.
Doch nun zu GeoIP selbst. Wir benötigen die GeoIP C Libary (API), die GeoIP Datenbank selbst (am besten beide -> GeoLite City und GeoLite Country) und das Modul mod_geoip für den Apachen. Die “Lite”-Versionen genügen unseren Ansprüchen und sie kosten nichts. Die C-Libary kompilieren wir mit dem klassischen Dreisatz:
./configure –PREFIX=/usr –with-dbdir=/Datenbankpfad/
make
make install
Zu dem Pfadangaben der Datenbanken werfen wir einen Blick in die “README”. In dem angegebenen Pfad sollten sich auch die einzelnen DB-Files befinden. Doch lässt sich der Pfad auch nachträglich per Direktive setzen. Das Paket enthält ein Programm namens “geoiplookup”, welches wir nun ausführen.
geoiplookup 212.12.12.12
Wir sollten in etwa GeoIP Country Edition: RU, Russian Federation als Antwort erhalten. Die übergebene IP oder auch eine Domain können frei gewählt werden. Im nächsten Schritt installieren wir das Modul für den Apachen (mod_geoip2_1.2.5.tar.gz) und übersetzen dieses mit apxs(2). Evtl. müssen die Devel-Pakete des Apachen nachinstalliert werden. Merke: Wer sich seinen Kram aus den Sourcen selbst übersetzt, sieht später auch weniger Compilerfehlermeldungen, weil die Headerdateien bzw. “Optionale Dinge” mal wieder fehlen.
apxs -i -a -L/usr/local/lib -I/usr/local/include -lGeoIP -c mod_geoip.c
Die Pfadangaben beziehen sich dabei auf die Location der “GeoIP.h” bzw. “libGeoIP”.
Achtung! apxs ändert die httpd.conf! Nach dem kompilieren sollte diese überprüft werden. Ich sichere diese stets vor der Kompilierung eines Moduls, schreibe sie dann zurück und füge die Ladeanweisung für zusätzliche Module von Hand ein.
LoadModule geoip_module modules/mod_geoip.so
Um das Modul zu aktiviren etc. gehören weiterin folgende Anweisungen in die httpd.conf bzw. in die default.conf:
GeoIPEnable On
GeoIPOutput All
GeoIPDBFile /pfad/geoip/GeoIP.dat MemoryCache
GeoIPDBFile /pfad/geoip/GeoLiteCity.dat
GeoIPScanProxyHeaders On
Zu den einzelnen Optionen lese man die “README”. Die GeoLityCity-DB sollte man nicht unbedingt in den Speicher laden;). Nun starten wir den Apachen neu. Das sollte er auch tun. Ansonsten hilft bei Fehlern das studieren des “error_log” des Apachen. Um nun zB. Zugriffe aus China, Russland, den USA etc. verweigern, fügt man folgende Zeilen in den entsprechenden VHosts ein:
SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE US BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE IT BlockCountry
und in den Location-Container:
Order allow,deny
Allow from all
Deny from env=BlockCountry
Dann starten wir den Apachen neu. Anschließend greifen wir extern über einen Proxy, der auf einen Standort innerhalb unserer Blacklist beruht, auf unseren Webserver zu, zB. über diese Liste. Der Zugriff sollte uns verweigert werden und im “error.log” sollte etwa stehen:
[error] [client 72.30.142.243] client denied by server configuration: /var/www/html/robots.txt
Nun wollen wir aber wissen, woher der Zugriff genau gekommen ist. Dazu modifizieren wir die “LogFormat”-Anweisung in der httpd.conf und erweitern diese um die Environment Variablen des Moduls mod_geoip. Folgende Variablen stehen bei Verwendung der “GeoLite City“-Datenbank zur Verfügung:
GEOIP_CONTINENT_CODE, GEOIP_COUNTRY_CODE, GEOIP_REGION, GEOIP_REGION_NAME, GEOIP_CITY, GEOIP_DMA_CODE, GEOIP_AREA_CODE, GEOIP_LATITUDE, GEOIP_LONGITUDE, GEOIP_POSTAL_CODE
Dies geschieht mit dem Parameter “%e“, wobei die Variable von dem Parameter umschlossen wird “%{GEOIP_CITY}e“. Hier mein verwendetes Beispiel:
LogFormat “%h %l %u %t \”%r\” %>s %b \”%{GEOIP_CITY}e\” \”%{GEOIP_COUNTRY_CODE}e\” \”%{GEOIP_REGION_NAME}e\”" combined
Nach der Modifizierung starten wir erneut den Apachen neu und greifen wieder über einen Proxy auf unseren Webserver zu. Anschließend werfen wir einen Blick in das “access.log” des Apachen. Dort sollte nun die Stadt, der Ländercode und die Region des Request auftauchen:
…HTTP/1.1″ 404 1181 “-” “Bocholt” “DE” “Nordrhein-Westfalen” “Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18)…
Sehr schön =). Wir wollen aber mehr!
Mit mod_geoip, mod_security und modsec2iptables können wir eine dynamische Firewall für unseren Webserver einrichten, die “die bösen Jungs” für eine bestimmte Zeit per “iptables” sperrt. Denn auch mod_security kann die Environment Variablen des Apachen für SpezialRules verwenden. Getestet habe ich es mit der älteren, aber sehr stabilen Version von mod_security-1.9.5. Wir schreiben eine neue Rule, die bewirkt, daß IP-Adressen aus den “USA” der Zugriff auf unseren Server verwehrt bleibt.
SecFilterSelective ENV_GEOIP_COUNTRY_CODE “^US$”
Wenn man keine Actions innerhalb der Rules angibt, so greift bei mir die Option:
SecFilterDefaultAction "deny,log,status:403,exec:/pfad/zu/modsec2iptables"
Die IP wird quasi an “modsec2iptables” übergeben. Dieses Modul generiert eine IP-Table-Rule und reicht diese dann an “iptables” weiter. Beim zweiten Request antwortet dann unser Webserver gar nicht mehr;). Im Logfile von mod_security sollte in etwa folgendes stehen:
Access denied with code 0. Pattern match "^US$" at ENV("GEOIP_COUNTRY_CODE")
Doch nun haben wir auch Google ausgesperrt. Besser wäre also folgende Rulekombination:
SecFilterSelective ENV_GEOIP_COUNTRY_CODE “^US$” chain
SecFilterSelective REMOTE_HOST “!.*googlebot\.com$”
Erklärung: Alles was aus den USA kommt, wird darauf geprüft, ob die Hostvariable den String “googlebot.com” enthält. Wenn ja, so darf Google passieren. Alles andere landet im Müll. Ohne Ausrufezeichnen ( ! = nicht) würde nur Google geblockt. Der DNS-Name des Google-Bot hat folgende Notation: “crawl-66-249-71-67.googlebot.com“. Wenn man nur Anfragen aus Deutschland, der Schweiz und Österreich zulassen will so genügt eine einzige Rule, oder mit Google dann analog:
SecFilterSelective ENV_GEOIP_COUNTRY_CODE "!^(DE|CH|AT)$” chainSecFilterSelective REMOTE_ADDR|REMOTE_HOST "!.*googlebot.com$”
Eine Liste der Ländercodes findet sich hier. Will man nun wissen, was so alles auf auf den IP-Tables gelandet ist, so gibt man an der Console einfach “modsec2iptables -s” ein. Es erscheint eine Liste der gesperrten IP’s.
Banned IP Reverse Lookup Date66.55.143.198 66-55-143-198.steam101.com 25.02.2009 18:45:05
Nun hat man die Qual der Wahl. Entweder man verweigert per “Location”-Direktive innerhalb des VHost oder man verwendet eben mod_security und optional “modsec2iptables” um gemeine Rules zu schreiben. Auch über mod_rewrite können Regeln definiert werden. Beispiele finden sich auf der MaxMind-Seite. Da wir sehr viele Environment Variablen von mod_geoip zu Verfügung haben, könnten wir den Zugriff durchaus nur auf einen Postleitzahlenbereich xyz, oder nur auf Europa beschränken. Zusammen mit den hoffentlich gut durchdachten anderen mod_security-Rules haben wir mit den GeoIP-Environement Variablen ein mächtiges dynamisches Werkzeug gegen Spam und automatisierte “Türrüttler” in der Hand.