News

Das Neuste aus der Welt von Adfinis SyGroup

OpenVPN an GitLab User DB anhängen

02/05/2017

In diesem Blog Post soll es darum gehen, wie ein GitLab hinter einem OpenVPN aufgebaut werden kann. Oft steckt in Daten, welche in einem Git-Repository sind, viel Arbeit und somit auch viel Energie, Zeit und Geld. Wer sich nicht nur auf das Login von GitLab verlassen sondern einen weiteren Schutz davor haben will, kann dies z.B. mit OpenVPN lösen. Die Idee ist, dass der Zugriff auf das GitLab nur noch innerhalb des VPN möglich ist.
Damit die User Administration weiterhin simpel bleibt, wird dabei der OpenVPN Server an die User Datenbank von GitLab angebunden.

Impact

Als negativer Punkt sei hier erwähnt, dass User zuerst einen Account mit Passwort haben müssen, bevor sie auf das GitLab verbinden können. Werden die User von einem Administrator verwaltet, erstellt dieser nur die Accounts, jedoch nicht die Passwörter, da GitLab einen Passwort-Reset-Link versendet. Dadurch kann sich der User aber nicht am System anmelden um sein Passwort zu setzen. Dies bedeutet, es muss in einem ersten Schritt zuerst entweder das Passwort durch den Administrator gesetzt werden (indem er die eigene E-Mail Adresse verwendet und später wechselt) oder der User kann über eine schon bestehende VPN Verbindung (z.B. mit Hilfe der Credentials eines schon vorhandenen Accounts) sein Passwort initial setzen.

Realisierung

Hier wird mit einem Debian 8 gearbeitet, jede andere aktuelle Linux Distribution sollte sich aber sehr ähnlich verhalten.
Zuerst wird ein GitLab installiert, dies ist auf der Webseite von GitLab schon dokumentiert (siehe GitLab-CE Install).
Danach wird ein OpenVPN Server mittels apt-get install openvpn installiert.

Zertifikate erstellen

Wir erstellen Keys und Zertifikate für eine CA und für den VPN Server. Dies geschieht vorzugsweise direkt im Verzeichnis, in welchem die OpenVPN Konfiguration (standardmässig /etc/openvpn) liegt.
Zuerst generieren wir den privaten Key und das Zertifikat der CA.

$ openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout ca.key -days 3650 -out ca.pem

Danach erstellen wir einen privaten Key und ein Certificate Signing Request für den Server und signieren diesen mit der CA.

$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout server.key -out server.csr  
$ openssl x509 -req -sha256 -CA ca.pem -CAkey ca.key -days 730 -CAcreateserial -CAserial ca.srl -in server.csr -out server.pem  

Es sollte darauf geachtet werden, dass die beiden privaten Keys (.key-Files) nur durch den benötigten User (in diesem Beispiel git) gelesen werden können.

OpenVPN Server Konfiguration

Der OpenVPN Server wird mit folgender Konfiugration erstellt:

port 1194
proto udp
dev tun
ca ca.pem
cert server.pem
key server.key
dh dh4096.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
cipher AES-256-CBC
comp-lzo
user git
group git
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn-debug.log
verb 3
auth-user-pass-verify /etc/openvpn/auth-user.rb via-env
script-security 3
client-cert-not-required

Der OpenVPN Server wird in der oben beschriebenen Konfiguration vom Client keine Zertifikate erwarten, da die User sich nur per Passwort anmelden sollen.
Der OpenVPN Client verifiziert den Server anhand dessen Zertifikat, welches jedem Client bekannt sein sollte.
Die Verifizierung der Usernamen-Passwort-Kombination wird mithilfe eines externen Scripts gelöst. Dieses Script muss bei gültiger Username-Passwort-Kombination 0, und ansonsten 1, zurückgeben. Aufgrund des gitlab-rails Runner muss das Script in der OpenVPN Konfiguration zwingend mit absolutem Pfad angegeben werden, da der Runner ansonsten das Script nicht findet.
Das Script sieht wie folgt aus:

#!/usr/bin/gitlab-rails runner

begin
    if ((User.find_by_username! ENV['username']).valid_password? ENV['password'])
        exit 0
    end
rescue
    exit 1
end

exit 1

DNS

