Linux Server setup

TLS Zertifikate hinterlegen

Bisher können unsere Domain und Subdomain nur über das unverschlüsselte HTTP Protokoll aufgerufen werden. Das ist überhaupt nicht zeitgemäß und schon gar nicht sicher. Suchmaschinen beispielsweise, schlagen äußerst ungern Seiten vor, die keine sichere TLS Verbindung anbieten.

TLS steht für Transport Layer Security und ist der Nachfolger von SSL (Secure Sockets Layer). Obwohl SSL als veraltetes Sicherheitsprotokoll gilt, hält sich die Bezeichnung hartnäckig. Wenn also mit SSL geworben wird, ist eigentlich der neue Standard TLS gemeint.

TLS Zertifikate können kostenlos und kostenpflichtig erstellt, beziehungsweise erworben werden:

  • OpenSSL, freie Software (kostenlos)
  • Let's Encrypt, freie Zertifizierungsstelle (kostenlos)
  • kommerzielle Zertifizierungsstellen (kostenpflichtig)

Eine Zertifizierungsstelle, auch Certification Authority (CA) genannt, unterzieht sich strengen Audits, bei denen insbesondere Sicherheitskonzepte und technische Infrastruktur geprüft wird. Trotz allem, ist es eine freie Entscheidung der Software Hersteller, eine Zertifizierungsstelle als vertrauenswürdig anzuerkennen oder nicht.

Selbsterstellte Zertifikate gelten allgemein als nicht vertrauenswürdig, da ihre Echtheit von einer unabhängigen Organisation nicht bestätigt ist. Es gibt jedoch auch freie Zertifizierungsstellen, wie zum Beispiel Let's Encrypt, die Zertifikate kostenlos ausstellen.

Zertifizierungsstellen geben SSL Zertifikate nur für Domains heraus, nicht für IP Adressen.

Um Zertifikate von freien Zertifizierungsstellen beziehen zu können, gibt es Voraussetzungen, die wir mit unserem Cloud Server und der Domain erfüllen:

  • root Zugriff auf dem Server
  • einen qualifizierten Domainnamen, der über DNS abgefragt werden kann
  • eine Webseite die bereits online und über Port 80 erreichbar ist

In diesem Kapitel werden wir vertrauenswürdige Zertifikate für unsere Domain und Subdomain von Let's Encrypt beziehen. Außerdem erstellen wir ein selbstsigniertes Zertifikat für unsere Server IP. Die Gültigkeitsdauer von Zertifikaten ist zeitlich begrenzt, daher wird ein Automatismus benötigt, der die Zertifikate frühzeitig vor Ablauf erneuert. Das Thema Cronjobs hatten wir bereits bei Logrotate besprochen.

SSL und TLS überprüfen

Zwischenzeitlich lassen wir über den online Dienst SSL Labs unsere Konfiguration und den Status der Verschlüsselung überprüfen. Aktuell ist kein Zertifikat hinterlegt, daher ist das Ergebnis für unsere Domain entsprechend negativ:

SSL Labs
SSL Labs: Assessment failed

Diesen Test werden wir später wiederholen und bekommen dann hoffentlich ein "A", vielleicht sogar ein "A+" Rating.

Die nächsten Schritte:


Certbot installieren

Certbot ist eine freie ACME-Clientsoftware (Automatic Certificate Management Environment), die uns hilft Let's Encrypt Zertifikate abzurufen und zu erneuern. Die Software kann noch mehr, aber das ist der hauptsächliche Zweck für uns.

Certbot installieren:


__$ sudo apt install -y certbot
 

Let's Encrypt Zertifikat für die Domain

Bevor es richtig los geht, möchte ich noch einen Spoiler öffnen: Certbot kann ein gewisses Maß an Kontrolle über Nginx oder Apache gegeben werden. Erfahrungsgemäß ist das eine bequeme Lösung, bis die Komponenten nicht mehr miteinander harmonieren. Wenn vielleicht Certbot geupdatet werden muss, die Server aber wegen der laufenden Webprojekte mit einer Aktualisierung noch warten müssen. Solche Abhängigkeiten versuche ich zu vermeiden, was meistens bedeutet, dass bei der Implementation ein Mehraufwand entsteht. Ich setze Certbot so ein, dass es Zertifikate beantragt und sie automatisch erneuert. Mehr soll es nicht tun. Die Konfiguration der Server Dienste möchte ich selbst kontrollieren.

