From 92d4cdbde506ab79e0c7012d67885075ba513bc9 Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 26 Sep 2025 16:30:28 +0200 Subject: [PATCH] Add appsettings.example.json, README config docs, and TLS/Long-Term-Auth deployment notes --- DEPLOYMENT_TLS_AUTH.md | 72 ++++++++++++++++++++++++++++++++++++++++ README.md | 26 +++++++++++++++ appsettings.example.json | 13 ++++++++ 3 files changed, 111 insertions(+) create mode 100644 DEPLOYMENT_TLS_AUTH.md create mode 100644 appsettings.example.json diff --git a/DEPLOYMENT_TLS_AUTH.md b/DEPLOYMENT_TLS_AUTH.md new file mode 100644 index 0000000..845ebcd --- /dev/null +++ b/DEPLOYMENT_TLS_AUTH.md @@ -0,0 +1,72 @@ +# TLS and Long-Term Authentication — Integration Notes + +Dieses Dokument beschreibt empfohlene Schritte, Abhängigkeiten und eine kurze Roadmap zur Integration von TLS (turns) und RFC-konformer Long-Term Authentication für den `niom-turn` MVP. + +Ziele +- TLS (turns) auf TCP/TLS Port 5349 (tokio-rustls / rustls) +- Long-Term Authentication (RFC 5389 / RFC 5766): Benutzerverwaltung + MESSAGE-INTEGRITY-Prüfung +- Sichere Speicherung von Credentials (keine Klartext-Passwörter in Produktion) + +Empfohlene Bibliotheken +- rustls + tokio-rustls — TLS für Tokio-basierte Server +- rcgen — optional für lokale self-signed certs während Tests +- ring / argon2 / scrypt — für sichere Passwort-Hashing (statt MD5/A1 in Produktion) + +Schritte (high-level) +1. TLS Listener + - Ergänze einen TCP-Listener auf Port 5349. + - Wrapping der TCP-Streams mit tokio-rustls using a configured ServerConfig (cert + private key). + - Handhabe ALPN falls nötig (z. B. `webrtc` client expectations). + +2. Socket Multiplexing und Protocols + - Behalte den UDP-Listener auf 3478 für STUN/TURN (UDP). Für TLS/TCP setze eine separate Task auf. + - Gemeinsame STUN/TURN-Nachrichtenverarbeitung (Parsing/Antworten) ist wiederverwendbar — benutze die Bibliotheks-Module (`stun.rs`, `alloc.rs`). + +3. Long-Term Auth (Credentials) + - Implementiere ein `PersistentCredentialStore`-Impl der `CredentialStore`-Trait, welches z. B. eine SQLite/Postgres-Tabelle oder Vault/Secrets-Backend nutzt. + - Verifiziere MESSAGE-INTEGRITY gemäß RFC: Client sendet `USERNAME`, `REALM`, `NONCE` und `MESSAGE-INTEGRITY`. Der Server berechnet die HMAC-SHA1 über den Nachrichtenteil entsprechend RFC und vergleicht. + - Verwende sichere Passwortspeicherung: speichere gehashte Passwörter (Argon2/Scrypt) und validiere beim Anmelden. Langfristige TURN-Konten sind oft server-seitig in Klartext/A1 gesetzt; für Produktion empfiehlt sich ein server-seitiges Secret, mit dem kurzfristige Credentials erzeugt werden (REST API zum Erstellen ephemerer Creds). + +4. Nonce / Replay-Protektion + - Implementiere Nonce-Generierung mit ausreichender Entropie und begrenzter Lebenszeit. Optional: zentrale Nonce-Store oder HMAC-gebundene Nonces. + +5. Tests und Fallbacks + - Automatisiere Tests: Unit-Tests für MESSAGE-INTEGRITY, Integrationstests mit `smoke_client` gegen UDP und TCP/TLS. + - Fallback-Mode: if TLS configs not present, start UDP-only server but clearly log the insecure state. + +Code-Snippets / Hinweise +- Beispiel (TLS-Server-Setup sketch): + +```rust +// load cert/key +let certs = load_certs("/path/to/cert.pem")?; +let key = load_private_key("/path/to/key.pem")?; +let mut cfg = rustls::ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(certs, key)?; +let tls_acceptor = tokio_rustls::TlsAcceptor::from(Arc::new(cfg)); + +let listener = TcpListener::bind("0.0.0.0:5349").await?; +loop { + let (socket, peer) = listener.accept().await?; + let acceptor = tls_acceptor.clone(); + tokio::spawn(async move { + match acceptor.accept(socket).await { + Ok(stream) => { + // read STUN messages from the TLS stream, process same as UDP + } + Err(e) => tracing::error!("TLS accept failed: {:?}", e), + } + }); +} +``` + +Prioritäten / Phasen +- Phase 1: Config-driven TLS listener + integration tests (low risk) +- Phase 2: Implement Persistent CredentialStore and nonce lifecycle +- Phase 3: Replace MD5/A1 usage with secure KDF-backed credential workflow (Argon2, PBKDF2) +- Phase 4: Hardening, monitoring, and deployment automation (cert renewal) + +Weiteres +- Wenn du möchtest, kann ich die TLS listener-Integration direkt als PR implementieren (schrittweise: TLS listener -> tests -> credential-store wiring). Ich kann auch Beispiel-Implementierungen für `PersistentCredentialStore` mit SQLite/SQLx anbieten. diff --git a/README.md b/README.md index 2250698..0725007 100644 --- a/README.md +++ b/README.md @@ -109,3 +109,29 @@ Wenn stattdessen eine 401-Antwort (Challenge) ausgegeben wird, sieht man im Hex Hinweis - Die derzeitige Auth-Implementierung ist minimal und für Tests gedacht. Für Produktion bitte die README-Abschnitte "Auth caveat" beachten: sichere Credentials, TLS, und ggf. ephemeral credentials verwenden. +Configuration (appsettings.json) +-------------------------------- +Das Projekt kann eine JSON-Konfigdatei `appsettings.json` im Arbeitsverzeichnis lesen. Eine Beispiel-Datei `appsettings.example.json` liegt im Repository und zeigt die erwartete Struktur: + +```json +{ + "server": { + "bind": "0.0.0.0:3478", + "tls_cert": null, + "tls_key": null + }, + "credentials": [ + { + "username": "testuser", + "password": "secretpassword" + } + ] +} +``` + +Wenn `appsettings.json` vorhanden ist, verwendet der Server die `server.bind` Adresse und befüllt den anfänglichen Credential-Store aus dem `credentials`-Array. Falls die Datei fehlt, verwendet der Server die internen Defaults (Bind `0.0.0.0:3478` und Demo-Cred `testuser`). + +Deployment & TLS / Long-term Auth roadmap +----------------------------------------- +Siehe `DEPLOYMENT_TLS_AUTH.md` für eine kurze Roadmap und empfohlene Schritte zur Integration von TLS (`turns:` / TCP+TLS Port 5349) und der Implementierung von RFC-konformer Long-Term Authentication. + diff --git a/appsettings.example.json b/appsettings.example.json new file mode 100644 index 0000000..98637e5 --- /dev/null +++ b/appsettings.example.json @@ -0,0 +1,13 @@ +{ + "server": { + "bind": "0.0.0.0:3478", + "tls_cert": null, + "tls_key": null + }, + "credentials": [ + { + "username": "testuser", + "password": "secretpassword" + } + ] +}