Damit diese Konfiguration funktioniert, sollten zwei DNS Einträge vorhanden sein. Der erste Eintrag wird gebraucht, damit der VPN Client zum Server verbinden kann und der Zweite wird genutzt, um auf das GitLab zu verbinden.
Der DNS Eintrag für den VPN Server hat die Public IP Adresse des Servers hinterlegt. Der DNS Eintrag für GitLab zeigt auf die IP Adresse im VPN Tunnel, im obigen Beispiel ist dies die erste IP Adresse aus dem IP Pool 10.8.0.1.

vpn.example.com.    IN    A    <Server Public IP>
git.example.com.    IN    A    10.8.0.1

OpenVPN Benutzer Konfiguration (CLI basiert)

Der User kann mit folgender Konfiguration zum VPN Server verbinden. Er muss dafür nebst der Konfiguration auch das Zertifikat der CA ca.pem besitzen, damit er den Server verifizieren kann.

dev tun
remote vpn.example.com 1194
nobind
ca ca.pem
tls-client
persist-key
persist-tun
comp-lzo
cipher AES-256-CBC
pull
auth-user-pass
verb 3

OpenVPN Benutzer Konfiguration (NetworkManager)

Es wird ein neues OpenVPN Setup im Network Manager angelegt.
Die “Identity” Konfiguration sollte dabei wie folgt aussehen (Gateway, Username und Password müssen dabei angepasst und als CA Certificate muss das Zertifikat der CA geladen werden):

Danach wird mit dem Button “Advanced…” das Fenster für die erweiterten Optionen geöffnet.
Dort wird der Reiter “General” wie folgt eingestellt (wichtig ist Use LZO data compression):

und der Reiter “Security” folgendermassen (“Cipher” anpassen):

Danach wird das Advanced Options Fenster mit “OK” wieder geschlossen.

Die IPv4 Konfiguration sollte wie folgt aussehen (“DNS” wird hier ausgeschalten, wichtig ist vor allem, dass IPv4 mit “DHCP” eingeschalten ist und die Routes automatisch konfiguriert werden):

Und schliesslich auch noch die IPv6 Konfiguration ausschalten:

Damit sind alle Konfigurationen für VPN gemacht, nach dem Speichern, kann eine Verbindung zum OpenVPN Server aufgebaut und danach innerhalb vom VPN Kanal der GitLab Server angesurft werden.

Interpretation des RFC 2119 in deutscher Sprache

15/04/2017

Der RFC 2119 vom Autor Scott Bradner von der Harvard University in Cambridge, wurde von Jean-Louis Fuchs von der Adfinis SyGroup in die deutsche Sprache interpretiert. Es handelt sich dabei nicht um eine wortgetreue Übersetzung, sondern um eine Interpretation in Deutsch. Das Ziel dieser Interpretation ist es, den RFC 2119 im deutschsprachigen Raum zur Verfügung zu stellen und zu verbreiten.

Der RFC 2119 behandelt die Schlüsselwörter in Dokumenten, um die Anforderung der Spezifikation aufzuzeigen.

Die Originalversion befindet sich auch auf GitHub.

Schlüsselwörter zum Kennzeichnen von Anforderungen

Status dieses Memorandum

Basierend auf RFC 2119 definiert dieses Dokument Schlüsselwörter zum Kennzeichen von Anforderungen. Dies ist keine Übersetzung, sondern eine Interpretation für Deutschsprachige, damit dieses grossartige Werkzeug auch für Deutsche Dokumentationen eingesetzt werden kann.

Zusammenfassung

Im Standardisierungsverfahren werden in vielen Dokumenten Schlüsselwörter verwendet um Anforderungen der Spezifikation aufzuzeigen. Diese Wörter werden oft gross geschrieben. Autoren die diesen Richtlinien folgen, sollten den folgenden Satz am Anfang ihres Dokuments einfügen:

Die Schlüsselwörter "MUSS", "DARF NICHT", "ERFORDERLICH", "SOLL", "VERBOTEN", "NÖTIG", "NICHT NÖTIG", "SOLL NICHT", "EMPFOHLEN", "DARF", "KANN" und "OPTIONAL" werden nach 2119de interpretiert. https://goo.gl/6QZH4J

Beachten Sie dass die Aussagekraft dieser Wörter, durch die Anforderungen des Dokuments in welchem sie verwendet werden, relativiert werden können.

1. MUSS
oder die Schlüsselwörter “ERFORDERLICH” oder “NÖTIG” bedeuten, dass die Definition eine absolute Anforderung der Spezifikation ist.

2. DARF NICHT
oder das Wort “VERBOTEN” Bedeutet, dass die Definition ein absolutes Verbot der Spezifikation ist.