Grundsätzlich muss für den Zertifikatsantrag die Domain oder Subdomain öffentlich über den Port 80 erreichbar sein. Was wir bereits im letzten Kapitel unter Server Block für eine Domain vorbereitet haben.

Mit folgendem Befehl beantragen wir ein Zertifikat mit Certbot bei Let's Encrypt. Es soll für die Domain und die "Subdomain" www gültig sein:


__$ sudo certbot certonly -d linuxserversetup.com -d www.linuxserversetup.com --rsa-key-size 4096
 

Es gibt noch einen kompakteren Befehl, wo die webroot Methode und das Verzeichnis gleich mitangegeben werden: sudo certbot certonly --webroot -w /var/www/com.linuxserversetup -d linuxserversetup.com -d www.linuxserversetup.com --rsa-key-size 4096

Wir müssen natürlich die Inhaberschaft über die Domain nachweisen. Das erledigen wir mit der "webroot" Methode. Den webroot haben wir für die Domain schon angelegt: /var/www/com.linuxserversetup. Meine Eingaben zum obigen Befehl lauten:

  • Place files in webroot directory (webroot): 2
  • Enter email address: an diese Adresse gehen Bestätigungen, Fehlerberichte und Ankündigungen seitens Let's Encrypt
  • Please read the Terms of Service: a
  • Newsletter: n
  • Input the webroot for linuxserversetup.com: /var/www/com.linuxserversetup
  • Select the webroot for www.linuxserversetup.com: 2

Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): tom@linuxservrsetup.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for linuxserversetup.com
http-01 challenge for www.linuxserversetup.com
Input the webroot for linuxserversetup.com: (Enter 'c' to cancel): /var/www/com.linuxserversetup

Select the webroot for www.linuxserversetup.com:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Enter a new webroot
2: /var/www/com.linuxserversetup
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/linuxserversetup.com/privkey.pem
   Your cert will expire on 2022-02-23. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

In der Antwort steht der Ort, wo die Zertifikate abgelegt wurden. Genauer gesagt, liegen dort Verknüpfungen zu den tatsächlichen Dateien:


__$ sudo ls -la /etc/letsencrypt/live/linuxserversetup.com/
	

Ausgabe:


drwxr-xr-x 2 root root 4096 Jan  4 12:02 .
drwx------ 3 root root 4096 Jan  4 12:02 ..
lrwxrwxrwx 1 root root   44 Jan  4 12:02 cert.pem -> ../../archive/linuxserversetup.com/cert1.pem
lrwxrwxrwx 1 root root   45 Jan  4 12:02 chain.pem -> ../../archive/linuxserversetup.com/chain1.pem
lrwxrwxrwx 1 root root   49 Jan  4 12:02 fullchain.pem -> ../../archive/linuxserversetup.com/fullchain1.pem
lrwxrwxrwx 1 root root   47 Jan  4 12:02 privkey.pem -> ../../archive/linuxserversetup.com/privkey1.pem
-rw-r--r-- 1 root root  692 Jan  4 12:02 README

Die Zertifikate sind drei Monate gültig und werden automatisch innerhalb des letzten Monats erneuert. Der Cronjob dazu wurde hier angelegt:


__$ sudo nano /etc/cron.d/certbot
 

Ausgabe:

/etc/cron.d/certbot


# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc.  Renewal will only occur if expiration
# is within 30 days.
#
# Important Note!  This cronjob will NOT be executed if you are
# running systemd as your init system.  If you are running systemd,
# the cronjob.timer function takes precedence over this cronjob.  For
# more details, see the systemd.timer manpage, or use systemctl show
# certbot.timer.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew

Auf unserem Ubuntu Linux ist es eher unwahrscheinlich, dass dieser Crontab berücksichtigt wird, da hier für gewöhnlich ein systemd timer die zeitliche Prozesssteuerung kontrolliert. Daher hat Certbot einen /lib/systemd/system/certbot.timer angelegt, der alle 12 Stunden die Ausführung von /lib/systemd/system/certbot.service auslöst.

Um nun herauszufinden, ob systemd die Kontrolle auf dem System hat, reicht es die Existenz von /run/systemd/system/ zu überprüfen:


