In der Standardkonfiguration werden die Administrationsoberfläche Foris und LuCI des Turris Omnia unverschlüsselt per HTTP angeboten. Für einen sicheren Zugriff bei der Administration sollte HTTPS aktiviert werden, damit Foris und LuCI per SSL/TLS abgerufen werden.

1| SSL/TLS aktivieren

Unverschlüsselte Verbindung zum Turris Omnia

Anmerkung: Im Folgenden wird davon ausgegangen, dass für die SSL/TLS-Verbindung keine selbstsignierten Zertifikate, sondern Zertifikate einer privaten CA verwendet werden (siehe auch Artikel ‘Private CA erstellen’).

Zunächst muss SSL/TLS in der lighttpd-Konfiguration aktiviert werden. Dies passiert am besten in der Datei /etc/lighttpd/conf.d/ssl-enable.conf:

# This settings enables https with CA signed certificate
$SERVER["socket"] == ":443" {
 ssl.engine = "enable"
 ssl.pemfile = "/etc/lighttpd/server.pem"
 ssl.ca-file = "/etc/lighttpd/ca.pem"
 ssl.use-sslv2 = "disable"
 ssl.use-sslv3 = "disable"
 ssl.cipher-list = "EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA"
 ssl.honor-cipher-order = "enable"
 setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=15768000") # six months
 # use this only if all subdomains support HTTPS!
 # setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=15768000; includeSubDomains")
}

$SERVER["socket"] == "[::]:443" {
 ssl.engine = "enable"
 ssl.pemfile = "/etc/lighttpd/server.pem"
 ssl.ca-file = "/etc/lighttpd/ca.pem"
 ssl.use-sslv2 = "disable"
 ssl.use-sslv3 = "disable"
 ssl.cipher-list = "EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA"
 ssl.honor-cipher-order = "enable"
 setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=15768000") # six months
 # use this only if all subdomains support HTTPS!
 # setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=15768000; includeSubDomains")
}

Mit dieser Konfiguration werden gleichzeitig mehrere SSL-Einstellungen für den IPv4 und IPv6-Listener vorgenommen:

  1. Die SSL-Engine wird aktiviert.
  2. Es werden die Pfade sosohl zum Server-Zertifikate (inkl. Schlüssel) und zu den CA-Zertifikaten angegeben (s.u.)
  3. Die Unterstützung von veralteten SSL-Versionen wird deaktiviert
  4. Die Cipher-Liste wird eingeschränkt gemäß den Empfehlungen von bettercrypto.org
  5. Die Reihenfolge in der Cipher-Liste wird berücksichtigt
  6. Es wird ein HSTS-Header gesetzt

Damit sollte eine halbwegs sichere SSL-Konfiguration umgesetzt sein.

2| Zertifikate und Schlüssel erzeugen

Wird eine private CA mit XCA verwaltet (siehe Artikel ‘Private CA erstellen’), kann sich wie im Abschnitt ‘4| Server-Zertifikat erstellen’ beschrieben ein Server-Zertifikat erstellen. Dazu wird zunächst der private Schlüssel aus XCA im PEM-Format in die Zwischenablage kopiert und die Datei /etc/lighttpd/server.pem eingefügt (siehe Zeilen 4 und 17 in /etc/lighttpd/conf.d/ssl-enable.conf). Am Ende der gleichen Datei muss auch noch das Server-Zertifikat eingefügt werden.  Die folgenden Bilder zeigen den Export-Vorgang und den Aufbau der Datei:

Für die Datei mit dem Schlüssel sollten die Berechtigungen möglichst restriktiv vergeben werden, damit der private Schlüssel möglichst von niemanden gelesen werden kann:

chmod 600 /etc/lighttpd/server.pem