3. SOLL
oder das Adjektiv “EMPFOHLEN” bedeutet, dass es in speziellen Situationen Gründe geben kann, diese Spezifikation zu ignorieren. Natürlich müssen die Auswirkungen voll und ganz verstanden und sorgfältig abgewägt werden, bevor von der Spezifikation abgewichen wird.

4. SOLL NICHT
oder “NICHT EMPFOHLEN” bedeutet, dass es gute Gründe in speziellen Situationen geben kann, dass dieses Verhalten akzeptabel, ja sogar nützlich sein kann. Natürlich müssen die Auswirkungen voll und ganz verstanden und sorgfältig abgewägt werden, bevor von der Spezifikation abgewichen wird.

5. DARF
oder “KANN”, “NICHT NÖTIG” oder das Adjektiv “OPTIONAL” bedeuten, dass dieses Verhalten wirklich optional ist.

Wichtig bei der Definition einer Interaktion oder Protokolls: Ein Anbieter kann entscheiden dieses Verhalten einzuschliessen, weil es das Produkt verbessert oder für einen speziellen Markt erforderlich ist. Ein anderer Anbieter kann dieses Verhalten weglassen. Eine Implementation die dieses Verhalten weglässt MUSS bereit sein, mit einer anderen Implementation welche dieses Verhalten einschliesst, zu interagieren. In der selben Art MUSS eine Implementation die dieses Verhalten einschliesst mit einer Implementation die dieses Verhalten weglässt interagieren können.

Anmerkung fürs Deutsche: Alle Schlüsselwörter DÜRFEN dekliniert und konjugiert werden. Die Grossschreibung ist ausreichend um die Schlüsselwörter zu erkennen. “NICHT” kann mit “KEIN” ersetzt werden, wie es im Deutschen üblich ist.

Abgrenzung

  1. Leitlinie für die Verwendung

Die Gebote, die in diesem Memo definiert sind, sollen sparsam und mit Sorgfalt eingesetzt werden. Im speziellen ist es NÖTIG, sie nur dort zu benutzen, wo es für die Interaktion wichtig ist oder um nachteiliges Verhalten auszuschliessen. Sie DÜRFEN KEINE Implementationsdetails vorschreiben, welche unabhängig von der Interaktion sind.

  1. Sicherheitsbedenken

Diese Begriffe werden oft verwendet um sicherheitsrelevantes Verhalten zu definieren. Ein MUSS oder SOLL wegzulassen oder etwas zu tun, dass als DARF NICHT oder SOLL NICHT definiert ist, kann subtile Auswirkungen haben. Autoren sollten sich Zeit nehmen, um über Sicherheitsauswirkungen nachzudenken, da die Anwender des Dokuments unter Umständen nicht über die selbe Erfahrung und Hintergrundwissen verfügen.

Danksagung

Ich danke den Autoren des RFCs 2119, welches es mir ermöglicht hat 2119de zu schreiben.

Die Definitionen basieren auf existierenden RFCs. Zusätzlich sind Anmerkungen einer Reihe von weiteren Personen eingeflossen, unter anderem Robert Ullmann, Thomas Narten, Neal McBurnett and Robert Elz.

Autor des original RFCs 2119:

Scott Bradner
email - sob@harvard.edu

Autor:

Jean-Louis Fuchs
email - ganwell@fangorn.ch

MSSQL auf Linux – die Details

11/04/2017

Als bekannt wurde, dass Microsoft MSSQL auf Linux portiert, dachte sich wohl so mancher Sysadmin, dass das in einer Katastrophe endet. Enterprise-Anbieter haben bisher nicht mit gelungenen Linux Ports geglänzt – Oracle DB auf einem Linux-Server zu installieren (und konfigurieren) gehört zu den mitunter schlimmsten Erfahrungen, die ein Admin sammeln kann. Bei Microsoft sieht das so aus:

$ curl https://packages.microsoft.com/config/rhel/7/mssql-server.repo | sudo tee /etc/yum.repos.d/mssql-server.repo
$ sudo yum update
$ sudo yum install mssql-server

Man mag sich verwundert die Augen reiben – Microsoft hat tatsächlich verstanden, wie man Software für Linux paketieren muss. \o/

Doch wie sieht MSSQL für Linux aus der Nähe aus? Engineers der Adfinis SyGroup wagten einen Blick hinter die Kulissen.

Unter der Haube

