opnsense-portal/deploy/config.example.yaml
Carsten Abele 11a3ec2e5f feat(auth): ad.max_tls_version zum Deckeln der angebotenen TLS-Version
Alte Schannel-Stacks brechen an einem TLS-1.3-ClientHello kommentarlos ab:
sie nehmen die TCP-Verbindung an, lesen den ClientHello und setzen zurueck,
ohne ein Zertifikat zu schicken. Herunterhandeln hilft dann nicht — TLS 1.3
darf gar nicht erst angeboten werden.

max_tls_version (Default 1.3) deckelt die Hoechstversion; die Validierung
lehnt eine Hoechstversion unterhalb der Mindestversion ab.

check erkennt zusaetzlich zurueckgesetzte Verbindungen und nennt die beiden
plausiblen Ursachen: fehlendes LDAPS-Zertifikat auf dem Server oder
TLS-1.3-Inkompatibilitaet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBHF4R9EAejDJUMdwr6C68
2026-08-14 13:36:03 +02:00

140 lines
5.4 KiB
YAML

# Beispielkonfiguration für das VPN-Konfig-Portal.
#
# Diese Datei enthält Zugangsdaten. Rechte setzen:
# chown root:vpnportal /etc/vpnportal/config.yaml
# chmod 640 /etc/vpnportal/config.yaml
# Das Portal startet nicht, wenn die Rechte weiter gefasst sind.
#
# Die Datei wird strikt gelesen: ein Tippfehler in einem Feldnamen führt zum
# Startabbruch mit klarer Meldung. Prüfen mit:
# vpnportal check --config /etc/vpnportal/config.yaml
portal:
# Adresse, auf der das Portal lauscht. HTTPS ist Pflicht.
listen: "0.0.0.0:8443"
# Serverzertifikat und privater Schlüssel des Portals.
# Der Schlüssel muss 0600 sein, sonst startet das Portal nicht.
tls_cert: "/etc/vpnportal/portal.crt"
tls_key: "/etc/vpnportal/portal.key"
# Lebensdauer einer Anmeldung. Absolut, nicht verlängerbar. Default: 10m
session_ttl: "10m"
# White-Label: Titel im Browser-Tab und in der Kopfzeile.
title: "VPN-Portal Firma GmbH"
# Optionales Logo in der Kopfzeile (PNG oder SVG).
# logo_file: "/etc/vpnportal/logo.png"
# Wird angezeigt, wenn für einen Benutzer kein Zertifikat hinterlegt ist.
support_contact: "it-helpdesk@firma.de"
# Optionaler Versionscheck. Default: false.
# Eingeschaltet baut das Portal beim Start eine ausgehende HTTPS-Verbindung
# zur Release-URL auf ("telefoniert nach Hause"). Read-only, kein Auto-Update.
# update_check: false
opnsense:
url: "https://fw01.firma.local"
# API-Zugangsdaten eines dedizierten Benutzers, der AUSSCHLIESSLICH das
# Privileg "VPN: OpenVPN Client Export" hat. Niemals einen Admin-Key.
api_key: "BITTE-ERSETZEN"
api_secret: "BITTE-ERSETZEN"
# alternativ als Datei (kompatibel mit systemd LoadCredential, Ansible Vault):
# api_key_file: "/run/credentials/vpnportal.service/opnsense-api-key"
# api_secret_file: "/run/credentials/vpnportal.service/opnsense-api-secret"
# oder als Umgebungsvariable:
# VPNPORTAL_OPNSENSE_API_KEY, VPNPORTAL_OPNSENSE_API_SECRET
# Rangfolge: Umgebungsvariable > *_file > Wert in dieser Datei.
# Interne CA, falls die Firewall ein eigenes Zertifikat verwendet.
# ca_file: "/etc/vpnportal/firma-ca.pem"
# NUR für Tests: deaktiviert die TLS-Prüfung zur Firewall.
# Erzeugt bei jedem Start eine Warnung. Für LDAP gibt es das bewusst nicht.
# insecure_skip_verify: false
ad:
# AD-Domäne. Der Base-DN wird daraus abgeleitet (DC=firma,DC=local).
domain: "firma.local"
# Optionaler Override, z. B. um auf eine OU einzuschränken.
# base_dn: "OU=Mitarbeiter,DC=firma,DC=local"
# Domain Controller mit Failover in dieser Reihenfolge.
# HOSTNAMEN, keine IP-Adressen: das LDAPS-Zertifikat wird gegen den
# Hostnamen geprüft. IP-Adressen werden abgelehnt.
servers:
- "dc01.firma.local"
- "dc02.firma.local"
# LDAPS ist Default. Für StartTLS auf 389:
# port: 389
# tls_mode: "starttls"
# port: 636
# tls_mode: "ldaps"
# Niedrigste akzeptierte TLS-Version zum Verzeichnisdienst.
# Default 1.2. Erlaubt: 1.0, 1.1, 1.2, 1.3.
#
# Nur herabsetzen, wenn die Domain Controller nachweislich kein TLS 1.2
# können (z. B. Windows Server 2012 R2 mit deaktiviertem TLS 1.2). Das
# Portal warnt dann bei jedem Start. Die Zertifikatsprüfung bleibt in jedem
# Fall aktiv — die lässt sich für LDAP bewusst nicht abschalten.
# min_tls_version: "1.2"
# Hoechste angebotene TLS-Version. Default 1.3.
#
# Auf "1.2" setzen, wenn der Domain Controller die Verbindung beim
# Verbindungsaufbau kommentarlos zuruecksetzt. Alte Schannel-Stacks kommen
# mit einem TLS-1.3-ClientHello nicht zurecht und brechen ab, bevor sie ein
# Zertifikat schicken. Erkennbar in openssl s_client an:
# SSL handshake has read 0 bytes and written <N> bytes
# no peer certificate available
# max_tls_version: "1.3"
# Unprivilegierter Domain-Benutzer genügt — er muss nur lesen dürfen.
bind_user: "svc-vpnportal@firma.local"
bind_password: "BITTE-ERSETZEN"
# alternativ: bind_password_file oder VPNPORTAL_AD_BIND_PASSWORD
# bind_password_file: "/run/credentials/vpnportal.service/ad-bind-password"
# Nur Mitglieder dieser Gruppe erhalten Zugang. Verschachtelte Gruppen
# werden aufgelöst. Der Gruppen-DN wird beim Start ermittelt und gecacht.
vpn_group: "VPN-Users"
# Interne CA für LDAPS. Für LDAP gibt es keine Insecure-Option.
# ca_file: "/etc/vpnportal/firma-ca.pem"
# Zeitlimit pro Domain Controller, danach wird der nächste versucht.
# timeout: "8s"
matching:
# Wie der Zertifikats-CN dem Benutzer zugeordnet wird.
# {username} ist der aus dem AD gelesene sAMAccountName in Kleinschreibung.
# Der Vergleich ignoriert Groß-/Kleinschreibung.
cn_pattern: "{username}"
# Beispiel für Bestandsumgebungen mit E-Mail-artigen CNs:
# cn_pattern: "{username}@firma.de"
# Notnagel für Bestandsumgebungen, die sich nicht in ein Template fassen
# lassen. Schließt cn_pattern aus. {username} wird vor dem Kompilieren
# quotiert eingesetzt.
# ACHTUNG: eine zu weit gefasste Regex kann fremde Zertifikate zuordnen.
# cn_regex: "^(vpn-)?{username}(-[0-9]+)?$"
logging:
# debug, info, warn, error. Im Normalbetrieb NICHT debug: auf debug werden
# die verglichenen CNs protokolliert.
level: "info"
# Das Audit-Log enthält personenbezogene Daten. Verzeichnis höchstens 0750,
# Datei wird mit 0600 angelegt.
audit_log: "/var/log/vpnportal/audit.log"
# Eingebaute größenbasierte Rotation (schont SD-Karten).
max_size_mb: 50
max_backups: 5
compress: true