__$ ls /run/systemd/system/
	

Über die Ausgabe durch systemctl list-timers, sollte der Certbot Timer aufgeführt sein:


__$ systemctl list-timers
	

Ausgabe:


NEXT                        LEFT          LAST                        PASSED       UNIT                         ACTIVATES
...
Wed 2022-01-05 16:40:04 UTC 29min left    Wed 2022-01-05 02:55:54 UTC 13h ago      certbot.timer                certbot.service
...

Schauen wir auch in die certbot.timer Datei:


__$ cat /lib/systemd/system/certbot.timer
 

Ausgabe:

/lib/systemd/system/certbot.timer


[Unit]
Description=Run certbot twice daily

[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true

[Install]
WantedBy=timers.target

Und der zugehörige Dienst certbot.service:


__$ cat /lib/systemd/system/certbot.service
 

Ausgabe:

/lib/systemd/system/certbot.service


[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://letsencrypt.readthedocs.io/en/latest/
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew
PrivateTmp=true

Dort sehen wir, dass der Befehl /usr/bin/certbot -q renew die Zertifikate erneuert.

Nachdem ein Zertifikat erneuert wurde, muss Nginx neugeladen werden. Für diese Aufgabe eignet sich der Certbot Parameter --deploy-hook. Eine schlechte Lösung wäre, das über den certbot.service zu erledigen. Die vollständige Datei mit der geänderten ExecStart Zeile würde dann so aussehen:

/lib/systemd/system/certbot.service


[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://letsencrypt.readthedocs.io/en/latest/
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew --deploy-hook "service nginx reload"
PrivateTmp=true

Mit dem nächsten Update ist diese Änderung wieder weg.

Ein besserer Ort ist die erzeugte Datei /etc/letsencrypt/renewal/linuxserversetup.com.conf im Abschnitt [renewalparams].


__$ cat /etc/letsencrypt/renewal/linuxserversetup.com.conf
 

Ausgabe:


# renew_before_expiry = 30 days
version = 0.40.0
archive_dir = /etc/letsencrypt/archive/linuxserversetup.com
cert = /etc/letsencrypt/live/linuxserversetup.com/cert.pem
privkey = /etc/letsencrypt/live/linuxserversetup.com/privkey.pem
chain = /etc/letsencrypt/live/linuxserversetup.com/chain.pem
fullchain = /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = adg4c513fhe12318sfvb76fd387
rsa_key_size = 4096
authenticator = webroot
server = https://acme-v02.api.letsencrypt.org/directory
[[webroot_map]]
linuxserversetup.com = /var/www/com.linuxserversetup
www.linuxserversetup.com = /var/www/com.linuxserversetup

Hier ergänzen wir renew_hook = service nginx reload. Die Datei können wir wie gehabt mit dem Editor nano bearbeiten oder mit diesem Einzeiler. Mit sed suchen wir die Zeile [renewalparams] und ergänzen darunter den renew_hook Teil:


__$ sudo sed -i '/\[renewalparams]/arenew_hook = service nginx reload' /etc/letsencrypt/renewal/linuxserversetup.com.conf
 

Die vollständige Datei sieht dann so aus:


__$ cat /etc/letsencrypt/renewal/linuxserversetup.com.conf
 

/etc/letsencrypt/renewal/linuxserversetup.com.conf


# renew_before_expiry = 30 days
version = 0.40.0
archive_dir = /etc/letsencrypt/archive/linuxserversetup.com
cert = /etc/letsencrypt/live/linuxserversetup.com/cert.pem
privkey = /etc/letsencrypt/live/linuxserversetup.com/privkey.pem
chain = /etc/letsencrypt/live/linuxserversetup.com/chain.pem
fullchain = /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = adg4c513fhe12318sfvb76fd387
rsa_key_size = 4096
authenticator = webroot
server = https://acme-v02.api.letsencrypt.org/directory
renew_hook = service nginx reload
[[webroot_map]]
linuxserversetup.com = /var/www/com.linuxserversetup
www.linuxserversetup.com = /var/www/com.linuxserversetup

Die .well-known Freigabe

Für die Autorisierung durch Let's Encrypt muss Zugriff auf eine bestimmte Adresse (http://www.linuxserversetup.com/.well-known/acme-challenge/) gegeben sein. Serverseitig wird in das webroot Verzeichnis, welches zuvor bei der Beantragung angegeben wurde, vom letsencrypt Dienst genutzt, um eine temporäre Datei unter /var/www/com.linuxserversetup.com/.well-known/acme-challenge zu erstellen. Nachdem das Zertifikat erneuert wurde, wird diese Datei auch wieder entfernt. Den .well-known/acme-challenge Pfad müssen wir selbst erstellen, wo wir gleich zu kommen. Ein Hinweis an dieser Stelle: der .well-known Ordner ist dafür berüchtigt, dass Hacker nach einem erfolgreichem Einbruch dort ihre Malware platzieren. Sie ist dort gut versteckt und kann durch die genannte Freigabe aus dem Internet abgerufen werden. Es schadet also nicht, zwischendurch mal dort reinzuschauen oder einen Automatismus zu erzeugen, der diese Ordner in gewissen Zeitabständen leert.

Zertifikate in der NGINX Konfiguration übernehmen

Die zuständige Konfigurationsdatei (/etc/nginx/sites-available/com.linuxserversetup.conf) müssen wir für HTTPS entsprechend umändern:


__$ sudo nano /etc/nginx/sites-available/com.linuxserversetup.conf
 

Die Datei sollte folgenden Inhalt haben:

/etc/nginx/sites-available/com.linuxserversetup.conf


# force https
server {
  listen      80;
  server_name www.linuxserversetup.com linuxserversetup.com;

  location ~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/com.linuxserversetup/;
    try_files $uri =404;
    break;
  }

  location / {
    return    301 https://$server_name$request_uri;
  }
}

# redirect to www
server {
  listen      443;
  server_name linuxserversetup.com;
  return      301 $scheme://www.$server_name$request_uri;
}

# main block
server {
  listen      443 ssl http2 default_server;
  listen      [::]:443 ssl http2;
  server_name www.linuxserversetup.com;

  root        /var/www/com.linuxserversetup;
  index       index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/linuxserversetup.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/linuxserversetup.com/chain.pem;
}

Ordnerpfad für die automatische Erneuerung der Let's Encrypt Zertifikate anlegen:


__$ mkdir -p /var/www/com.linuxserversetup/.well-known/acme-challenge
 

Nach dem speichern überprüfen wir die neue Konfiguration und starten NGINX neu:


__$ sudo nginx -t
__$ sudo systemctl reload nginx
 

Certbots automatische Erneuerung überprüfen

Bevor es weiter geht, können wir noch überprüfen, ob Certbot überhaupt in der Lage ist, Zertifikate zu erneuern. Dazu gibt es den Parameter --dry-run. Dieser simuliert den Prozess und erstellt anschließend ein Bericht.


__$ sudo certbot renew --dry-run
 

Mit SSL Labs überprüfen

Wiederholen wir den Test jetzt mit SSL Labs, sollte unsere Konfiguration mit "A" eingestuft sein:

SSL Labs: A-Rating

Das "Rating" kann noch verbessert werden, indem wir einen Diffie-Hellman Schlüssel hinzufügen. Wir erstellen einen mit OpenSSL, der Ablageort soll /etc/ssl/certs/ sein:


__$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
 

Achtung Spoiler: Die Berechnung wird auf unserem CPX11 mindestens 10 Minuten dauern:


Generating DH parameters, 4096 bit long safe prime, generator 2
This is going to take a long time
...............................................+..................................
..................................................................................
...................................................................+..............
..................................................................................
..................................................................................
 

Indem wir HSTS aktivieren, ist sogar ein "A+" Rating möglich. Durch HSTS wird der HTTP Header Strict-Transport-Security übertragen, was dem Browser mitteilt, dass diese Adresse nur über HTTPS aufgerufen werden soll. Der mitgelieferte Wert, ist der Zeitraum in Sekunden, für die der Browser sich das merken soll. Für gewöhnlich ein Jahr (31536000 Sekunden).

Den Pfad zum PEM Zertifikat und den HSTS Header geben wir wie zuvor in die NGINX Site-Konfiguration ein:


__$ sudo nano /etc/nginx/sites-available/com.linuxserversetup.conf
 

Die finale Datei sieht dann so aus:

/etc/nginx/sites-available/com.linuxserversetup.conf


# force https
server {
  listen      80;
  server_name www.linuxserversetup.com linuxserversetup.com;

  location ~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/com.linuxserversetup/;
    try_files $uri =404;
    break;
  }

  location / {
    return    301 https://$server_name$request_uri;
  }
}

# redirect to www
server {
  listen      443;
  server_name linuxserversetup.com;
  return      301 $scheme://www.$server_name$request_uri;
}

# main block
server {
  listen      443 ssl http2 default_server;
  listen      [::]:443 ssl http2;
  server_name www.linuxserversetup.com;

  root        /var/www/com.linuxserversetup/;
  index       index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/linuxserversetup.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/linuxserversetup.com/chain.pem;

	# dhparam
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  # HSTS
  add_header Strict-Transport-Security "max-age=31536000";
}

Zuletzt geben wir für eine Verbindung auch die erlaubten Verschlüsselungsverfahren (Cipher) mit ssl_ciphers vor, die ein Browser unterstützen muss. Hier gilt ein gutes Maß zwischen Sicherheit und aussreichend Browserkompatibilität zu finden:


ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
 

Diese Vorgabe können wir in globalen Einstellungen von NGINX schreiben:


__$ sudo nano /etc/nginx/nginx.conf
 

Die vollständige Datei sieht dann so aus:

/etc/nginx/nginx.conf


user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
  worker_connections 768;
  # multi_accept on;
}

