Wiki: CSTV, Ingame-Hinweise, Sicherheit, Beamer-Diashow, Lobby-Aufräumen und weitere Ergänzungen

SPP User committed 2026-11-01 22:12:42 +01:00
1 parent bd7b4f2b74
commit 5d64a16ee5
12 files changed
+232 -10

No files matched your search

+7 -3
@@ -8,9 +8,11 @@
- Zuschauer: `/watch/<code>` für Stream und Kommentatoren
Ein Code gilt nur für die Webseite. Den CS2-Serverzugang bekommen Spieler getrennt. Codes lassen sich jederzeit neu erzeugen, der alte Link wird dann ungültig.
Der Organisator sieht den Einladungslink jedes Teams unten in dessen Team-Karte, mit Code, „Kopieren“ und „Neuer Code“. Im Bereich „Einladungen“ stehen der Zuschauer-Link, die Stream-Links und der Organisator-Zugang für ein anderes Gerät.
4. **Spieler treten bei.** Über den Teamlink gibt ein Spieler seinen Namen ein (optional die SteamID64). Der erste Spieler eines Teams wird Captain. Jeder Spieler setzt sich auf „bereit“. Ein Team ist bereit, wenn mindestens ein Spieler dabei ist, ein Captain existiert und alle beigetretenen Spieler bereit sind. Mit `REQUIRE_FULL_TEAMS=true` muss das Team vollständig sein.
5. **Map-Veto.** Sind beide Teams bereit, startet der Organisator das Veto. Die Captains bannen und wählen abwechselnd nach dem festen Ablauf (siehe [Map-Pools und Veto](Map-Pools-und-Veto)). Die letzte verbleibende Map wird automatisch Entscheidungsmap. Für die Seitenwahl per Messerrunde gibt es dauerhafte [Messer-Server](Messer-Server).
6. **Server konfigurieren.** Nach dem Veto richtet das Backend den laufenden Server ein: Spielmodus, erste Map, Teamnamen, Startseiten, Match-Einstellungen, Passwörter und die [Turnierregeln](Turnierregeln).
5. **Map-Veto.** Sind beide Teams bereit, startet der Organisator das Veto. Die Captains bannen und wählen abwechselnd nach dem festen Ablauf (siehe [Map-Pools und Veto](Map-Pools-und-Veto)). Die letzte verbleibende Map wird automatisch Entscheidungsmap. Bei der Seitenwahl per Messerrunde läuft die Runde vorher auf dem eigenen Server des Matches, siehe [Messer-Server](Messer-Server).
6. **Server konfigurieren.** Nach dem Veto richtet das Backend den laufenden Server ein: Spielmodus, erste Map, Teamnamen, Startseiten, Match-Einstellungen, Passwörter und die [Turnierregeln](Turnierregeln). Im Spielchat stehen danach Map, Wahl, Seiten und Serienstand, siehe [Ingame-Hinweise](Ingame-Hinweise).
7. **Während der Serie.** Der Organisator beendet die Aufwärmphase (`mp_warmup_end`), pausiert und setzt fort (`mp_pause_match`, `mp_unpause_match`), lädt die nächste Map, stoppt den Server oder beendet das Match.
8. **Fehlerfälle.** Startet der Server nicht oder schlägt die Konfiguration fehl, zeigt die Seite den Grund. Der Organisator kann den Vorgang über „Server neu starten“ bzw. „Konfiguration wiederholen“ erneut anstoßen. Auch im laufenden Match lädt der neu gestartete Server danach die aktuelle Map samt Passwort wieder.
@@ -27,7 +29,9 @@ Zuschauer und Gäste sehen keinen Chat. Er gilt das ganze Match über, von der L
Das Backend prüft regelmäßig alle Server:
- Match abgeschlossen oder abgebrochen: Server wird gestoppt.
- Match abgeschlossen: Server wird gestoppt, bei CSTV mit Verzögerung erst nach deren Ablauf plus 15 Sekunden (siehe [CSTV](CSTV)).
- Match abgebrochen: Server wird sofort gestoppt.
- Lobby länger als `LOBBY_MAX_HOURS` (Standard 3 Stunden) offen, ohne dass das Veto gestartet wurde: Die Lobby wird samt Server gelöscht.
- Lobby, Veto oder Server ohne Spieler: Nach `SERVER_IDLE_TIMEOUT_MINUTES` ohne Aktivität wird der Server gestoppt. Die Frist zählt frühestens ab dem letzten (Neu-)Start des Servers.
- Messer-Server sind davon ausgenommen, sie laufen dauerhaft.
- Nach `SERVER_MAX_LIFETIME_HOURS` wird jeder Server gestoppt, unabhängig von der Aktivität.
+60
@@ -0,0 +1,60 @@
# CSTV
CSTV ist die Zuschauer-Übertragung von CS2. Jeder Match-Server bringt seinen eigenen CSTV-Zugang mit. Zuschauer, Stream und Kommentatoren verbinden sich darüber, ohne einen Spielerplatz zu belegen.
## Zugang
- **Port:** immer `CS2_TV_PORT_OFFSET` (Standard 100) über dem Spielport, z. B. Spielport 27016 → CSTV 27116. Siehe [Steam-LAN-Browser](Steam-LAN-Browser).
- **Passwort:** erzeugt die App pro Match. Den fertigen Befehl `password …; connect …` sehen Organisator und Zuschauer (Zuschauercode) auf der Match-Seite, nicht die Spieler. Siehe [Rollen und Rechte](Rollen-und-Rechte).
- **Discord:** Beim Match-Start enthält die Meldung den CSTV-Zugang, wenn CSTV an ist.
## Verzögerung
CSTV überträgt mit Verzögerung, Standard **90 Sekunden** (`CS2_TV_DELAY`, im Admin-Bereich unter Einstellungen → Gameserver → CSTV). Die Verzögerung schützt vor Ghosting: Wer neben einem Spieler sitzt, soll auf dem Stream nicht live sehen, wo die Gegner stehen.
Eine Änderung im Admin-Bereich schickt die App sofort an alle laufenden Server.
### Woher früher `tv_delay 0` kam
Bis November 2026 stand CSTV nach jedem Mapwechsel ohne Verzögerung da, obwohl 90 eingestellt waren. Die Ursache lag im Container-Image `joedwards32/cs2`:
1. Das Image kennt die Umgebungsvariable `TV_DELAY` (Standard `0`).
2. Bei jedem Containerstart schreibt sein Startskript diesen Wert in **alle** `gamemode_*.cfg` im Ordner `game/csgo/cfg`.
3. CS2 führt die Datei des Spielmodus bei **jedem Laden einer Map** aus und setzt `tv_delay` damit zurück.
Die Dateien liegen im gemeinsamen Spieldateien-Volume des Hosts. Jeder Container, der startet, schreibt sie für alle Server auf diesem Host neu.
Die App setzt die Verzögerung deshalb an zwei Stellen:
- **Beim Containerstart** gibt sie `TV_DELAY` mit dem eingestellten Wert mit, bei Match- wie bei Messer-Servern.
- **Nach dem Laden jeder Map** setzt sie `tv_delay` per RCON. Das wirkt auch dann, wenn ein anderer Container die gemeinsamen Dateien inzwischen überschrieben hat.
Prüfen lässt sich der Wert per RCON mit `tv_delay` (Antwort z. B. `tv_delay = 90`).
## Mapwechsel innerhalb einer Serie
Die Server laufen mit `tv_delaymapchange 1`: CS2 wechselt die Map erst, wenn CSTV das Ende der alten Map übertragen hat. Nach einem Map-Ende vergeht also mindestens die CSTV-Verzögerung, bis die nächste Map lädt, auch wenn `SERIES_AUTO_ADVANCE_SECONDS` kürzer ist. Der Ingame-Chat nennt diese Zeit, z. B.:
`Nächste Map: Inferno, wird in etwa 90 s geladen (nach der CSTV-Übertragung) - bleibt auf dem Server`
## Ende der Serie
CSTV läuft im selben Container wie der Spielserver und endet mit ihm. Damit Zuschauer das Ende sehen, stoppt die App den Server am Ende einer Serie nicht sofort:
- Das Match wird wie gewohnt abgeschlossen (automatisch nach `SERIES_AUTO_ADVANCE_SECONDS` oder von Hand). Auf der Webseite steht sofort „Abgeschlossen“.
- Der Server läuft danach noch **CSTV-Verzögerung + 15 Sekunden** weiter, bei 90 s also 105 s. Im Ereignisprotokoll steht „Server läuft noch 105 s weiter, damit CSTV das Ende überträgt“.
- Im Ingame-Chat steht: `Der Server bleibt noch etwa 2 Minuten für die CSTV-Übertragung online und schaltet sich dann ab.`
- Der automatische Aufräum-Lauf wartet in dieser Zeit ebenfalls.
- Ein **abgebrochenes** Match stoppt seinen Server sofort.
Ohne CSTV oder mit Verzögerung 0 stoppt der Server wie früher direkt nach dem Abschließen.
## Trennung mit `NETWORK_DISCONNECT_BADDELTATICK`
Seit einem CS2-Update vom November 2024 prüft der Server die Reihenfolge der Bestätigungen von Spielern und CSTV streng (`sv_deltaticks_enforce 2`). Kommen sie außer der Reihe, trennt er die Verbindung mit „Clientseitige Delta-Ticks fehlerhaft“ bzw. `NETWORK_DISCONNECT_BADDELTATICK`, oft direkt nach einem Runden-Neustart.
Die App setzt deshalb `sv_deltaticks_enforce 0`: als Startparameter jedes Containers, beim Einrichten jeder Map und auf den Messer-Servern. Die Prüfung soll Manipulationen am Netzwerkverkehr erschweren. Im LAN ist das Abschalten ein vertretbares Risiko.
## Messer-Server
Auf den [Messer-Servern](Messer-Server) bleibt CSTV technisch an, weil das Image es beim Start einschaltet. Die App gibt ihnen dieselbe Verzögerung mit, damit sie beim Start die gemeinsamen Spielmodus-Dateien nicht auf 0 zurücksetzen.
+3
@@ -16,6 +16,9 @@ Diese Seiten erklären den Betrieb und die Bedienung der Match-Verwaltung für C
- [Docker-Betrieb](Docker-Betrieb) – CS2-Server als Container auf einem Docker-Host
- [Mehrere Docker-Hosts](Mehrere-Docker-Hosts) – Gameserver auf mehrere Rechner verteilen
- [Steam-LAN-Browser](Steam-LAN-Browser) – Server im LAN-Reiter von Steam, Ports und CSTV
- [CSTV](CSTV) – Zuschauer-Übertragung: Verzögerung, Mapwechsel, Ende der Serie, Delta-Ticks
- [Ingame-Hinweise](Ingame-Hinweise) – farbige Hinweise im Spielchat: Map, Seiten, Serienstand, Ergebnis
- [Sicherheit](Sicherheit) – Zugänge, Stream-Schlüssel, Absicherungen, Datenschutz
- [Reverse-Proxy](Reverse-Proxy) – Webseite per HTTPS unter eigener Domain
## Stand
+83
@@ -0,0 +1,83 @@
# Ingame-Hinweise
Die Anwendung schreibt an festen Stellen Hinweise in den Chat auf dem Gameserver, per RCON mit `say`. Im Spiel erscheinen sie als Chatzeile von „Console“. Ein Plugin ist dafür nicht nötig.
## Wann welche Hinweise kommen
**Nach dem Laden einer Map (Aufwärmphase).** Die Hinweise wiederholen sich jede Minute, solange die Aufwärmphase läuft, höchstens zehnmal. So sehen sie auch Spieler, die später verbinden.
```
Map 2 von 3: Inferno - gewählt von Hafenkante
Nordlicht hat die Seite gewählt: Nordlicht startet als CT, Hafenkante als T
Serienstand: Nordlicht 1:0 Hafenkante
Aufwärmphase - das Match startet, sobald der Organisator es freigibt
```
Bei der Entscheidungsmap steht „Entscheidungsmap“ statt „gewählt von“. Im Best of 1 fehlt der Serienstand.
**Beim Match-Start** (der Organisator beendet die Aufwärmphase):
```
Match live! Nordlicht (CT) gegen Hafenkante (T) - viel Glück, have fun
```
**Am Ende einer Map:**
```
Map 1 (Mirage) geht an Nordlicht mit 13:9
Serienstand: Nordlicht 1:0 Hafenkante
Nächste Map: Inferno, wird in etwa 90 s geladen (nach der CSTV-Übertragung) - bleibt auf dem Server
```
Die Wartezeit ist die längere von `SERIES_AUTO_ADVANCE_SECONDS` und der CSTV-Verzögerung, weil CS2 die Map erst nach der CSTV-Übertragung wechselt. Siehe [CSTV](CSTV).
**Am Ende der Serie:**
```
Nordlicht gewinnt die Serie 2:0 - danke fürs Spielen!
Der Server bleibt noch etwa 2 Minuten für die CSTV-Übertragung online und schaltet sich dann ab.
```
Ohne CSTV-Verzögerung fällt die zweite Zeile weg.
## Farben
| Was | Farbe |
|---|---|
| Team, das als CT startet, und „CT“ | Blau |
| Team, das als T startet, und „T“ | Gold |
| „Match live!“, Sieger einer Map, Sieger der Serie | Grün |
| Hinweis zur Aufwärmphase | Gelb |
| alles andere | Weiß |
CS2 zeigt Farben im Chat über Steuerzeichen vor dem Text an. Am Server geprüft wurden diese Codes:
| Code | Farbe |
|---|---|
| `\x01` | Weiß (Standard) |
| `\x02` | Rot |
| `\x04` | Grün |
| `\x07` | Hellrot |
| `\x09` | Gelb |
| `\x0B` | Blau |
| `\x0C` | Dunkelblau |
| `\x0E` | Lila |
| `\x10` | Gold |
Vor dem ersten Farbcode einer Zeile steht ein Leerzeichen, sonst wirkt er nicht immer.
## Sicherheit
- Teamnamen, Map-Namen und andere Eingaben werden vor dem Einsetzen bereinigt: keine Anführungszeichen, kein Semikolon, keine Zeilenumbrüche, keine Steuerzeichen. Niemand kann über seinen Teamnamen weitere Konsolenbefehle anhängen oder eigene Farben einschleusen.
- Farbcodes kommen ausschließlich aus den festen Textbausteinen.
- Im Log des Servers erscheint ein Hinweis als Chatzeile. Chatzeilen können keinen Spielstand verändern, siehe [Sicherheit](Sicherheit).
## Grenzen
- Absender ist immer „Console“.
- Nachrichten an ein einzelnes Team oder einen einzelnen Spieler und große Einblendungen in der Bildschirmmitte gehen nur mit Plugins (CounterStrikeSharp).
- Eine Zeile hat höchstens 120 Zeichen, sehr lange Teamnamen werden auf 32 Zeichen gekürzt.
## Texte ändern
Alle Texte stehen in `server/src/servers/chatAnnouncements.js`, die Tests dazu in `server/test/chatAnnouncements.test.js`.
+3 -2
@@ -12,12 +12,13 @@ Alle Variablen mit Standardwerten stehen in `.env.example` im Repository. Hier d
| `SERVER_ADAPTER` | `demo` | `demo`, `docker` oder `static` |
| `SERVER_IDLE_TIMEOUT_MINUTES` | `30` | Frist bis zum automatischen Herunterfahren |
| `SERVER_MAX_LIFETIME_HOURS` | `8` | harte Obergrenze pro Server |
| `CS2_TV_DELAY` | `90` | CSTV-Verzögerung in Sekunden |
| `LOBBY_MAX_HOURS` | `3` | offene Lobbys (Veto nie gestartet) nach so vielen Stunden samt Server löschen; `0` = nie |
| `CS2_TV_DELAY` | `90` | CSTV-Verzögerung in Sekunden, siehe [CSTV](CSTV) |
| `CS2_GSLT` | leer | Docker: Game Server Login Token. Leer = LAN-Modus (`sv_lan 1`) |
| `CS2_PUBLIC_HOST` | – | **Pflicht bei Docker:** öffentliche Adresse des Docker-Hosts |
| `LOG_RECEIVER_URL` | `PUBLIC_URL` | Adresse, unter der der CS2-Server das Backend erreicht |
| `SERIES_AUTO_ADVANCE_SECONDS` | `30` | Wartezeit nach einem Map-Ende; `-1` = nur manuell |
| `STREAM_KEY` | leer | Schlüssel für die Stream-Übersicht aller Matches |
| `STREAM_KEY` | leer | Schlüssel für Stream-Übersicht und Beamer-Diashow; Organisatoren bekommen einen davon abgeleiteten Schlüssel nur für ihr Match |
| `ADMIN_PASSWORD` | leer | Aktiviert den Admin-Bereich unter `/admin` |
| `LOG_DEBUG` | `false` | empfangene Logzeilen im Terminal ausgeben |
| `VETO_STEP_SECONDS` | `30` | Zeit pro Veto-Schritt, danach wird automatisch gewählt; `0` = ohne Frist |
+17 -2
@@ -8,12 +8,14 @@ Beim Konfigurieren setzt die Anwendung auf dem Server `log on` und `logaddress_a
**Angezeigt werden:** Live-Stand und Rundenverlauf pro Map, Serienstand, Ergebnisse in der Übersicht.
**Nach dem Spielende:** Ist die Serie offen, lädt die Anwendung nach `SERIES_AUTO_ADVANCE_SECONDS` die nächste Map. Ist sie entschieden, etwa 2:0 in Best of 3, schließt sie das Match ab und gibt den Server frei.
**Nach dem Spielende:** Ist die Serie offen, lädt die Anwendung nach `SERIES_AUTO_ADVANCE_SECONDS` die nächste Map. CS2 wechselt dabei erst, wenn CSTV das Ende übertragen hat. Ist die Serie entschieden, etwa 2:0 in Best of 3, schließt die Anwendung das Match ab. Den Server gibt sie erst nach der CSTV-Verzögerung frei, damit der Stream das Ende zeigt. Siehe [CSTV](CSTV).
**Voraussetzung:** Der Server muss `LOG_RECEIVER_URL` erreichen. Ob Daten ankommen, zeigt das Serverpanel des Organisators. Mit `LOG_DEBUG=true` gibt das Backend alle empfangenen Zeilen aus.
**Geprüft** mit echten Logzeilen eines CS2-Servers (Wingman). Eine anonymisierte Fassung liegt unter `server/test/fixtures/wingman-anonym.log`.
Ausgewertet werden nur ganze Systemzeilen nach dem Zeitstempel. Chatzeilen der Spieler können deshalb weder eine Runde noch eine Map beenden, auch wenn jemand den passenden Text eintippt. Siehe [Sicherheit](Sicherheit).
Zwei Eigenheiten von CS2 berücksichtigt der Parser:
- CS2 sendet `Match_Start` schon beim Laden der Map. Gezählt wird erst, wenn der Organisator die Aufwärmphase beendet.
- Direkt nach der Halbzeit nennt CS2 zu Rundenbeginn noch die alte Seitenzuordnung. Ausgewertet werden deshalb nur die Zeilen direkt nach einem Rundenende.
@@ -26,9 +28,22 @@ Unter `/stream` zeigt eine 1920×1080-Seite alle laufenden Vetos und Matches, li
- **Raster:** passt sich der Anzahl an (1, 2, 4 oder 6). Bei mehr als 6 Matches blättert die Seite alle 12 Sekunden weiter.
- **Unten:** offene Lobbys und die Ergebnisse der letzten drei Stunden.
- **Einzelnes Match:** Ein Klick auf eine Karte öffnet `/stream/match/<matchId>`, die Übersicht nur dieses Matches. Der Link enthält keinen Zuschauercode.
- **Schlüssel:** Mit `STREAM_KEY` nur über `/stream?key=<schlüssel>`, sonst offen. `?bg=transparent` macht den Hintergrund durchsichtig.
- **Schlüssel:** Mit `STREAM_KEY` nur über `/stream?key=<schlüssel>`, sonst offen. Ein Organisator bekommt im Link „Match-Übersicht“ nicht den globalen Schlüssel, sondern einen eigenen, der nur sein Match zeigt (siehe [Sicherheit](Sicherheit)). `?bg=transparent` macht den Hintergrund durchsichtig.
- **Datenschutz:** Codes, Verbindungsdaten und Passwörter erscheinen nie.
## Beamer-Diashow
Unter `/beamer` (in der Kopfzeile als „Beamer“ verlinkt) läuft eine Diashow für den Beamer im Saal: **ein laufendes Match pro Folie**, groß und aus der Ferne lesbar.
- **Inhalt:** Teams, Serienstand, aktuelle Map mit Rundenstand und CT/T-Symbolen, die Maps der Serie mit Ergebnis. Im Hintergrund das Bild der aktuellen Map.
- **Veto:** wer gerade bannt oder wählt, und die Maps mit gebannt/gewählt.
- **Server startet:** welche Map gerade eingerichtet wird.
- **Letzte Folie:** offene Lobbys („Gleich“) und die Ergebnisse der letzten Stunden. Läuft kein Match, steht dort „Gerade läuft kein Match“.
- **Weiterschalten:** alle 15 Sekunden, einstellbar mit `?sekunden=20` (5 bis 120). Ein roter Balken unten zeigt die Zeit bis zur nächsten Folie.
- **Bedienung:** Klick oder `F` schaltet Vollbild um, `←`/`→` blättern, Leertaste hält an.
- **Schlüssel:** mit `STREAM_KEY` als `/beamer?key=<schlüssel>` aufrufen.
- Die Seite zeigt nur öffentliche Daten, keine Codes und keine Verbindungsdaten.
## Stream-Übersicht eines Matches
Unter `/stream/<Zuschauercode>` gibt es eine Vollbild-Übersicht für den Stream. Den Link findet der Organisator bei den Einladungen.
+6
@@ -123,6 +123,12 @@ Im Admin-Bereich unter Einstellungen → **Image aktualisieren** auf „Auf alle
Die CS2-Spieldateien liegen im Volume jedes Hosts und kommen mit **Spieldateien aktualisieren** auf den neuesten Stand, auf allen Hosts gleichzeitig. Hosts mit laufenden Servern werden dabei ausgelassen. Siehe [Docker-Betrieb](Docker-Betrieb).
## Welcher Host einen neuen Server bekommt
- Zuerst Hosts, auf denen gerade **kein** Server hochfährt. Ein neuer Container lädt beim Start per SteamCMD die Spieldateien. Nach einem großen CS2-Update kann das lange dauern, und weitere Starts auf diesem Host müssten so lange warten. Gezählt werden Starts in der Warteschlange und Server, die laut Datenbank noch starten. So greift das auch nach einem Neustart der Anwendung.
- Danach der Host mit den meisten freien Plätzen.
- Hosts, auf denen gerade **Spieldateien aktualisiert** werden, bekommen keinen neuen Server. Sind alle anderen voll, schlägt der Start mit einem Hinweis darauf fehl.
## Ein Host fällt aus
Ein laufendes Match lässt sich nicht automatisch auf einen anderen Host verschieben. Der Admin beendet den Server über **Server stoppen** und startet ihn mit **Server neu starten / wiederholen** neu. Welcher Host dann gewählt wird, hängt von den freien Plätzen ab. Ist der Ausfall dauerhaft, den Host aus `CS2_DOCKER_HOSTS` entfernen und die Anwendung neu starten.
+3 -1
@@ -30,7 +30,9 @@ Beim Erstellen eines Matches bei „Wer beginnt das Veto?“ **Messerrunde** wä
2. Die Lobby zeigt den Spielern beider Teams die Verbindungsdaten mit „In CS2 verbinden“.
3. Die **Aufwärmphase läuft ohne Ende**, bis der Organisator in der Lobby **Messerrunde starten** klickt. **Runde wiederholen** setzt zurück in die Aufwärmphase.
4. Nach der Runde klickt der Organisator statt „Veto starten“ auf **„Team A beginnt“** oder **„Team B beginnt“**. Dieses Team beginnt das Veto.
5. Nach dem Veto richtet die App **denselben Server** für das Match ein und nimmt die Messer-Einstellungen zurück. Die Spieler bleiben einfach drauf.
5. Nach dem Veto richtet die App **denselben Server** für das Match ein und nimmt die Messer-Einstellungen zurück. Eine noch laufende Messerrunde setzt sie vorher in die Aufwärmphase, damit ihr Ende nicht als Ende der ersten Map zählt. Die Spieler bleiben einfach drauf.
**Wenn das Einrichten nicht klappt:** Nach einer frischen Installation dauert das erste Laden einer Map oft länger als die Wartezeit. Die App versucht das Einrichten deshalb bis zu dreimal, alle 10 Sekunden. In der Lobby steht dabei „Messerrunde wird erneut eingerichtet (Versuch 2 von 3)“. Scheitern alle Versuche, zeigt die Lobby den Fehler, und der Organisator bekommt den Knopf **Messerrunde neu einrichten**.
Die Knöpfe „Team A/B beginnt“ gibt es auch im Admin-Bereich in der Matchkarte. Gibt es keinen eigenen Server (z. B. Adapter `static`), zeigt die Lobby wie bisher die freien Messer-Server.
+2 -1
@@ -10,7 +10,8 @@ Die Webseite lässt sich hinter einen Reverse-Proxy wie nginx, Caddy oder Traefi
- **Nicht über den Proxy:**
- Die CS2-Spielverbindungen laufen per UDP direkt zum Docker-Host. Für Spieler aus dem Internet braucht es dort Portfreigaben und einen GSLT (`CS2_GSLT`).
- Die Logs der CS2-Server können weiter über das LAN kommen. `LOG_RECEIVER_URL` bleibt dann z. B. `http://192.168.178.31:3000`.
- **Vor dem Freigeben absichern:** Öffentlich erreichbar sind dann auch `/admin` und, ohne Schlüssel, die Stream-Übersicht. Setze ein starkes `ADMIN_PASSWORD` und einen `STREAM_KEY`.
- **Vor dem Freigeben absichern:** Öffentlich erreichbar sind dann auch `/admin` und, ohne Schlüssel, Stream-Übersicht und Beamer-Diashow. Setze ein starkes `ADMIN_PASSWORD` und einen `STREAM_KEY`. Organisatoren bekommen nur einen Schlüssel für ihr eigenes Match, nicht den globalen.
- **Datenschutz:** Die Seite setzt keine Cookies und lädt nichts von fremden Servern, auch die Schriften liefert sie selbst aus. Ein Cookie-Banner braucht es nicht. Öffentlich erreichbar braucht sie aber Impressum und Datenschutzerklärung, z. B. als Link auf die von maxlan.de. Siehe [Sicherheit](Sicherheit).
Beispiel für nginx:
+39
@@ -0,0 +1,39 @@
# Sicherheit
Diese Seite fasst zusammen, wie die Anwendung mit Zugängen, Passwörtern und Eingaben umgeht. Sie beruht auf einer Prüfung vom November 2026, bei der sieben Schwachstellen gefunden und behoben wurden.
## Zugänge
- **Codes und Tokens:** Teams und Zuschauer kommen über Codes auf die Webseite, der Organisator über einen geheimen Token. Wer was darf, steht unter [Rollen und Rechte](Rollen-und-Rechte).
- **Admin-Bereich:** nur mit `ADMIN_PASSWORD`, Anmeldeversuche sind begrenzt. Abgelaufene Anmeldungen werden entfernt.
- **Server-Passwörter:** erzeugt die App pro Match. Spieler sehen das Spielerpasswort, Zuschauer nur den CSTV-Zugang. Das RCON-Passwort verlässt nie das Backend.
## Stream-Schlüssel
Mit `STREAM_KEY` ist die Stream-Übersicht nur über `/stream?key=<schlüssel>` erreichbar.
- Der **globale Schlüssel** zeigt alle Matches. Ihn kennt nur, wer die `.env` verwaltet.
- Ein **Organisator** bekommt im Link „Match-Übersicht“ einen eigenen Schlüssel, der aus `STREAM_KEY` abgeleitet ist und **nur sein Match** zeigt. Daraus lässt sich weder der globale Schlüssel noch ein Schlüssel für ein anderes Match gewinnen.
- Ändert sich `STREAM_KEY`, werden alle abgeleiteten Schlüssel ungültig.
## Was gegen Fehler und Missbrauch abgesichert ist
| Bereich | Absicherung |
|---|---|
| **Live-Verbindung (WebSocket)** | Jede Nachricht wird geprüft, Fehler in der Verarbeitung beenden nie das Backend. Pro Verbindung sind 20 Abfragen am Stück erlaubt, danach 2 pro Sekunde. Vorher konnte eine einzige fehlerhafte Nachricht ohne Anmeldung das Backend beenden. |
| **Fehlermeldungen** | Meldungen von Docker und anderen Programmen werden bereinigt, bevor sie gespeichert oder angezeigt werden. Die Befehlszeile fällt weg, Werte wie `*_PW`, `*TOKEN*` oder `*PASSWORD*` und alle bekannten Passwörter des Servers werden geschwärzt. Vorher stand bei einem fehlgeschlagenen Start das RCON-Passwort in der öffentlichen Statusmeldung. |
| **Live-Ergebnisse** | Ausgewertet wird nur die ganze Systemzeile nach dem Zeitstempel. Chatzeilen von Spielern beginnen mit `"Name<…>"` und passen nie. Vorher konnte ein Spieler mit `Game Over: … score 13:0` im Chat eine Map beenden. |
| **Start, Stopp, Löschen** | Kommt ein Serverstart erst an, nachdem der Server gestoppt, neu angefordert oder das Match gelöscht wurde, baut die App den neuen Container sofort wieder ab. Vorher konnten Container unbeobachtet weiterlaufen. |
| **RCON** | Kaputte Pakete trennen nur die Verbindung. Ein Befehl ohne jede Antwort gilt als Fehler (CS2 bestätigt auch Befehle ohne Ausgabe mit einem leeren Paket). Ausnahme ist `changelevel`, dort prüft die App das Laden der Map selbst. |
| **Anfragen-Begrenzung** | Die Zähler pro Adresse räumen sich regelmäßig auf und haben eine feste Obergrenze. |
| **Ingame-Chat** | Eingaben werden für `say` bereinigt, siehe [Ingame-Hinweise](Ingame-Hinweise). |
Die Tests dazu stehen in `server/test/hardening.test.js`.
## Datenschutz
- **Keine Cookies, kein Tracking.** Im Browser speichert die Seite nur, was für die Bedienung nötig ist: den Match-Zugang (`localStorage`), die Admin-Anmeldung für die Dauer des Tabs (`sessionStorage`), gelesene Chat-Nachrichten sowie Filter und Menüpunkt im Admin-Bereich. Ein Cookie-Banner ist dafür nicht nötig (unbedingt erforderliche Speicherung).
- **Keine Verbindung zu fremden Servern.** Die Schriften (Barlow, Barlow Condensed) liefert die Anwendung selbst aus, nicht über Google Fonts. Dadurch geht keine IP-Adresse an Google, und die Seite funktioniert auch im LAN ohne Internet.
- Ist die Seite öffentlich erreichbar, braucht sie trotzdem Impressum und Datenschutzerklärung, z. B. als Link auf die von maxlan.de. Siehe [Reverse-Proxy](Reverse-Proxy).
Das ist keine Rechtsberatung.
+1 -1
@@ -17,7 +17,7 @@ Der CSTV-Port liegt immer `CS2_TV_PORT_OFFSET` (Standard 100) über dem Spielpor
| 27015–27020 (LAN-Reiter) | 27115–27120 |
| 27100–27139 (normal) | 27200–27239 |
Auf jedem Docker-Host müssen deshalb auch diese CSTV-Ports frei sein.
Auf jedem Docker-Host müssen deshalb auch diese CSTV-Ports frei sein. Verzögerung und Verhalten am Ende einer Serie stehen unter [CSTV](CSTV).
## Host-Netz
+8
@@ -13,6 +13,14 @@ Jeder konfigurierte Server setzt nach dem Mapwechsel diese Werte. Sie orientiere
Dazu kommen die Match-Einstellungen `mp_maxrounds` (24 bei Competitive, 16 bei Wingman), `mp_overtime_enable`, `mp_match_can_clinch 1` und `mp_autoteambalance 0`.
Außerdem setzt die App:
| Befehl | Wert | Zweck |
|---|---|---|
| `mp_endmatch_votenextmap` | `0` | keine Map-Abstimmung nach dem Match, die nächste Map legt das Veto fest |
| `sv_deltaticks_enforce` | `0` | keine Trennung mit `NETWORK_DISCONNECT_BADDELTATICK`, siehe [CSTV](CSTV) |
| `tv_delay` | `CS2_TV_DELAY` | CSTV-Verzögerung, nach dem Laden der Map noch einmal gesetzt, siehe [CSTV](CSTV) |
**Wichtig:** Die Werte stammen nicht aus dem Regelwerk eines konkreten Turniers. Vor einem echten Turnier mit dem Veranstalter abgleichen und in `server/src/servers/cs2Config.js` anpassen.
**Noch nicht geprüft:** ob `sv_pausable` und die Pause-Befehle am echten Server wirken.