Eines der wichtigsten Credos beim Portieren von MSSQL auf Linux ist, dass sich das Laufzeitverhalten gegenüber Windows nicht verändert. Applikationen sollen nicht einmal merken, wenn im Backend ein Tux Einzug hält.

Hier stellt sich sofort die Frage, wie Microsoft ein solches Unterfangen löst, schliesslich gibt es immer Edge Cases, wenn man eine Lösung auf eine komplett andere Plattform portiert. Genau solche Edge Cases will man bei einer zentralen Enterprise-Anwendung ausschliesen, schliesslich könnten schon minimalste Regressions bei einer kritischen Lösung immense Schäden auslösen. Schaut man sich noch die vielen Abhängigkeiten an, welche MSSQL hat, stellt man fest, dass eine eigentliche Portierung inkl. aller Libs und Umgebungen wie CLR, eine Monster-Aufgabe darstellt, die sich vom Aufwand her nur schlecht rechtfertigen lässt. In solchen Situationen ist Erfindergeist gefragt und wir finden, dass Microsoft eine sehr kreative Lösung gewählt hat.

Eines sei schon im Voraus gesagt, Microsoft benutzt +/- die selben Executables und Libraries unter Linux wie unter Windows. Wie das ganze geht, erläutert die folgende Übersicht.

SQL OS

Bereits mit SQL Server 2005 hat Microsoft begonnen, Betriebssystem-abhängige Teile in einem eigenen Modul namens SQLOS zusammenzufassen. Das Ziel war damals jedoch noch nicht, andere Plattformen zu unterstützen, sondern tiefergreifende Monitoring- und Analysefunktionen bereitstellen zu können. Dies hatte jedoch den positiven Nebeneffekt, dass die meisten Zugriffe auf das Betriebssystem zentralisiert wurden. Dies wurde für die Portierung auf Linux später zu einem grossem Vorteil. Allerdings war diese Implementation natürlich noch nicht auf die Unterstützung verschiedener Betriebssysteme ausgelegt und viele Windows-Spezifika waren für die übergeordneten Schichten immer noch klar ersichtlich.

Mit diesem Layer könnten zwar die System-Aufrufe zentralisiert portiert werden, jedoch würden die weiteren Module und Bibliotheken, welche von SQL Server verwendet werden, davon immer noch nicht profitieren. Zum Glück hatte eine andere Abteilung innerhalb Microsoft mit dem Projekt Drawbridge begonnen, eine Abstraktion für Windows-Prozesse zu implementieren – ursprünglich, um die Virtualisierung von Windows-Systemen zu vereinfachen.

Drawbridge

Drawbridge ist ein Research Projekt von Microsoft, das schon 2011 das Licht der Welt erblickte. Im Grunde ging es bei Drawbridge darum, den Overhead bei der Virtualisierung von Windows Systemen zu reduzieren. Um dies zu erreichen, benötigte Microsoft knapp zusammengefasst folgende Bestandteile:

  • Prozess-Isolation
  • Layer, der das Windows ABI (Kernel/Syscalls) abbildet
  • User Space Implementation der Windows APIs/Libs (win32 Subsystem)
  • Treiber auf dem Gast-System um das Memory für die VM zu initialisieren

Diese Zutaten ergeben bereits ein relativ klares Bild, was bei Drawbridge passiert, wenn eine VM erstellt wird. Als erstes initiiert der Treiber auf dem Gast-System den Speicher für die virtuelle Maschine. In diesem Schritt wird ein Layer geladen, der das Windows ABI abdeckt – dies wird mit einem User Space NT Kernel bewerkstelligt. Zudem wird eine Library in den Speicher der VM geladen, welche die Windows APIs abbildet. Sowohl der User Mode Kernel wie auch die Library, welche die zahlreichen APIs abbildet, sind Bestandteil von LibOS. Sobald die VM mit LibOS initiiert ist, können darin Windows Binaries ausgeführt und Windows Libraries geladen werden ohne dass ein Syscall oder API-Aufruf die VM verlassen muss.

Drawbridge wurde gemäss unseren Informationen nie in ein Produkt integriert, zeigte aber auf, wie man “leichte Windows Virtualisierung” machen könnte.

LibOS

