Nginx - (Geo) IP Blocking und User Agent Filter

Dieser Artikel zeigt, wie man Nginx sicherer macht, durch IP Blocking, basierend auf dem Herkunftsland der IP und dem Schutz vor potentiellen Zugriffen von Bots oder anderen Trackern.

Wichtig: Es werden die Module rewrite, map, geo und geoIp benötigt. Diese sollten bei den meisten Nginx Instanzen bereits installiert sein, anderenfalls müssen sie erst installiert werden.

Einrichten des Geo IP Blockings

Als erstes muss die entsprechende MaxMind Datenbank heruntergeladen werden, zum Blockieren nach dem herkunftsland der IP Adresse wird die Datenbank “Country” benötigt. Da MaxMind diese Datenbanken nur noch gegen Registrierung zum Download anbietet können diese von folgender (kostenloser) Seite bezogen werden.

Nach dem Download müssen sie die Datei “maxmind.dat.gz” noch extrahieren, um die Datenbank nutzen zu können.

Verschieben sie diese Datei nun in ein beliebiges Verzeichnis (ich empfehle das Nginx Konfigurationsverzeichnis, unter Linux wäre das /etc/nginx), sie müssen allerdings darauf achten, dass Nginx Berechtigungen zum Lesen der Datei hat.

Änderungen in der nginx Konfiguration

Nun zu den Veränderungen in der nginx Konfiguration, um das Blockieren von IPs mit GeoIp zu aktivieren fügen sie folgende Zeilen zu der nginx Konfigurationsdatei mit dem “http” Block hinzu (standardmäßig ist findet sich die Datei unter Linux in /etc/nginx.conf).

http{
...
  geoip_country /pfad/zur/datenbank/maxmind.dat
  map $geoip_country_code $blocked_countrys{
        default 1;
        DE 0;
  }
}

