Let’s Encrypt unter Ubuntu und Nginx einrichten

Vor einigen Tagen habe ich damit begonnen alle von mir betriebenen Webseiten auf TLS umzustellen. Dabei nutzte ich Zertifikate der Zertifizierungsstelle Let’s Encrypt. Let’s Encrypt ging dabei im letzten Jahr in Betrieb und liefert kostenlose Zertifikate für TLS. Die CA wird dabei unter anderem von der EFF und Mozilla unterstützt. Im Gegensatz zu anderen Lösungen ist der Prozess bei Let’s Encrypt hochgradig automatisiert, so das die Einrichtung schnell von statten geht.

Der offizielle Client hört dabei auf den Namen Certbot (früher Let’s Encrypt Client) und implementiert das ACME-Protokoll (Automated Certificate Management Environment) über welches der Prozess abgewickelt wird. Neben dem offiziellen Client gibt es viele weitere Clients welche das ACME-Protokoll implementieren. Um Let’s Encrypt unter Ubuntu zu nutzen, muss im ersten Schritt der Client installiert werden:

apt-get install letsencrypt

Nachdem der Client installiert wurde, kann mit der Erzeugung der Zertifikate begonnen werden. Im Gegensatz zu Apache wird unter Nginx die automatische Einrichtung nicht unterstützt. Aus diesem Grund werden nur die Zertifikate mit dem Client erzeugt. Dies geschieht mit dem Befehl:

letsencrypt certonly

Damit wird der interaktive Modus gestartet in welchem das Zertifikat erzeugt werden kann. Zuerst wird nach einer Mailadresse gefragt, mit welcher das Recovery in Notfällen möglich ist. Anschließend müssen die allgemeinen Geschäftsbedingungen akzeptiert werden. Nun wird nach den Domains gefragt, für welche ein Zertifikat erstellt werden soll. Hier kann man mehrere Domains per Komma bzw. Leerzeichen getrennt angeben – allerdings scheint dies in der aktuellen Version nicht zu funktionieren. Stattdessen wird nur für die erste angegebene Domain ein Zertifikat erzeugt. Standardmäßig benötigt Certbot während der Generierung der Zertifikate Zugriff auf den Port 80. Hintergrund für dieses Verhalten ist das der Client kurz einen Webserver aufsetzt um die Kommunikation mit der CA durchzuführen.

Abgelegt werden die erzeugten Zertifikate dabei im Ordner /etc/letsencrypt/. In diesem Ordner liegen neben den Stammzertifikaten auch die eigentlichen Zertifikate für die einzelnen Domains. Nun kann dieses Zertifikat in Nginx eingebunden werden. Dazu muss die Konfigurationsdatei der jeweiligen Seite (z.B. /etc/nginx/sites-available/example) geöffnet werden. Im ersten Schritt wurde dazu in der Konfiguration eine Weiterleitung eingerichtet:

server {
        listen 80;
        listen [::]:80;

        server_name .example.org;

        return 301 https://$host$request_uri$is_args$args;
}

Diese Weiterleitung sorgt dafür das eine Verbindung über unverschlüsseltes HTTP automatisch auf die verschlüsselte Variante umgeleitet wird. Weiter geht es mit der Konfiguration der verschlüsselten Verbindung:

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

        ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;

        ...

Jedes erzeugte Zertifikat von Let’s Encrypt ist 90 Tage lang gültig, so das ein automatischer Prozess eingerichtet werden sollte um die Zertifikate automatisch zu erneuern. Mit dem Befehl:

letsencrypt renew --agree-tos

kann dabei der Erneuerungsprozess angestoßen werden. Möchte man das ganze ohne Risiko testen, so sollte der Parameter –dry-run angefügt werden.

letsencrypt renew --agree-tos --dry-run

Bei der Erneuerung der Zertifikate kann es nun vorkommen das man den Nginx-Server vorher beenden muss. Das ganze kann man in ein Skript gießen:

#!/bin/sh
service nginx stop
letsencrypt renew --agree-tos
service nginx start

Dieses Skript kann man nun zum Beispiel einmal in der Nacht per Cronjob ausführen. Der Client überprüft dabei ob eine Erneuerung notwendig ist und führt diese dann automatisch durch.

Einführung in die uncomplicated firewall

Wenn man unter Linux eingehende und abgehende Pakete kontrollieren, umleiten oder blockieren möchte, so kann man für diese Aufgabe iptables nutzen. Das Problem an iptables ist das es relativ kompliziert in der Anwendung ist.

Damit man hier nicht im Regen steht, gibt es (neben vieler anderer Firewall-Lösungen für Linux) die uncomplicated firewall kurz ufw. Technisch gesehen handelt es sich bei ufw um ein Frontend für iptables. Seit der Version 8.04 (Hardy Hedon) ist ufw ein Bestandteil der Ubuntu-Distribution. Neben Ubuntu ist ufw unter anderem auch für Debian verfügbar. Installiert werden kann ufw mittels des Befehls:

apt-get install ufw

Standardmäßig ist ufw deaktiviert, so das die Installation im ersten Schritt keinerlei Auswirkungen hat. Den aktuellen Status sowie die definierten Regeln können dabei mittels:

ufw status

eingesehen werden. Das könnte dann z.B. so aussehen:

Status: Aktiv

Zu                   Aktion      Von
--                   ------      ---
8080/tcp             DENY        Anywhere                                
22/tcp               ALLOW       Anywhere                            
22/tcp (v6)          ALLOW       Anywhere (v6)

Ist der Status auf inaktiv gesetzt, so muss ufw erst mit dem Befehl:

ufw enable

