Elasticsearch mit nginx absichern

Der Such-Server Elasticsearch ist eine spannende Sache, allerdings aufgrund der Philosophie, die die Entwickler verfolgen, recht spartanisch ausgestattet und so bringt der Dienst keine Authentifizierung oder Verschlüsselung mit. Sollen Such-Dienst und Projekt-Dateien auf getrennten Maschinen laufen, wird das zu einem Problem.

Bei meiner Recherche stieß ich sehr schnell auf das Plugin Jetty, welches eine Authentifizierung über HTTP nachrüstet. Jedoch habe ich damit keine besonders guten Erfahrungen gemacht, wenn es darum geht die Verbindung zusätzlich noch zu verschlüsseln. In der Zwischenzeit wirkt das Projekt auch etwas verwaist.

Aus diesem Grund habe ich mich dazu entschieden, nginx als Reverse Proxy vor den Such-Server zu schnallen. Nginx ist ein schneller und funktionsreicher Webserver, bzw. Reverse Proxy und so ist es ein Leichtes, diese Aufgabe zu erledigen.

Zunächst installieren wir nginx auf dem Debian-Server, auf dem bereits der Elasticsearch-Dienst seine Arbeit verrichtet.

apt-get install nginx

Anschließend sollte der HTTP-Server bereits über den Browser und die Host-Adresse erreichbar sein. Eine Testseite des nginx erscheint. Wir schmeißen nun die Standard-Konfiguration raus. Wer bereits mit dem Apache unter Debian gearbeitet hat, dem sollte die Ordner-Struktur für Virtual Hosts, bzw. Server Blocks, wie sie bei nginx heißen, bekannt vorkommen. Diese liegen nämlich in einzelnen Dateien in /etc/nginx/sites-available/ und werden zur Aktivierung lediglich in den Nachbarordner /etc/nginx/sites-enabled/ gelinkt. Die Helfer a2ensite und a2dissite, des guten alten Apachen, liefert uns der nginx nicht mit. Doch nun wieder an die Arbeit. Wir deaktivieren also die Standard-Konfiguration.

rm /etc/nginx/sites-enabled/default

Anschließend legen wir unsere eigene Konfiguration eines Server Blocks in der Datei /etc/nginx/sites-available/elasticsearch an.

server {
   listen 8080 ssl;
   server_name example.com;

   ssl on;
   ssl_certificate /etc/ssl/certs/example_com.crt;
   ssl_certificate_key /etc/ssl/private/example_com.key;

   auth_basic "Elasticsearch Authentication";
   auth_basic_user_file /etc/nginx/elasticsearch.pwd;

    location / {
        rewrite ^/(.*) /$1 break;
        proxy_ignore_client_abort on;
        proxy_pass http://localhost:9200;
        proxy_redirect http://localhost:9200 http://example.com:8080/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
    }
}

Mittels dieser Konfiguration lauscht nginx auf Port 8080 und reagiert auf die Domain example.com. Des Weiteren richten wir noch ein SSL-/TLS-Zertifikat ein, was für unsere Verschlüsselung sorgt.

Der Webserver bietet in diesem Bereich zahlreiche weitere Einstellungen an. Uns sollen in diesem Artikel die drei Zeilen beginnend mit „ssl*“ als einfache Verschlüsselung genügen. Wichtig ist dabei zu bedenken, dass der spätere Applikationsserver diesem Zertifikat traut. Stellt also sicher, dass entsprechende Root-Zertifikate auf dem Applikationsserver hinterlegt sind.

Zuletzt werden die gestellten Anfragen der Domain an den Elasticsearch-Server weitergeleitet und dabei HTTP-Header korrekt gesetzt.

Für die Authentifizierung braucht es noch die oben erwähnte Passwort-Datei, die ich mit dem guten alten passwd des Apache erzeuge. Dafür in Debian einfach die Utilities und nicht den kompletten Apachen installieren.

apt-get install apache2-utils

Nun die Password-Datei erstellen.

htpasswd -c /etc/nginx/elasticsearch.pwd username

Beim nginx existiert für ein Zwischenzertifikat keine eigene Direktive, wie beim Apache. Das bedeutet, dass in einer Zertifikatsdatei alle notwendigen Zertifikate eingetragen sein müssen.

cd /etc/ssl/certs
cat cert1.crt cert2.pem >> example_com.crt

Anschließend muss der Server Block nur noch mit dem bereits erwähnten Symlink aktiviert und der Dienst neugestartet werden.

ln -s /etc/nginx/sites-available/elasticsearch /etc/nginx/sites-enabled/elasticsearch
service nginx restart

Fertig? Noch nicht! Es gäbe nun nämlich noch die Möglichkeit am nginx vorbei den Such-Server aufzurufen, indem man in der URL den Port von Elasticsearch anfügt: http://example.com:9200.

Dazu setzen wir einfach die folgende Einstellung in der Datei /etc/elasticsearch/elasticsearch.yml und starten den Dienst neu.

network.host: "127.0.0.1"
service elasticsearch restart

Diese Anleitung ist natürlich erst der Anfang eines robusten Sicherheitskonzepts. Denkbar wäre es nun mit fail2ban den Schutz vor Brute-Force-Angriffen zu erhöhen oder den Zugriff mittels iptables, auf den nginx, nur aus einem speziellen Netzsegment zu erlauben.

Patrick Baber

Als erfahrener Programmierer löst Patrick jeden Gordischen Knoten, findet die geeignete Methode und entwickelt damit flexible Software-Systeme.