Reverse-Proxy auf Basis von OPNsense

Grund

Ich möchte 1) Der Wechsel ist u.a. ein Gebot der Vernunft, da z.B. die Weiterentwicklung der von mir verwendeten und geschätzten Shorewall fraglich ist. Bei der Konfiguration bin ich wegen des eher seltenen Aufbaus auf mich alleine gestellt - keine Firma würde das supporten. Da ist OPNsense erfolgversprechender. von der Firewallbasis Debian mit Shorewall wechseln zu OPNsense. Dazu gehört auch die Funktion des Reverse-Proxys am Eingang des Netzes. Dieser übernimmt auch weitere Aufgaben wie Dynamisches DNS, SSL-Offloading, Letsencrypt usw.

Auch eine Schule kann einen Reverse-Proxy gut gebrauche, da man doch mit der Zeit den einen oder anderen Webdienst auch nach außen verfügbar machen will. Mit ein wenig Aufwand erhält man dann aber mit OPNsense ein hervorragendes Ergebnis.

Übersicht zum Aufbau des Netzes

Die Debian-Web-Server, welche Dienste bereitstellen, sind im Bild ganz rechts.
Der benachbarte AdminPC kann irgendein Betriebssystem haben - solange ein Browser zur Firewallsteuerung läuft.
Die roten Netze existieren hier alle nur innerhalb des KVM-Systems als virtuelle Netze (ohne DHCP oder Hostverbindung). Von oben sind es Schulnetz, Demonetz und das winzige Management-Netz. Natürlich könnte nach rechts aus dem KVM-System auch eine echte Ethernetleitung herausführen, die ebenfalls von der OPNsense-Firewall kontrolliert wird und z.B. mit einem Servernetz verbunden ist.

Uns so erfolgt nun der Zugriff aus dem Internet:

Vom Clients ist zuerst die Fritzbox zu „überwinden“ um eine Verbindung zum Gatewayserver herzustellen. Dieser greift dann stellvertretend als Reverse-Proxy auf die Webserver zu und liefert das Ergebnis an den Client zurück. Welchen der Webserver er anspricht hängt von dem übertragenen FQHN ab (jedenfalls sind die im Folgenden verwendeten „Rules“ so angelegt).

Installation

Plane das Netzwerk und die Serveradressen! Die restlichen Maschinen außer OPNsense können bereits installiert sein, man kann sie ja dann in den virtuellen Netzen verschieben.

Mögliche IP-Adressen innerhalb des KVM-Servers (hier meine heimische Konfiguration):

Maschine	Interface zum Netz	IPv4-Adr. (immer privat)	IPv6-Adr. (public)	Kommentar
OPNsense	LAN	192.168.2.200	dynamisch	von Fritzbox via Präfix weitergegeben
OPNsense	Management	192.168.1.1	-	Standard bei OPNsense-Installation, Port ändern (s.u.)
OPNsense	Schulnetz	192.168.3.1	-
OPNsense	Demonetz	192.168.9.1	-
Admin-PC	Management	192.168.1.100	-
Shellinabox	Schulnetz	192.168.3.133	-	Port 8080 per HTTP
DemoServer	Demonetz	192.168.9.122	-	Port 80 per HTTP
Technikserver	Demonetz	192.168.9.123	-	Port 80 per HTTP

DNS-Vorbereitungen

Dyn-DNS-Adresse besorgen / festlegen (z.B. gatewayexample.dynv6.net)

Zieladressen der Server per CNAME auf die Dyn-DNA-Adresse lenken (hier: remote.example.com und demo.example.com)

OPNsense: Installation und erste Konfiguration

(Stand: April 2020)

Konfigurieren der virtuellen Netze

OPNsense installieren als FreeBSD 11.2 auf KVM,

dabei virtuellen Netzwerkkarten schon vorher als virtio mit den entsprechenden Netzen verbinden. MAC-Adressen merken…

ich empfehle auf Englisch mit Deutscher Tastatur zu arbeiten.

Nach der Installation die Netzwerkschnittstellen inkl. DHCP konfigurieren (nicht Teil dieser Anleitung).

System→Settings→Administration (Web-Gui verlegen)

TCP port: 4433 (Unbedingt den Port (Standard: 443) verlegen - z.B. auf 4433.)

HTTP Redirect: ✓ (Unbedingt Haken setzen für Disable web GUI redirect rule)

Save (nun im Browser die neue Adresse aufrufen und Lesezeichen setzen)

Services → Dynamic DNS für z.B. Dynv6.com konfigurieren, ggf. getrennt für IPv4 und IPv6

System → Settings → Cron dort „+“:

enable: ja,

Minutes: eine Zahl<60

Hours: z.B. 4,6,12,18

Command: Dynamic DNS Updates

Description: Dyn DNS aktualisieren

Save

Apply

Jetzt sollte die Firewall die Server anpingen können und die IP-Adresse beim Dyn-DNS-Dienstleister aktualisieren. Testen! Morgen noch einmal testen!

Fritzbox

OPNsense für Freigaben auswählen

Port-Forwarding (http, https) und Ping6-Freigabe einrichten

noch nicht testbar…

OPNsense: Software nachinstallieren

System → Firmware → Plugins:

os-haproxy

os-acme-client

Konfiguration von Letsencrypt (acme-client) und von HAProxy

Es gibt es einige ausführliche Anleitungen - siehe am Ende der Seite unter Quellen. Meist sind es aber „klick dies - tipp das“-Anleitungen. Damit man weiß, was man überhaupt konfiguriert, betrachten wir folgende Grafik:

Ein einkommender Request (Anfrage eines Browsers) muss zuerst die Firewall von OPNsense überwinden, d.h. die Ports müssen freigegeben sein.

Der Request wird von einem der konfigurierten Public-Services verarbeitet:

Hier gibt es jeweils einen für Port 80 (HTTP) und Port 443 (HTTPS).

Der HTTPS-Public-Service arbeitet mit aktiviertem „SSL-Offloading“, d.h. er erwartet und verarbeitet das HTTPS-Protokoll (rot).

Jeder Public-Service enthält Rules, die zum Entscheiden auf Conditions (also geprüfte Bedingungen) zurückgreifen.

Typisch:

Condition url_ist_shellinabox prüft, ob der angefragte Host den Namen für den shellinabox-Server hat.

Rule server_shellinabox hängt von obiger Condition ab und leitet den Request bei „wahr“ an den passenden Backend-Pool weiter.

Viele Regeln steuern nun den Zugriff auf einen passenden Backend-Pool, der aus einem oder mehreren quasi identischen Servern (Real-Servers) besteht.

Die Idee ist, dass man die Arbeit auf mehrere identische Server verteilen kann inkl. Ausfallsicherheit.

Dann kann man sie z.B. der Reihe nach neu starten, ohne dass der Kunde eine Unterbrechung merkt. Daher das HA im Namen…

Der echte Server bekommt nun über das Netzwerk den Request und gibt eine Antwort zurück, die zum Client weitergeleitet wird. Im Falle von SSL-Offloading wird die Antwort natürlich verschlüsselt weitergeleitet (ohne dass der echte Server dies tut).

Ein spezieller Real-Server ist der vom Letsencrypt-Plugin eingerichtete acme_challenge_host, der in OPNsense selbst läuft. Er muss über Port 80 und HTTP erreicht werden, wenn ein bestimmtet Pfad angefragt wird. Dafür richtet das Plugin selbst eine Regel ein.

Die Verschlüsselung beim Public-Service greift auf das von Letsencrypt gelieferte Zertifikat zurück - sobald es da ist. Man kann den Public-Service für Port 443 also erst danach aktivieren!

Unnötig zu sagen, dass HAProxy natürlich deutlich komplexer ist, als hier dargestellt. So können auch Backend-Server eigene Regeln haben, Conditions können komplexer sein, Benutzeranmeldung kann gemacht werden usw.

Wenn es nicht funktioniert: Unten sind einige Fehler beschrieben.

Verschlüsselung optimieren

Voraussetzung: Es funktioniert!

Nun kann man die Verschlüsselung bei https://SSLLabs.com testen. Vermutlich erhält man eine B-Note. Bei T hat man etwas falsch gemacht… Um auf die Note A+ zu kommen sind nun wenige Optimierungen in den HAProxy-Settings nötig:

Bei Settings→Global Parameters:

Maximum SSL DH Size aus 2048 erhöhen

Bind options: no-tlsv11 ergänzen

Cipher List: Löschen und die Zeichenfolge von Mozilla „Intermediate“ (siehe unten) übernehmen.

Beim Virtual Service→Public Service→ NameMeinesPublicService:

Bind options: no-tlsv11 ergänzen

Cipher List: Löschen und die Zeichenfolge von Mozilla „Intermediate“ (siehe unten) übernehmen.

Enable HTTP/2

Schließlich kann man noch in dem DNS-Server der Domain einen CAA-Eintrag machen:

example.org. CAA 128 issue "letsencrypt.org"

Fehler, die mir unterkamen und ihre Ursachen

Letsencrypt kann das Zertifikat nicht aktualisieren

→ überprüfe, dass die URL (die mit /.well-known beginnt) von außen per HTTP (Port 80) erreichbar ist

→ findet für diese URL eine Weiterleitung zu https statt, so ist entweder

eine solche im HAProxy eingerichtet worden (dann ergänze die Rule so, dass beim acme-challenge-Verfahren nicht weitergeleitet wird) oder

oben der Haken bei „Disable web GUI redirect rule“ nicht gesetzt worden!

HAProxy lässt sich nicht starten

→ Teste die Konfiguration mit dem Button

→ Sind bei abgeschaltetem HAProxy die Ports 80 und 443 wirklich frei? D.h. nicht erreichbar?

Übrigens: Wenn fälschlicherweise immer noch die Administration auf 443 läuft, so bekommt man auch eine merkwürdige DNS-Rebind-Attack-Meldung. Daher „Unbedingt verlegen“.

Die Server sind aus dem LAN zwischen Fritzbox und OPNsense nicht zu erreichen.

Private Network Adresses für WAN-Interface gesperrt? (OPNsense-WAN-Interface-Konfiguration)

Namensauflösung gescheitert, da die Fritzbox interne IP-Adressen nicht auflöst? (testen mit host remote.example.com . Ausnahmeliste in der Fritzbox-Netzwerk-Konfiguration ergänzen)

Kein HTTPS-Zugriff mit Firefox möglich, mit anderen Browsern klappt es:

→ In Letsencrypt OCSP Must Staple angeklickt? Sonst eine gute Idee, wird aber von HAProxy nicht unterstützt und Firefox beschwert sich zu Recht. Also Haken weg, Zertifikat neu ausstellen lassen, fertig.

Quellen & Links

Deutsche Anleitungen:

Schulnetzkonzept: Installation und Konfiguration des Reverse-Proxy-Servers

Triumvirat: HAProxy Reverse Proxy mit Let’s Encrypt Zertifikaten unter OPNsense 20.1

Englische Anleitung:

OPNsense-Forum: HowTo - Let's encrypt with HaProxy with 19.1.4

OPNsense-Dokumentation: HAProxy Installation

Patric Green: Let's Encrypt with HAProxy on OPNsense

Mozilla SSL-Konfiguration:

SSL Configuration Generator

Liefert eine Liste empfehlenswerter Verschlüsselungstechniken (Cipher).

„intermediate“ dürfte für die meisten Anwender praktikabel sein.

Man sollte die Einstellungen z.B. jährlich aktualisieren…

Derzeit (April 2020) lautet sie:

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