Wie bereits erwähnt, beinhaltet Drawbridge eine vollständige User Space-Implementation der Windows System Calls und der APIs die unter Windows benötigt werden. Das heisst, dass Drawbridge eine Art User Space Version des NT-Kernels implementierte (NTUM genannt – “user mode NT”) zudem gehört eine Library zu LibOS, welche die Windows APIs im User Space abbildet. Beide Elemente sind gegenüber den eigentlichen Implementationen in einer normalen Windows Umgebung massiv schlanker gehalten, ergeben aber eine Laufzeitumgebung, welche sich nichts anders verhält, als ein herkömmliches Windows.

SQL PAL

Drawbridge und SQLOS ermöglichen in Kombination, MSSQL Server unter Linux auszuführen, gehen aber in ihrer Implementation zum Teil viel zu weit und lösen teilweise die gleichen Probleme. Aus diesem Grund hat das Team bei Microsoft entschieden, die relevanten Teile zu extrahieren und aus Drawbridge, LibOS und dem Abstraktions-Layer SQLOS einen neuen Plattform-Abstraktionslayer (PAL) zu bauen. Dieser enthält nur die für SQL Server relevanten ABI und APIs und bietet alles, was nötig ist, um eine Laufzeitumgebung für MSSQL zu bieten. Die unterste Schicht besteht dabei aus einem Linux Binary (im User Space), welches den Rest der Umgebung initiiert.

Offene ToDos bezüglich SOS und LibOS

Der aktuelle Status ist, dass MSSQL auf Linux bereits problemlos funktioniert, jedoch ist das Team von Microsoft noch nicht fertig mit der Zusammenlegung von SOS und LibOS. So gibt es momentan zwei Versionen von SOS / LibOS innerhalb des SQL Servers für Linux, wobei die “obere” Version Calls an SQL PAL weiterleitet, welches wiederum die neuere Version von SOS verwendet, um via einer Host Bridge Anfragen an den Linux-Kernel zu senden. Microsoft arbeitet aktuell intensiv daran, diese Doppelspurigkeit zu eliminieren und die beiden Instanzen zu vereinheitlichen, damit am Schluss die gesamte Abstraktion in SQL PAL erledigt werden kann.

Die finale Architektur im Überblick

Wie erwähnt, haben Drawbridge und SQLOS einige Überschneidungen, welche Microsoft noch eliminiert. Generell bildet SQL PAL die Laufzeitumgebung für MSSQL und das RPM/DEB Paket bringt alle Executables sowie die nötigen zusätzlichen Windows Libraries mit um MSSQL, aufsetzend auf SQL PAL, ausführen zu können. Gemäss Microsoft werden rund 81MB unkomprimierte Windows Libraries mitgeliefert (das ist nur rund 1% einer kompletten Windows-Installation), das SQL PAL Binary ist rund 8MB gross.

Die Software landet übrigens in /opt und wird mit systemd verwaltet. Microsoft liefert dabei alles pfannenfertig und inklusive man pages aus.

Generell lässt sich der Prozess Ablauf, um MSSQL auf Linux zu starten, wie folgt beschreiben: die Host-Komponente (standard Linux Binary) startet als erstes SQL PAL und dieses initiiert wiederum den MSSQL Server in der “emulierten” Windows Umgebung.

Die finale Architektur sieht in etwa so aus:

 

 

 

 

 

 

 

 

 

Der geneigte Leser wird wohl bereits festgestellt haben, dass dieser Ansatz dem Windows Subsystem for Linux sehr ähnlich sieht.

Erste Erfahrungen

In Zusammenarbeit mit einem unserer Kunden arbeiten wir bereits an der ersten Migration einer MSSQL DB auf Linux.

Die ersten Erfahrungen sind sehr gut und zeigen, dass das Konzept auch in der Praxis funktioniert.

Für das Management der DB unter Linux bietet sich sowohl das CLI wie auch SSMS an, letzteres muss aber bis auf weiteres noch auf Windows ausgeführt werden. Als plattformunabhängige Alternative zu SSMS für Admins die kein Windows nutzen, hat Microsoft die offizielle MSSQL-Erweiterung für Visual Studio Code im Angebot, welches unter Linux, Mac und Windows eingesetzt werden kann. Dabei handelt es sich zwar nicht um einen vollständigen Ersatz für SSMS, die Lösung funktioniert aber sehr gut und bietet u.a. auch IntelliSense support.

Einschränkungen von MSSQL auf Linux

Microsoft kommuniziert sehr offen, wie es bezüglich den aktuellen Einschränkungen von MSSQL auf Linux aussieht und führt diese in den Release Notes exakt auf.

Momentan noch nicht verfügbar sind beispielsweise:

  • Volltext Suche
  • Replikation
  • Active Directory Authentisierung

