Nginx als Reverse Proxy / Load Balancer

Nginx ist bekanntlich der neue Stern am Webserver Himmel. Meiner Meinung nach ist der Einsatz als Reverse Proxy und Load Balancer. Die Konfiguration kann zwar sehr schnell groß werden, aber die Möglichkeiten sind nahezu unbegrenzt. Ich möchte hier nun aufzeigen wie man einen Proxy (SSL / Cache für Bilder / Load Balancer für 2 Server) aufbaut.

Im ersten Schritt sollte man den Proxy Konfigurieren (das ganze sollte in den http { } Part geschrieben werden) geschrieben werden. Dafür erstellen wir einen allgemeine Server Einstellung und legen den Server-Namen fest sowie den Port:

server {
   #Servername auf dem ngnix hört
   server_name sv-neoproxy;
   #Port
   listen 443;
}

Da der Proxy nur SSL-Verschlüsselte Verbindungen annehmen soll, hört er von Anfang an auf den Port 443. Damit die Verschlüsselung geht müssen die Zertifikate gleich mit geladen werden und das SSL Modul eingeschallten werden:

ssl_certificate datei.pem;
ssl_certificate_key key1.pem;
ssl on;

Damit wäre die Allgemeine Verbindungseinstellungen beendet und wir müssen jetzt dem Nginx Server beibringen was er tun sollen wenn ein User den auf den Server zugreift. Wir möchten an dieser Stelle das er bei jedem Aufruf sofort sein Dienst als Proxy antritt:

location / {
      # Proxy Aktivieren
      proxy_pass  http://servername;
    ....
}

Mit dieser reinen Einstellung bekommt man aber das Problem das es eine reine Weiterleitung ist. Zwar Passiert noch nichts aber wir wollen das Verhalten gleich von Anfang an unterbinden. Das macht man in dem man in den man proxy_redirect auf off schaltet:

# Schaltet die reine Weiterleitung ab
        proxy_redirect off;

Ein großer Vorteil von Nginx ist, das man sagen kann das der Proxy wie der Client auftreten soll. Dazu wird der HTTP Header angepasst der zu den richtigen Webservern geschickt werden soll:

#Verändert den Header so das es für den Angefragten Webserver so scheint als ob der Client da anfrägt
proxy_set_header   Host             $host;
proxy_set_header   X-Real-IP        $remote_addr;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

Das ganze hat den Vorteil, wenn man die Log Dateien auf den Webservern nun anschaut, stehen dort nicht die IP-Adresse des Proxys sondern, die des Users der die Webseite besucht.

Der nächste Part von Einstellungen betreffen die Timeouts sowie die allgemeinen Größen Angaben. Hier sollte jeder seinen Weg suchen und auf seinen eigene Gegebenheiten anpassen:

# Gibt an wie große die Max. Übertragender HTTP Body ist
client_max_body_size       10m;
# Gibt an wie groß max der HTTP-Body im Buffer sein darf
client_body_buffer_size    128k;
# Timeouts
proxy_connect_timeout      90;
proxy_send_timeout         90;
proxy_read_timeout         90;
#Proxy Speichern
proxy_buffer_size          4k;
proxy_buffers              4 32k;
proxy_busy_buffers_size    64k;
proxy_temp_file_write_size 64k;

Im Grunde wäre das schon mit dem Reverse Proxy. Man könnte noch eine Extra Regel für  Bilder, CSS und Java-Script-Dateien erstellen. In meinem Fall würde das so aussehen:

#Änderung das die Bilder zwischengespeichert werden und nicht neu angefragt werden müssen
  location \.(jpg|png|gif|jpeg|css|js|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx)$ {
  #Cache anschalten
  proxy_buffering on;
  #Größe und Max. Lebensdauer
  proxy_cache_valid 200 120m;
  expires 864000;
}

Hier kann man super die Macht die man mit den Variabeln hat, die man in Nginx benutzen kann. Der Server wendet diese Regel also nur an wenn die übertragende Datei ein der angegebene Dateiendungen hat. Eigentlich macht diese Regel nichts, ausser das Buffering einschalten und eine max. Größe und eine Lebensdauer für diese Dateien anzugeben. Der Server sollte nun beim Starten meckern das Ihm ein Cache Pfad fehlt. Dieser Pfad muss im http {} Bereich festgelegt werden. Dort kann man auch gleich die sendfile aktivieren, damit Nginx auch Dateien schreiben bzw. kopieren darf. Hier mal mein Kompletter http {} Bereich (ohne Location):

http {
    include       /etc/nginx/mime.types;
    #Access Log
    access_log  /var/log/nginx/access.log;
    #Cache Pfad
    proxy_cache_path  /tmp/nginx/cache levels=1:2   keys_zone=one:10m;
    sendfile        on;
    tcp_nopush     on;

    keepalive_timeout  65;
    tcp_nodelay        on;
    #Daten werden gepackt
    gzip  on;
    # Ausser für IE bis 7
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";
}

Für eine genaue Erklärung, der Einstellung verweise ich hier einmal auf die Seite: http://wiki.nginx.org/HttpProxyModule
Das Nginx Wiki ist die Perfekte und immer neuste Seite um genau Informationen zu bekommen.

 

Wenn man jetzt den Server in einem Browser aufruft sollte nichts kommen. Weil wir die Weiterleitung zu den richtigen Webserver noch nicht gemacht haben.
Um das zu machen erweitern wir den  http {} Bereich um folgenden Part:

upstream servername  {
   #Aktiviert das die IP Adresse immer an den gleichen Server geschickt werden
   ip_hash;
   #Liste der Webserver
   server   ip-Server1 down;
   server   ip-Server2 70;
   server   ip-Server3 30:
}

Durch die Angabe ip_hash; wird versucht einen Client immer auf den gleichen Webserver zu schicken (bzw. eine IP-Adresse). Das ist spätestens nötigen wenn ein User ein bestimmte Session auf dem Webserver hat (zum Beispiel bei einer Anmeldung oder ähnliches).
Die Liste der Webserver ist im Grunde nur eine Aufzählung der Webserver. Durch die Angabe „down“ hinter der IP-Adresse (eine URL zum Server geht natürlich auch) gibt an das der Server nicht verwendet werden soll. Durch die Angaben von Zahlen versucht Nginx die User anhand dieser Prozentual zu verteilen (in diesem Bespiel Webserver 2 bekommt 70% der User und Webserver 3 30%).

Wir sind fertig. Der Server sollte nun gehen und seine Arbeit verrichten. Bei Probleme oder Fragen, einfach einen Kommentar hinterlassen

Hier noch einmal die Komplette Konfiguration in einem Stück:

http {
    include       /etc/nginx/mime.types;
    #Access Log
    access_log  /var/log/nginx/access.log;
    #Cache Pfad
    proxy_cache_path  /tmp/nginx/cache levels=1:2   keys_zone=one:10m;
    sendfile        on;
    tcp_nopush     on;
    #keepalive_timeout  30;
    keepalive_timeout  65;
    tcp_nodelay        on;
    #Daten werden gepackt
    gzip  on;
    # Ausser für IE bis 7
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";
#LoadBalancer
upstream servername {
   #Aktiviert das die IP Adresse immer an den gleichen Server geschickt werden
   ip_hash;
   #Liste der Webserver
   server   server1 down; #Richtige IP Adresse
   server   server2 ; # IP Adresse des 2. Webserver

}
#Umleitung von http auf https
server {
   listen 80;
   server_name servername;       
   rewrite ^ https://$server_name$request_uri?  permanent;
}

server {
   #Servername auf dem ngnix horcht
   server_name sv-neoproxy;
   #Port
   listen 443; #Muss noch auf SSL umgestellt werden.
   ssl_certificate ssl.pem;
   ssl_certificate_key key1.pem;
   ssl on;
   #Was muss er machen Einstellungen
   location / {
      # Proxy Aktivieren
      proxy_pass  http://servername;
      # Schaltet die reine Weiterleitung ab
        proxy_redirect off;
        #Verändert den Header so das es für den Angefragten Webserver so scheint als ob der Client da anfrägt
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
           #
            client_max_body_size       10m;
           #
           client_body_buffer_size    128k;
         # Timeouts
            proxy_connect_timeout      90;
            proxy_send_timeout         90;
            proxy_read_timeout         90;
        #Proxy Speichern
            proxy_buffer_size          4k;
            proxy_buffers              4 32k;
            proxy_busy_buffers_size    64k;
            proxy_temp_file_write_size 64k;
   }
        #Änderung das die Bilder zwischengespeichert werden und nicht neu angefragt werden müssen
        location \.(jpg|png|gif|jpeg|css|js|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx)$ {
        #Cache anschalten
         proxy_buffering on;
        #Größe und Max. Lebensdauer
         proxy_cache_valid 200 120m;
         expires 864000;
        }
}

 

Johannes

Hauptberuflich bin ich im Bereich Filesecurity unterwegs und schütze die Daten meines Arbeitgebers vor internen und externen Gefahren. Nebenberuflich helfe ich KMUs als IT-Consultent bei der IT-Strategie sowie bei der Entwicklung von Webanwendungen.

2 thoughts to “Nginx als Reverse Proxy / Load Balancer”

  1. Vielen Dank für diesen Artikel. Ein gutes Beispiel wie man NGINX als „Load balanced“-Proxy benutzen kann.
    Eine Frage, wie könnte ich nun mehrere Proxies anstatt mehrerer Webserver benutzen. Denn so muss man doch eher den Webserver unter mehreren Webservern spiegeln.

  2. Gute Beschreibung und funktioniert auch einwandfrei.

    Einziges Manko: Die Klammer von http wird nicht zu gemacht (http sollte eigentilch garnicht in die site-available Configs von nginx)  und die Einrückung ist ein totales Chaos.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.