Zur Erklärung http{ steht hier nur zur Verdeutlichung, siehe obigen Text, steht für andere, für diesen Artikel unwichtige, Einträge der Konfiguration. Das Wichtige sind die GeoIp Einträge, dabei binden sie mit geoip_country eine Datenbank mit IP Adress-Bereichen und deren Landerzugehörigkeit ein. /pfad/zur/datei müssen sie damit mit ihrem eigenen Pfad ersetzen (wenn sie die Datenbank im selben Verzeichnis wie die nginx.conf haben, können sie den Pfad weglassen und nur maxmind.dat als Wert nutzen).

Als nächstes wird eine “Map” definiert, dies ist eine Variable, deren Wert auf anderen Variablen basiert. Dabei ist $geoip_country_code die Variable auf der der Wert der Map basiert, diese Variable des GeoIp Modules enthält bei jedem Zugriff auf den Server eine zweistellige Abkürzung eines Ländernamens (dieser wird mithilfe der IP des Zugriffes aus der Datenbank ermittelt, eine komplette Liste finden sie hier). $allowed_countrys ist der Name der Map, diesen können sie frei wählen (der Name sollte keine Sonderzeichen enthalten, das $ Zeichen am Anfang muss aber sein), dieser Name wird später zum Zugriff auf die Map genutzt.

Innerhalb der Map wird mit default 1; festgelegt, dass der Wert der Map zunächst 1 ist, mit der nächsten Zeile DE 0; wird der Wert auf 0 gesetzt, wenn $geoip_country_code, also der Ländercode, “DE” (Deutschland) ist, warum ausgerechnet 0 und 1, werden sie später verstehen. Ist der Ländercode ein Anderer, nicht festgelegter, bleibt der Wert der Map logischerweise bei 1. Sie können natürlich unter der Zeile mit dem deutschen Code weitere einfügen, achten sie nur darauf, dass sie nach dem Code immer 0; anhängen. Als Beispiel für die Schweiz müssten sie CH 0; hinzufügen. Hinweis: Es werden entweder alle IP Adressen eines Landes blockiert oder alle erlaubt, wenn sie nur einzelne blockieren/erlauben wollen/müssen, lesen sie im Anschluss beim Abschnitt White-/Blacklist mit dem geo Modul weiter. Auch lokale Adressen werden blockiert, das Freischalten dieser ist ebenfalls White-/Blacklist Abschnitt erklärt.

Um das Blocking zu aktivieren müssen sie in jedem server Block (in den Konfigurationen der Virtualhosts) direkt am Anfang, am besten unter server_name, folgenden Code hinzufügen.

server{
  ...
  server_name example.com;
  if ($blocked_countrys){
    return 444;
  }
 ...
}

Die Anweisung server_name ist hier nur zu Verdeutlichung zur Platzierung vorhanden. Zum blockieren der Anfragen wird eine if Bedingung genutzt, diese kennen sie sicherlich von anderen Programmiersprachen, deshalb auch die obigen Werte 0 (false) und 1 (true). Eine Besonderheit bei nginx ist jedoch, das zwichen if und er Klammer ein Leerzeichen sein muss. Denken sie daran, falls sie die Map anders benannt haben, dass sie hier ihren Namen der Map eintragen. Wenn nun der Wert 1 ist, wird Nginx durch return 444; angewiesen, die Verbindung mit dem Client sofort zu trennen (siehe Wikipedia: HTTP Status Codes) und ihm somit keine Möglichkeit zu geben eine Antwort auf die Anfrage zu bekommen.

Zum Schluss vergessen sie nicht die Nginx Konfiguration neu zu laden (im Terminal mit nginx -s reload).

White-/Blacklist mit dem geo Modul

Das Nutzen einer Whitelist ist zum Beispiel sinnvoll, wenn sie das oben beschriebene Geo Blocking aktiviert haben, sie jedoch einige IPs z.B. aus den USA freischalten wollen/müssen und nicht alle Zugriffe aus den USA erlauben möchten. Da auch lokale Adressen durch das Geo Blocking gesperrt werden, wird hier ebenfalls erklärt, wie sie diese freischalten.

Um die Whitelist zu aktivieren fügen sie folgenden Code in die Datei nginx.conf ein.

geo $whitelist{
  default 0;
  #add ips or networks here
}

Dabei erstellen sie eine Variable und legen mit geo die Nutzung des geo Modules fest. $whitelist ist der Name der Variable, den sie wie oben beschrieben, auch ändern können. $default 0; legt fest, das standardmäßig der Wert der Variable 0 ist.

Den Kommentar “#add ips or networks here” können sie mit ihren eigenen IP Adressen oder Netzwerken, die freigeschaltet werden sollen ersetzen. Dabei könnte ein Eintrag wie folgt aussehen:

  • 1.2.3.4 1;
  • 192.168.2.0/24 1;

Dabei wäre der erste Eintrag der Liste ein Beispiel für das Freischalten der IP 1.2.3.4 und der zweite für das Freischalten einen kompletten Netzes, in diesem Fall ein lokales Netz, wie oben beschrieben werden durch das Geo Blocking auch lokale Adressen von Nginx abgewiesen, deshalb müssen sie in die Whitelist bei aktivem Geo Blocking mindestens ihr(e) lokale(s/n) Netz(e) eintragen.

Um die Whitelist zu aktivieren, müssen sie ebenfalls vor jedem server Block in ihren Virtualhost Konfigurationen folgende if Bedingung aktivieren. Diese Bedingung MUSS VOR der obigen Geo Blocking Bedingung stehen.

if ($whitelist){
    set $blocked_countrys 0;
}

Beachten sie auch hier, dass sie, falls sie die Namen der Variablen geändert haben diese Änderungen auch hier machen müssen. Diese if Bedingung setzt, wenn $whitelist 1 ist (wenn der Zugriff von einer oben zugelassen IP/einem zugelassenen Netz kommt) nun durch set die angegebene Variable $blocked_countrys auf 0, somit wird die nachfolgende if Bedingung, die das Geo Blocking durchführt (siehe oben) nie ausgeführt und der Zugriff wird nicht abgewiesen.

Vergessen sie auch hier nicht, die Konfiguration in nginx neu zu laden.

User Agent Filter

Das Filtern des User Agents ist zum Beispiel sinnvoll, um Zugriffe von verschiedenen Bots und Website-Copiern abzuweisen. Auch hier wird zunächst eine Map in nginx.conf erstellt, deren Wert auf dem User Agent basiert, den Namen der Map können sie auch hier frei wählen.

map $http_user_agent $blocked_ua {
  default 0;
  #blocked user agents
}

Der Wert der Map liegt standardmäßig bei 0, so dass nichts geblockt wird, der Kommentar #blocked user agents wird nachfolgend durch eine RegEx Instruktion ersetzt, in welcher sie Begriffe eingeben können, nach denen im User Agent gesucht werden soll. Falls sie sehr viele Begriffe einfügen oder die Begriffe z.B. nach Art des User Agents trennen möchten, können sie auch in einer neuen Zeile eine weitere Instruktion hinzufügen.

map $http_user_agent $blocked_ua {
  default 0;
  ~*(googlebot|msnbot|bing) 1;
  ~*(HTTrack|wget|Download) 1;
}

In diesem Beispiel wird in der ersten RegEx Instruktion der Wert der Map auf 1 gesetzt, wenn der User Agent “googlebot”, “msnbot” oder “bing” enthält, in der Zweiten ist der Wert 1, wenn der User Agent “HTTrack”, “wget” oder “Download” enthält. Hier habe ich die verschiedenen Begriffe in “Suchmaschinen Bots” und “Download Programme” getrennt, sie können auch alle Begriffe in eine Instruktion schreiben. Sie müssen nur bei einer neuen Instruktion darauf achten, dass sie den Wert der Map, falls die Instruktion etwas findet, auf 1 setzen.

Eine Liste, die sehr viele Agents blockiert, finden sie hier (in der ersten Antwort auf die Frage), diese können sie übernehmen und beliebig Begriffe hinzufügen/löschen.

Um das Blocking zu aktivieren, müssen sie auch hier eine if Bedingung in allen server Blocks ihrer Virtulhost Konfiguration(en) hinzufügen. Falls sie die obige IP-Whitelist konfiguriert haben, müssen sie auch in dieser if Bedingung eine Änderung vornehmen. Nachfolgend die Änderungen in der Konfiguration.

server_name example.com;
if ($whitelist){
    set $blocked_countrys 0;
    set $blocked_ua 0;
}
if ($blocked_ua){
    return 444;
}

server_name steht auch hier zur Verdeutlichung, wo die neue if Bedingung platziert werden sollte. Falls sie wie oben beschrieben die Whitelist konfiguriert haben müssen sie in dieser if Anweisung noch set $blocked_ua 0; hinzufügen, um, falls der User Agent geblocked werden sollte, den Zugriff trotzdem zuzulassen. Denken sie auch hier daran, die Namen der variablen ggf. anzupassen.

Um den Zugriff abzuweisen wird auch hier der Code 444 genutzt, die genauere Funktionalität wurde bereits im Abschnitt “Geo IP Blocking” bechrieben.

Auch hier nicht vergessen: Konfiguration neu laden!

Bei Fragen oder Fehlern können sie gerne die Kommentarfunktion nutzen.