Genauere Informationen dazu findet man in den offiziellen Release Notes.

Nächste Schritte

Wir planen diverse weitere Tests und wenn es die Zeit zulässt, werden wir noch das eine oder andere weitere Thema in diesem Blog abdecken. Insbesondere interessiert sind wir am Clustering von MSSQL unter Linux, sowie dem Einsatz von MSSQL in Containern.

Fazit

Man muss Microsoft für die vorliegende Lösung ein Kränzchen winden – was die Engineers aus Redmond in Bezug auf die technische Umsetzung vorgemacht haben, hinterlässt bei uns staunende Techies.

Mit dem gewählten Ansatz ebnet Microsoft zudem den Weg für die Portierung weiterer Windows Dienste auf Linux. Schliesslich könnte SQL PAL auch für Exchange, AD, IIS, usw. Pate stehen – uns würde jedenfalls nicht erstaunen, wenn Microsoft schon 2017 verkündet, dass es nun auch Exchange für Linux gibt.

Interesse?

Haben Sie Interesse, MSSQL auf Linux zum Fliegen zu bekommen? Wir helfen sehr gerne weiter und unterstützen Sie mit unserer gesammelten Expertise bei möglichen Migrations-Projekten. Gerne treten wir mit Ihnen in Kontakt, Sie erreichen uns unter info@adfinis.com.

Quellen

Webserver security

07/04/2017

Im Bereich von Webserver sind viele Möglichkeiten vorhanden, um Verbindungen besser abzusichern, aber auch Cross-Site Attacken zu verhindern.

SSL

Es werden hier zuerst die einfachen SSL/TLS Konfigurationen, danach noch erweiterte SSL/TLS Features, wie HSTS und OCSP aufgezeigt. Grundsätzlich wird empfohlen immer aktuelle Protokolle und Cipher Suites, zum Beispiel aus dem Mozilla Wiki, zu kopieren. Diese werden oft nachgeführt und es sind nicht nur verschiedene Cipher Suites aufgelistet, sondern auch die jeweilige Kompatibilitätsliste dazugegeben.

Die Konfiguration “Modern” ist zwar anstrebenswert, jedoch werden sich dadurch ältere Clients oft nicht mehr auf die Server verbinden können. Daher empfiehlt es sich eher, die Konfiguration “Intermediate” zu nutzen. Im Mozilla Wiki und bei Cipherli.st sind auch immer die Konfigurationen verschiedener Software gegeben. Cipherli.st mag zwar übersichtlicher sein und mehr Beispiele aufzeigen, die Cipher Suites sind jedoch längst nicht so durchdacht, wie im Mozilla Wiki. Daher sollten die Cipher Suites eher aus dem Mozilla Wiki übernommen werden.

Nginx

server {
listen 80 default_server;
listen [::]:80 default_server; # Redirect all HTTP requests to HTTPS
return 301 https://$host$request_uri;
} server {
listen 443 ssl http2;
listen [::]:443 ssl http2; # Certs sent to the client in SERVER HELLO are concatenated
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off; # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /path/to/dhparam.pem; # Intermediate configuration, tweak to your needs
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on; # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000; # OCSP Stapling # Fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on; ## Verify chain of trust of OCSP responses
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates; resolver <IP DNS resolver>; [...]
}

Nginx erwartet als CA Zertifikat (Parameter ssl_certificate) das Zertifikat aller Intermediate CAs und das eigene Server Zertifikat (alles im PEM Format). Diese können einfach zusammen kopiert werden (das erste Zertifikat im File sollte das Server Zertifikat sein).

Apache

<VirtualHost *:443>
[...]
SSLEngine on
SSLCertificateFile /path/to/signed_certificate_followed_by_intermediate_certs
SSLCertificateKeyFile /path/to/private/key # Uncomment the following directive when using client certificate authentication #SSLCACertificateFile /path/to/ca_certs_for_client_authentication # HSTS (mod_headers is required) (15768000 seconds = 6 months)
Header always set Strict-Transport-Security "max-age=15768000"
[...]
</VirtualHost> # Intermediate configuration, tweak to your needs
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off # OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)

Testen

Um HTTPS Server zu testen, eignet sich Qualys SSL Labs am besten. Dort sind auch bei neuen Attacken schnell Tests eingebaut, welche die Server auf die Vulnerabilities testen. Alternativ kann hierzu auch Hardenize verwendet werden. Dieses befindet sich momentan aber noch in einer Testphase.

