Technik
Unter der Haube
Für IT-Dienstleister und Administratoren: woraus Fonkontor besteht, welche Ports es braucht und wie es abgesichert ist.
Aufbau
Ein Docker-Compose-Stack mit getrennten Diensten. Änderungen an Nebenstellen wirken ohne Neuladen, weil PJSIP Endpunkte bei Bedarf aus der Datenbank liest. Den Wahlplan erzeugt das Backend je Mandant und lädt ihn über ARI nach.
| Dienst | Technik | Aufgabe |
|---|---|---|
asterisk | Asterisk 20 LTS (PJSIP) | Registrar, Anrufsteuerung, Medien, Anrufbeantworter, Warteschlangen. Liest Endpunkte, Leitungen, Postfächer und Warteschlangen live aus PostgreSQL (Realtime), schreibt Anrufdaten dorthin. |
backend | Node.js 22, Express 5, TypeScript | REST-API, schreibt in die PJSIP-Realtime-Tabellen, erzeugt den Wahlplan je Mandant, steuert Asterisk über ARI, Live-Ereignisse per WebSocket. |
web | React 19, Vite, Tailwind CSS 4, nginx | Verwaltungsoberfläche, Einrichtungsassistent, Provisionierung der Telefone, WebRTC-Telefon. |
db | PostgreSQL 17 | Anwendungsdaten und Realtime-Konfiguration; Migrationen laufen beim Start automatisch. |
sbc | Kamailio 6.0, rtpengine 12.5 | Grenzschutz für Telefone und Apps im Internet: TLS/SRTP, WSS mit DTLS-SRTP/ICE, eigene Sperren. Asterisk ist nie direkt im Internet. |
standort-gw | WireGuard (Kernel-Modul) | Je Filiale eigene Schnittstelle und eigener UDP-Port, Rückweg per Policy-Routing – überlappende Filialnetze sind möglich. |
tts (optional) | Piper 1.8, Stimme de_DE-mls-medium | Text-zu-Sprache für Ansagen, nur CPU, rund 250 MB RAM. Ab 2 GB Arbeitsspeicher automatisch aktiv. |
- Mandantenfähig: je Mandant eigener Wahlplan-Kontext, SIP-Benutzer
<nummer>-<mandant>, Anrufe zwischen Mandanten sind bewusst nicht möglich. - Rollen: Betreiber (mandantenübergreifend), Mandanten-Admin, Benutzer.
- Abbilder für amd64; arm64 folgt mit dem öffentlichen Kanal. Kubernetes-Manifeste gibt es für den eigenen Betrieb, Produktform für Dritte ist Compose.
Ports
| Port | Dienst | Zweck | Von außen |
|---|---|---|---|
80 / 443 (sonst 8090 / 8443) | web | Oberfläche, Provisionierung, WebRTC | nein |
5060 udp/tcp | asterisk | SIP im LAN | nein |
5061 tcp | asterisk | SIP über TLS im LAN | nein |
10000–10049 udp | asterisk | Medien im LAN und zum Anbieter | nein |
5063 tcp | sbc | SIP über TLS für Telefone im Internet | ja (am Router z. B. 5061 → 5063) |
8444 tcp | sbc | SIP über WebSocket (WSS) für Apps und Browser | ja (am Router z. B. 8443 → 8444) |
20000–20099 udp | sbc | Medien (rtpengine) | ja |
5062 udp/tcp | sbc | SIP unverschlüsselt (nur für Sonderfälle) | nein, nicht empfohlen |
51821–51850 udp | standort-gw | WireGuard, ein Port je Filiale | ja, je Filiale |
Die Host-Ports des SBC sind über SBC_SIP_PORT, SBC_TLS_PORT undSBC_WSS_PORT in der .env änderbar; Name und Ports nach außen stellt die Oberfläche ein. Im Router SIP-ALG ausschalten.
Sicherheit
- Kein Standard-Konto: Erstes Betreiber-Konto nur mit dem Einrichtungsschlüssel des Installers, 10 Fehlversuche je Adresse sperren 15 Minuten.
- Alle Geheimnisse zufällig erzeugt,
.envmit Rechten 0600. - Passwörter mit scrypt, Sitzungen als HTTP-only-Cookies.
- 2FA mit TOTP, Wiederherstellungscodes und Passkeys (WebAuthn), Pflicht je Rolle einstellbar.
- OIDC mit beliebigem Anbieter (Code-Flow mit PKCE, ID-Token gegen JWKS geprüft), Gruppen → Rolle und Mandant.
- TOTP-Schlüssel und Client-Secrets AES-GCM-verschlüsselt in der Datenbank.
Telefonie-Schutz
- SIP-Schutz: Sperre nach Fehlanmeldungen, „SIP nur aus diesen Netzen“.
- SBC sperrt Anfragefluten (pike), Scanner-Kennungen und wiederholt abgelehnte Anmeldungen; Abgleich mit dem SIP-Schutz jede Minute.
- Berechtigungsklassen je Nebenstelle (intern, national, international, alles); Mehrwertdienste und Satellit nur mit „alles“.
- Notruf 110/112 ohne Berechtigungsprüfung über jede Leitung, jeder Notruf protokolliert.
- TLS und SRTP für Telefone außer Haus, Provisionierung dort nur über HTTPS mit Geheimnis im Pfad.
Telefone und Provisionierung
MAC-basierte Auslieferung aus Vorlagen je Hersteller (Yealink <mac>.cfg, Snom und Grandstream XML). Unbekannte MAC-Adressen bekommen 404; jeder Abruf aktualisiert „zuletzt provisioniert“ und die Gerätekennung. Tasten: Yealink linekey, Snomfkey. Firmware-Verteilung je Hersteller und Mandant; Firmware wird nicht mitgeliefert, sondern vom Kunden hochgeladen. Hot Desking über SIP-NOTIFYcheck-sync.
Im LAN läuft die Provisionierung über HTTP – üblich, aber nur fürs eigene Netz gedacht. Geräte außer Haus erhalten automatisch eine HTTPS-Adresse mit Geheimnis im Pfad und werden auf TLS/SRTP umgestellt.
Installer
curl -fsSL https://fonkontor.de/install.sh | sudo sh
sudo sh install.sh [Optionen]| Option | Wirkung |
|---|---|
--ziel DIR | Installationsverzeichnis (Vorgabe /opt/fonkontor) |
--bild-quelle PFAD | Abbild-Präfix, etwa eine eigene Registry |
--bild-version TAG | Abbild-Version |
--abbilder DATEI.tar | Offline-Installation aus docker save |
--ohne-pull | Abbilder nicht laden (schon vorhanden) |
--ohne-mdns | keinen pbx.local anmelden |
--erzwingen | auch auf nicht unterstützten Systemen fortfahren |
Ein zweiter Lauf ist der Update-Weg: Geheimnisse bleiben, compose.yml wird ersetzt (die alte bleibt als compose.yml.alt), danach pull undup -d. Eigene Anpassungen gehören in compose.override.yml.
Schnittstellen
- REST-API des Backends für Mandanten, Nebenstellen, Geräte und Einstellungen.
- Webhooks bei Anrufereignissen, Namensauflösung eingehender Rufnummern gegen eigene Quellen.
- Klick-zum-Wählen und Präsenzliste (
/api/praesenz, mit Live-Hinweis per WebSocket). - Telefonbuch für die Telefone, Anrufliste aus
cdrin PostgreSQL. - Externer Prüfknoten für die Erreichbarkeit von außen, Netzwerkdiagnose in der Oberfläche.
Fragen zur Integration? Technische Anfrage stellen.