Danach müssen auch noch die Zertifikate der CAs exportiert werden. Bei mir sind das die Zertifikate der Zwischen-CA und der Root CA. Diese müssen in die  Datei /etc/ca.pem eingetragen werden, wobei das Zertifikat der Zwischen-CA am Anfang der Datei eingefügt wird und das Zertifikat der Root-CA an das Ende der Datei kommt.

3| Weiterleitung von HTTP auf HTTPS einrichten

Da es gelegentlich vorkommt, dass man das https:// vergisst wird zusätzlich auch eine Weiterleitung von HTTP auf HTTPS einrichten. Dazu muss zunächst lighttpd-Modul mod_redirect  installiert werden:

opkg update
opkg install lighttpd-mod-redirect

Anschließend wird die Konfiguration in der Datei /etc/lighttpd/lighttpd.conf angepasst:

server.modules = (
)

server.document-root = "/www"
server.upload-dirs = ( "/tmp" )
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"
#server.username = "http"
#server.groupname = "www-data"

index-file.names = ( "index.php", "index.html",
 "index.htm", "default.htm",
 "index.lighttpd.html" )

static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

# listen on IPv6 (IPv4 Listener wird per Default gestartet)
$SERVER["socket"] == "[::]:80" { }
# Weiterleitung aug https aktivieren:
$HTTP["scheme"] == "http" {
 # capture vhost name with regex condition -> %0 in redirect pattern
 # must be the most inner block to the redirect rule
 $HTTP["host"] =~ ".*" {
 url.redirect = (".*" => "https://%0$0")
 }
 # Set the environment variable properly
 setenv.add-environment = (
 "HTTPS" => "on"
 )
}

include "/etc/lighttpd/mime.conf"
include_shell "cat /etc/lighttpd/modules.d/*.load"
include_shell "cat /etc/lighttpd/conf.d/*.conf"

Das Modul mod_redirect wird bei der Installation (s.o.) automatisch aktiviert. Daher muss es in der Konfiguration nicht explizit angegeben werden.

Jetzt kann der Server neu gestartet werden:

# /etc/init.d/lighttpd restart
Syntax OK
/usr/lib/lighttpd/mod_alias.so
/usr/lib/lighttpd/mod_cgi.so

Wenn alles gut läuft ist anschließend ein lighttpd-Listener sowohl für IPv4 als auch für IPv6 auf Port 80 und 443 gestartet:

# netstat -tulpen
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
[...]
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      9877/lighttpd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      9877/lighttpd
[...]
tcp        0      0 :::443                  :::*                    LISTEN      9877/lighttpd
tcp        0      0 :::80                   :::*                    LISTEN      9877/lighttpd
[...]

4| SSL/TLS Verbindung überprüfen

Nach den Änderungen sollte im Browser bei der Verbindung ein grünes Schloss angezeigt werden (siehe Screenshot).

Wer ganz sicher gehen will kann abschließend mit nmap überprüfen welche Cipher-Suiten unterstützt werden:

Sichere HTTPS-Verbindung zum Turris Omnia
$ nmap --script +ssl-enum-ciphers -n -p 443 192.168.1.1

Starting Nmap 7.40 ( https://nmap.org ) at 2016-12-20 23:37 Eur
Nmap scan report for 192.168.1.1
Host is up (0.00s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|     compressors:
|       NULL
|     cipher preference: server
|     warnings:
|       Key exchange (dh 1024) of lower strength than certificate key
|       Key exchange (secp256r1) of lower strength than certificate key
|   TLSv1.1:
|     ciphers:
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|     compressors:
|       NULL
|     cipher preference: server
|     warnings:
|       Key exchange (dh 1024) of lower strength than certificate key
|       Key exchange (secp256r1) of lower strength than certificate key
|   TLSv1.2:
|     ciphers:
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|     compressors:
|       NULL
|     cipher preference: server
|     warnings:
|       Key exchange (dh 1024) of lower strength than certificate key
|       Key exchange (secp256r1) of lower strength than certificate key
|_  least strength: A