Es ist möglich, mit openssl manuell zu testen, der folgende Test kann dabei einfach mit den eigenen Parameter erweitert werden. Dies ist nur ein Basis Command, welcher den Inhalt des Server Zertifikates in Textform darstellt. Es kann damit auch die Cipher Suite getestet werden, da dies aber lange und vielzählige Commands sind, wird empfohlen, dies mit den vorhandenen Diensten zu machen. Ist dies nicht gewünscht oder technisch nicht möglich, kann z.B. SSL Decoder lokal installiert und ausgeführt werden, die Sources dazu befinden sich auf GitHub ist.

$ openssl s_client -connect example.com:443 2>/dev/null </dev/zero | openssl x509 -noout -text

Weitere Parameter sind in der Manpage von s_client und x509 dokumentiert.

Weitere Features im Bereich von SSL/TLS

Webserver können auch Headers für Strict-Transport-Security und Public-Key-Pins ausliefern. Welche gewünscht sind und welche nicht, hängt vom Einsatz ab.

Strict-Transport-Security – RFC 6797

Die Idee dahinter ist, dass wenn ein Browser mit einer Webseite einmal eine Verbindung hatte, zukünftig weis, dass immer HTTPS genutzt werden soll. Den Wert, der vom Webserver gesendet wird, ist die Anzahl Sekunden für wie lange diese Einstellung gültig sein soll.

Public-Key-Pins – RFC 7469

Mit Public Key Pinning (HPKP) wird die Subject Public Key Info im Zertifikat angegeben (ist schon im Certificate Signing Request), welcher der Webserver ausliefern muss. Mit der stark wachsenden Verbreitung von Let’s Encrypt ist dies nicht mehr so simpel, da dort die Zertifikate automatisch erneuert werden. Wird immer der selbe Certificate-Signing-Request verwendet, funktioniert HPKP, dies muss jedoch so vom Let’s Encrypt Client umgesetzt sein. Das Verständnis von HPKP ist enorm wichtig, um dieses korrekt umzusetzen. Werden Fehler gemacht, können Webseiten gegebenenfalls von gewissen Clients über längere Zeit nicht mehr genutzt werden. Backup Keys sind Pflicht und werden auch vom RFC vorausgesetzt. Backups des Servers dürfen natürlich nicht vergessen gehen.

Weiterführendes

Webserver sollten auch gewisse Headers, z.B. gegen Cross-Site-Scripting, ausliefern. Welche gewünscht sind und welche nicht, hängt vom Einsatz ab. securityheaders.io bietet die Möglichkeit gängige Headers zu testen:

  • Content-Security-Policy
  • X-Frame-Options
  • X-XSS-Protection
  • X-Content-Type-Options

Diese Optionen können Auswirkungen auf die Webseite haben und brauchen teilweise spezifische Anpassungen.

Eine mögliche Konfiguration von Nginx sieht wie folgt aus (in der server Section):

add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";
add_header Content-Security-Policy "script-src 'self'";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

Die entsprechenden Werte sind per Default konfiguriert und sollten so angepasst werden, dass die Seite auch funktioniert. Gängige Browser zeigen in den Developer Tools beim Laden der Seite, was verhindert wurde. Dadurch kann darauf geschlossen werden, welche Werte noch hinzugefügt werden müssen.

Links

Matrix

07/04/2017

Bei Matrix handelt es sich um ein Protokoll, welches sein Hauptmerkmal auf chatten legt. Das Protokoll ist darauf ausgelegt, die schon bestehenden Chat-Lösungen wie z.B. XMPP (Jabber), IRC oder Mattermost zu verlinken.

Vergleich XMPP

XMPP hat grundsätzlich dieselbe Idee, ein Unterschied ist der Aufbau des Protokolles. XMPP hat ein Basis RFC und kann so mit diversen XEPs erweitert werden. Dies macht das Protokoll sehr komplex und jeder Server kann andere XEPs implementieren. Im Gegensatz dazu besteht Matrix aus einem RFC in welchem alles spezifiziert ist. Wenn neue Features dazu kommen, muss das Basis Protokoll selber mit einem neueren RFC erweitert werden.

Funktionalität