http {

  ##
  # Basic Settings
  ##

  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  server_tokens off;

  # server_names_hash_bucket_size 64;
  # server_name_in_redirect off;

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

  ##
  # SSL Settings
  ##

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
  ssl_prefer_server_ciphers on;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

  ##
  # Logging Settings
  ##

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  ##
  # Gzip Settings
  ##

  gzip on;

  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  ##
  # Virtual Host Configs
  ##

  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

#mail {
  #  # See sample authentication script at:
  #  # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
  #
  #  # auth_http localhost/auth.php;
  #  # pop3_capabilities "TOP" "USER";
  #  # imap_capabilities "IMAP4rev1" "UIDPLUS";
  #
  #  server {
  #     listen     localhost:110;
  #     protocol   pop3;
  #     proxy      on;
  #  }
  #
  #  server {
  #     listen     localhost:143;
  #     protocol   imap;
  #     proxy      on;
  #  }
  #}

Und wie gehabt: NGINX prüfen und neu starten:


__$ sudo nginx -t
__$ sudo systemctl reload nginx
 

Das Rating von SSL Labs sollte jetzt "A+" sein:

SSL Labs: A+ Rating

Die Seite ssl-config.mozilla.org kann helfen, um weitere Einstellungen vorzunehmen. Es ist aber zu beachten, dass noch eine gewisse Abwärtskompatibilität vorhanden sein sollte. Denn eine zu strenge TLS Konfiguration wird ältere Geräte ausschließen.


Selbstsigniertes TLS Zertifikat für den Default Server Block

Let's Encrypt stellt TLS Zertifikate nur für qualifizierte Domainnamen aus. Daher müssen wir für unsere IP ein selbstsigniertes Zertifikat hinterlegen. Für gewöhnlich ist es gar nicht erwünscht, dass jemand die Server IP direkt im Browser abruft. Da es aber möglich ist, sollte dieser Austausch auch verschlüsselt sein. An der Stelle ist es auch nicht wichtig, ob das Zertifikat vertrauenswürdig ist. Es tut was es soll, nämlich verschlüsseln. Und wem das zu unsicher ist, soll die IP nicht zu besuchen.

Mit dem folgenden OpenSSL Befehl erstellen wir ein Zertifikat und einen Schlüssel mit dem RSA Verschlüsselungsverfahren. Die Komplexität soll 2048 Bit betragen mit einer Gültigkeitsdauer von 365 Tagen:


__$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
 

Während der Prozedur bestätige ich Country Name mit DE und Common Name mit der Server IP 116.203.69.89. Zu dem Rest kannst Du Angaben machen oder einfach durch Entern.


gned.key -out /etc/ssl/certs/nginx-selfsigned.crt
Generating a RSA private key
.................................................+++++
......+++++
writing new private key to '/etc/ssl/private/nginx-selfsigned.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:116.203.68.89
Email Address []:

Die erzeugten Dateien sind:

  • /etc/ssl/private/nginx-selfsigned.key
  • /etc/ssl/certs/nginx-selfsigned.crt

__$ sudo ls -la /etc/ssl/private/
__$ sudo ls -la /etc/ssl/certs/
	

Die müssen wir jetzt nur noch in der obigen default Konfiguration hinterlegen.

Öffnen wir die Datei zum Bearbeiten:


__$ sudo nano /etc/nginx/sites-available/default
 

Wir werden einen weiteren Server Block am Anfang der Datei hinzufügen. Dieser leitet von HTTP auf HTTPS um und erzwingt damit eine verschlüsselte Übertagung. Der Zweite ursprüngliche Block wird um die beiden Pfade ergänzt, die zu dem selbstsignierten Schlüssel (ssl_certificate) und dem Zertifikat (ssl_certificate_key) führen.

Wenn wir schon dabei sind, können wir auch den oben erzeugten Diffie-Hellman Schlüssel mit angeben.

Die vollständige Datei sollte folgenden Inhalt haben:

/etc/nginx/sites-available/default


# force https
server {
  listen 80;
  server_name _;
  return 301 https://116.203.68.89;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name _;

  root /var/www/default;
  index index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
  ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
}
 

Überprüfen wir die neue Konfiguration und starten NGINX neu:


__$ sudo nginx -t
__$ sudo systemctl reload nginx
 

Der Aufruf von http://116.203.69.89 leitet jetzt nach https://116.203.69.89 um. Es ist also gar nicht mehr möglich Daten unverschlüsselt zu übertragen.


Let's Encrypt Zertifikat für die Subdomain

Im Grunde wiederholt sich der erste Abschnitt, wo wir ein Zertifikat für die Domain eingerichtet haben. Daher die Schritte jetzt für die Domain im Schnelldurchgang.

Die Subdomain muss über Port 80 erreichbar sein, was wir bereits im letzten Kapitel unter Server Block für eine Subdomain vorbereitet haben.

Ein Zertifikat von Let's Encrypt beantragen:


__$ sudo certbot certonly -d dev.linuxserversetup.com --rsa-key-size 4096
	
  • Place files in webroot directory (webroot): 2
  • Enter email address
  • Please read the Terms of Service: a
  • Newsletter: n
  • Input the webroot for dev.linuxserversetup.com: /var/www/com.linuxserversetup.dev

Die Konfigurationsdatei für HTTPS umändern:


__$ sudo nano /etc/nginx/sites-available/com.linuxserversetup.dev.conf
	

Die Datei sollte folgenden Inhalt haben:

/etc/nginx/sites-available/com.linuxserversetup.dev.conf


# force https
server {
  listen      80;
  server_name dev.linuxserversetup.com;

  location ~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/com.linuxserversetup.dev/;
    try_files $uri =404;
    break;
  }

  location / {
    return    301 https://$server_name$request_uri;
  }
}