aktiviert werden. Hierbei muss man beachten das eine unbedachte Aktivierung von ufw dazu führen kann das man sich aus dem Rechner aussperrt. Dies liegt daran das am Anfang keinerlei Regeln definiert sind – so werden Pakete an Port 22 ignoriert; dies führt dazu das keine Verbindung per SSH möglich ist. Um dem vorzubeugen sollte eine Regel für SSH definiert werden, bevor ufw aktiviert wird:

ufw allow 22/tcp

Bei dieser Schreibweise handelt es sich um die vereinfachte Form zum Anlegen einer Regel. Neben allow, sind dabei auch die Werte deny und reject möglich. Während bei allow die Pakete passieren können, werden sie bei deny blockiert – im Gegensatz dazu wird bei reject der Absender darüber informiert das die Pakete abgelehnt wurden. Möchte man komplexere Regeln definieren nutzt man ufw nach folgendem Schema:

ufw allow proto tcp from any to 127.0.0.1 port 1234

Damit werden alle Verbindungen per TCP von beliebigen IP-Adressen an die spezifizierte IP-Adresse weitergeleitet. Als Port wird als Eingangs- und Zielport Port 1234 genutzt. Die Regeln welche ufw verwaltet werden in drei Dateien gespeichert:

/etc/ufw/before.rules
/var/lib/ufw/user.rules
/etc/ufw/after.rules

Abgearbeitet werden die Regeln in der Reihenfolge wie oben angegeben – somit könnte eine Regel in der user.rules-Datei definiert sein, welche anschließend von einer anderen Regel in der after.rules-Datei überschrieben wird. Die selbst definierten Regeln sind dabei in der user.rules zu finden. Neben dem Anlegen ist es natürlich auch möglich Regeln wieder zu löschen. Für obige SSH-Regel würde das dabei so aussehen:

ufw delete allow 22/tcp

Daneben ist es möglich ufw auf die Standardeinstellungen zu setzen. Dazu dient der Befehl:

ufw reset

Alle Regeln werden dabei auf die Standardeinstellungen zurückgesetzt. Für die bestehenden Regeln wird ein Backup im Verzeichnis /etc/ufw/ angelegt. Möchte man ufw wieder deaktivieren, so nutzt man den Befehl:

ufw disable

Beim beschriebenen reset-Befehl wird ufw ebenfalls deaktiviert. Damit sind die grundlegenden Konfigurationsschritte erklärt – für die weitergehende Konfiguration empfiehlt sich der entsprechende Artikel bei ubuntuusers.

apt-get Sperrdateien entfernen

Unter Umständen kann es unter Ubuntu, oder anderen Distributionen basierend auf Debian passieren, das ein apt-get Vorgang fehlschlägt. Dies kann sich darin äußern das apt-get nicht mehr genutzt werden kann – stattdessen bekommt man folgende Meldung zu sehen:

E: Could not get lock /var/lib/dpkg/lock - open (11 Resource temporarily unavailable)
E: Unable to lock the administration directory (/var/lib/dpkg/) is another process using it?

Hintergrund ist das dpkg Sperrdateien mit dem Name lock anlegt und sie nach getaner Arbeit wieder entfernt. Bei plötzlichen Unterbrechungen wie z.B. einem Stromausfall kann es passieren das die Dateien nicht mehr entfernt werden. Lösen kann man das Problem indem man die entsprechenden Sperrdateien entfernt:

rm /var/lib/dpkg/lock
rm /var/lib/apt/lists/lock
rm /var/cache/apt/archives/lock

Abschließend sollte dpkg bzw. apt-get wieder ohne Probleme funktionieren.

Probleme mit dem Minecraft Server, Ubuntu 16.04 und KVM

Vor einigen Tagen migrierte ich einen Minecraft-Server von einem Server mit Ubuntu 14.04 LTS auf einen Server mit Ubuntu 16.04 LTS. Der Minecraft-Server lief dabei auf dem alten als auch auf dem neuen Server jeweils in einer KVM-Gast-Maschine. Er startete ohne Probleme und wenn man sich das ganze von außen mit nmap anschaute, war der entsprechende Port auch offen gekennzeichnet. Allerdings konnte der Minecraft-Client keinerlei Verbindung mit dem Server aufnehmen. Lösen ließ sich das Problem mit der Änderung einer Einstellung in der server.properties Datei. Konkret ging es dabei um die Einstellung:

use-native-transport = true

welche auf false gesetzt werden musste. Mit diesem Flag wird das optimierte Senden und Empfangen von Paketen unter Linux deaktiviert. Damit funktionierte der Minecraft-Server wieder ohne Probleme.

Screen-Session wieder aufnehmen

Wenn man unter Linux eine Session mittels screen gestartet hat und diese später wieder aufrufen möchte, so nutzt man den Befehl:

screen -r

Unter bestimmten Bedingungen kann es vorkommen, das die Sitzung noch gebunden ist. Auf der Konsole würde das dann wie folgt aussehen:

# screen -r

There is a screen on:
	29711.ubuntu-release-upgrade-screen-window	(05/05/2016 04:09:56 PM)	(Attached)
There is no screen to be resumed matching 29711.ubuntu-release-upgrade-screen-window.

Vorkommen kann so etwas z.B. wenn man die SSH-Verbindung während einer Screen-Sitzung verliert. Damit man diese Screen-Sitzung wieder aufnehmen kann, muss die bestehende Bindung zuerst wieder gelöst werden. Dazu gibt es das Kommando:

screen -d

welches die Bindung löst. Bei mehreren offenen Sitzungen muss zusätzlich die ID der Sitzung angegeben werden. Anschließend kann die Sitzung wieder mittels:

screen -r

aufgenommen werden.