Das Protokoll ist auf Basis von HTTP aufgebaut. Jeder Channel und jeder Client ist mindestens einem Server zugeordnet. So hat zum Beispiel der Server example.com den Channel foo, welcher nach dem entsprechenden Namensschema “#foo:example.com“ heisst. Dieser Channel kann aber über mehrere Server verteilt werden, so kann er z.B. auch über “#foo:example.org“ verfügbar gemacht werden. Dies hat den Vorteil, dass ein Channel auch bei Ausfall eines Servers weiterhin verfügbar ist.

Wird eine Message an einen Server geschickt, wird diese danach an jeden Server weitergeleitet, auf welchem ein User diesen Raum ebenfalls aktiviert hat.

Bridges

Es gibt zum Beispiel eine IRC Bridge, welche das IRC Netzwerk Freenode auf Matrix.org zur Verfügung stellt. Wird dem Channel “#freenode_#ansible:matrix.org“ gejoint, sieht dies auf Seite von IRC aus, als ob ein neuer User den Channel “#ansible“ joint, es gibt hierbei pro User und IRC Server eine Verbindung vom Matrix.org Server aus. Auf der Seite von Matrix präsentiert sich das Ganze wie ein normaler Matrix Channel.

Aktuell sind schon diverse Bridges vorhanden. Unten ist eine Übersicht der aktuellen Situation.

Identity Service

Jeder User hat eine Matrix User Identifikation, welche sich nach dem Schema “@user:domain“ richtet, also beispielsweise “@bob:matrix.org“. Die Matrix Accounts werden auf den jeweiligen Homeserver gespeichert. Um Matrix Accounts mit anderen Accounts zu verknüpfen, existiert der Identity Service. Aktuell existiert als bekannter Identity Service Provider nur [Vector.im](https://vector.im). Dieses Feature ist aber optional, da die eigentlichen Accounts auf den jeweiligen Servern liegen und nur die Verknüpfung zu anderen (ausserhalb von Matrix) Accounts dort abgespeichert werden.

Implementationen

Da es sich bei Matrix um ein Protokoll handelt, braucht es noch Implementationen davon. Dabei können drei Komponenten getrennt angeschaut werden, die Server, die Clients und die Bridges.

Server

Die gebräuchlichste Server Implementation ist Synapse, welche in Python implementiert ist. Diese wird von den Protokoll-Entwicklern als ihre Referenz-Implementation zur Verfügung gestellt.

Bridges

Es gibt schon in ganz verschiedene Netzwerke eine Bridge. Die wohl gebräuchlichste ist IRC, von welcher es schon mehrere Produkte gibt. Die Liste der unterstützten Netzwerke ist bereits gross und so können unter anderen auch Bridges zu XMPP, Mattermost, Slack oder GitHub betrieben werden.

Die Integration der Bridges ist mit der Weboberfläche riot.im sehr simpel. Das Aktivieren eines neuen Bots funktioniert in etwa so, dass ein neuer Channel erstellt und in diesem dann der jeweilige Bot hinzugefügt wird. Dafür gibt es in den Room Settings einen Menüpunkt “Manage Integrations”. Diese Bridges werden von Riot zur Verfügung gestellt, die Auswahl ist aber begrenzt. Sollen andere Bots und Bridges hinzugefügt werden oder ist z.B. ein IRC Netzwerk nicht verfügbar, muss der entsprechende Bot oder die entsprechende Bridge selber zur Verfügung gestellt werden.

Clients

Es gibt schon reichlich Clients. Synapse bringt eine kleine Weboberfläche mit. Eine der gebräuchlichsten Oberfläche ist Riot, welche als Web-Applikation, Android App und iPhone App zur Verfügung steht. Riot ist dabei eine reine Webapplikation, welche auf die API von Matrix zugreift. Sie hat selber keine Datenbank oder persistente Daten im Hintergrund.

Eine weiterer Client ist WeeChat, für welchen es ein Plugin gibt. Dies ist für all jene interessant, welche gerne einen Client in der Konsole bedienen.

Erkenntnisse

Matrix macht es einfach über ein Protokoll auf die verschiedenen, schon vorhandenen Protokolle zu zugreifen. Die Möglichkeit den Client selber zu wählen ist ein zusätzliches Nice-to-have.

Diverse Implementationen sind noch in einer Alpha bis Beta Phase. Dies schränkt die Wahl der einzelnen Komponenten beträchtlich ein.

Das Protokoll kennt nur einen reduzierten Satz von HTTP Headern. So ist zum Beispiel der Server Name Indicator (SNI) nicht implementiert, was dazu führt, dass Matrix nur unter gewissen Umständen hinter einem Reverse Proxy betrieben werden kann.