# main block
server {
  listen      443 ssl http2;
  listen      [::]:443 ssl http2;
  server_name dev.linuxserversetup.com;

  root        /var/www/com.linuxserversetup.dev/;
  index       index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/letsencrypt/live/dev.linuxserversetup.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/dev.linuxserversetup.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/dev.linuxserversetup.com/chain.pem;

  # dhparam
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  # HSTS
  add_header Strict-Transport-Security "max-age=31536000";
}

Den Pfad /var/www/com.linuxserversetup.dev/.well-known/acme-challenge für Let's Encrypt erstellen:


__$ mkdir -p /var/www/com.linuxserversetup.dev/.well-known/acme-challenge
	

NGINX neu starten:


__$ sudo systemctl reload nginx
 

Domäne aus Certbot löschen

Der Vollständigkeit halber wird hier beschrieben, wie eine Domain aus dem Certbot-Prozess ausgeschlossen und die entsprechenden Certbot-Dateien entfernen werden.

Führen den Befehl certbot delete aus und wähle die zu löschende Domain:


__$ sudo certbot delete
	

Certbot zeigt eine nummerierte Liste an und erwartet die Eingabe einer Zahl:


Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which certificate(s) would you like to delete?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: linuxserversetup.com
2: dev.linuxserversetup.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 

Nach der Eingabe der entsprechenden Nummer wird eine Meldung angezeigt, dass die Domain von Certbot gelöscht wurde:


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Deleted all files relating to certificate dev.linuxserversetup.com.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -