Nginx Reverse Proxy mit Let's Encrypt

In dieser Anleitung wird beschrieben, wie ein bestehender Elasticsearch Server mithilfe eines Nginx Reverse Proxies über eine native HTTPS Verbindung auf Port 443 mit einem Let's Encrypt Zertifikat abgesichert werden kann.

Voraussetzungen

  • Aktiver Elasticsearch Server
  • Kein installierter Dienst auf Port 80 oder 443
  • SSH Root Zugriff auf den Elasticsearch Server

Vorbereitung

Melden Sie sich zunächst via SSH auf dem Elasticsearch Server an, um die weiteren Konfigurationsschritte durchzuführen. Sollten Sie während der Bestellung des Servers keinen öffentlichen SSH-Schlüssel für den Server hinterlegt haben, können Sie die Zugangsdaten über das Kundencenter über den Menüpunkt Server → Virtuelle Server → Zugangsdaten abrufen.



In dieser Anleitung wird der Reverse Proxy für den Elasticsearch Server sXXXXX.creolineserver.com eingerichtet. Bitte passen Sie den Hostnamen in allen folgenden Konfigurationsdateien entsprechend an.



Melden Sie sich über SSH mit dem root Benutzer am Server an:

ssh root@sXXXXX.creolineserver.com


Nginx Installation

Durch den Einsatz von Nginx kann neben der HTTPS Verbindung auf Port 443 gleichzeitig ein Let's Encrypt Zertifikat konfiguriert werden, welches automatisch vor Ablauf verlängert wird.


apt update && apt install curl gnupg2 ca-certificates lsb-release

# Installation des offiziellen Nginx Repositories
wget -qO - http://nginx.org/packages/keys/nginx_signing.key | apt-key add -
echo "deb http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list

# Installation des nginx Webservers
apt update && apt install nginx



Nach der Installation können Sie mithilfe von systemctl prüfen, ob der Nginx Server erfolgreich installiert und gestartet wurde.

systemctl status nginx

● nginx.service - nginx - high performance web server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2021-09-22 16:01:18 CEST; 6s ago



Nginx Konfiguration

Deaktivieren Sie die Standard-Vhost-Konfiguration mit folgendem Befehl:

mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled


Fügen Sie anschließend eine neue Konfigurationsdatei mit folgendem Befehl hinzu:

nano /etc/nginx/conf.d/elasticsearch-proxy.conf



server {
    listen 80;
    server_name localhost sXXXXX.creolineserver.com;

    location / {
        proxy_pass http://127.0.0.1:9200;
        proxy_read_timeout 60;
        proxy_connect_timeout 60;
        proxy_buffering off;
        client_max_body_size 100M;

        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }
}


Sollten Sie den Elasticsearch HTTP API Port geändert haben, muss dieser in der NGINX Konfiguration entsprechend angepasst werden.


Prüfen Sie anschließend die Konfiguration auf Syntaxfehler und laden Sie die Nginx Konfiguration neu, damit Ihre Änderungen wirksam werden.

nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

systemctl reload nginx



Let's Encrypt Installation

Installieren Sie das Certbot-Paket, um Let's Encrypt Zertifikate ausstellen zu können:


apt update && apt install certbot python3-certbot-nginx



Let's Encrypt Konfiguration

Nach der erfolgreichen Installation des Certbot-Paketes können Sie das notwendige SSL-Zertifikat mithilfe des certbot Befehls ausstellen.


Sofern Sie den certbot Befehl zum ersten Mal nutzen, müssen Sie noch eine E-Mail-Adresse für Ablaufbenachrichtigungen oder wichtige Sicherheitshinweise eintragen.


certbot --nginx -d sXXXXX.creolineserver.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): info@creoline.de

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for sXXXXX.creolineserver.com
Using default address 80 for authentication.
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://sXXXXX.creolineserver.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=sXXXXX.creolineserver.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Stimmen Sie der HTTPS Umleitung zu, wenn Sie eingehenden Traffic auf Port 80 (HTTP) automatisch zu Port 443 (HTTPS) umleiten möchten.



Automatische Verlängerung von SSL-Zertifikaten

Für die automatische Verlängerung wird über das certbot Paket bereits der certbot.service sowie der certbot.timer mitgeliefert, sodass ein manueller Cronjob nicht mehr benötigt wird.


Sofern die beiden systemd-Services von certbot nicht genutzt werden sollen, kann das certbot-Paket auch via cronjob zweimal täglich über crontab -e angestoßen werden:


52 0,12 * * * certbot renew --post-hook "nginx -t && systemctl reload nginx" 


Der Cronjob ist nur notwendig, wenn die systemd-Services certbot.service und certbot.timer deaktiviert wurden.



Firewall Konfiguration

Anschließend kann der direkte Elasticsearch Zugriff über die Cloud-Firewall blockiert werden, damit alle zukünftigen HTTP-Anfragen ausschließlich über den Nginx Proxy gesendet werden müssen.

Erstellen Sie hierzu eine neue Firewall-Regel, die die eingehende TCP Kommunikation auf Port 80 und 443 erlaubt und blockieren Sie mithilfe einer weiteren Regel den restlichen eingehenden Traffic.



Bitte beachten Sie, dass weitere Regeln für den Zugriff auf Kibana erforderlich sind. Sofern Ihr Applikations-Server über eine statische IP-Adresse verfügt, empfiehlt es sich die HTTP und HTTPS Kommunikation ausschließlich von der Quell-Adresse des Applikations-Servers freizugeben.



HTTP(S)-Anfragen testen

Mithilfe von curl kann geprüft werden, ob die Konfiguration erfolgreich war und der Nginx Proxy wie gewünscht funktioniert.


curl https://sXXXXX.creolineserver.com
{
  "name" : "sXXXXX.creolineserver.com",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "Mi_bhUolSw2UTHTnVNoKZA",
  "version" : {
    "number" : "7.14.2",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "6bc13727ce758c0e943c3c21653b3da82f627f75",
    "build_date" : "2021-09-15T10:18:09.722761972Z",
    "build_snapshot" : false,
    "lucene_version" : "8.9.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}



Sofern Sie bei der Let's Encrypt Konfiguration die HTTPS Weiterleitung aktiviert haben, können Sie die Weiterleitung zusätzlich testen:


curl -I http://sXXXXX.creolineserver.com

HTTP/1.1 301 Moved Permanently
Server: nginx/1.21.3
Date: Wed, 22 Sep 2021 15:12:31 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://sXXXXX.creolineserver.com


Der HTTP-Status-Code 301 sowie der Location Header der Response zeigt an, dass die HTTPS-Weiterleitung einwandfrei funktioniert.


Der Elasticsearch Server kann nun über https:// ohne Angabe eines Ports von Ihrer Applikation angesprochen werden.



Nginx Version in HTTP-Antworten deaktivieren

In der Standard-Konfiguration von Nginx wird in jeder HTTP-Antwort die eingesetzte Nginx Version in dem Server Header zurückgeliefert. Dieses Verhalten kann über die nginx.conf deaktiviert werden.


Editieren Sie hierzu die Datei /etc/nginx/nginx.conf und ergänzen Sie den Parameter server_tokens off; im http Block.


user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile on;
    keepalive_timeout 65;
    server_tokens off;

    include /etc/nginx/conf.d/*.conf;
}


Damit die Änderungen wirksam werden, muss die Nginx Server Konfiguration neu geladen werden:


nginx -t && systemctl reload nginx


Die eingesetzte Nginx Version wird anschließend in den HTTP-Antworten verborgen:


curl -I https://sXXXXX.creolineserver.com

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 23 Sep 2021 06:11:34 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 554
Connection: keep-alive
X-elastic-product: Elasticsearch