VoxMotoChat - serwer

Podręcznik administratora

wersja dokumentu: 1.0.0 (2026-07-01)

Index

 

Opis

VoxMotoChat Server to wydajny serwer komunikacyjny działający w oparciu o protokół UDP. Serwer wspiera bezpieczne pokoje rozmów z pełnym szyfrowaniem end-to-end (E2EE), mechanizmy niezawodnego dostarczania pakietów (ACK).

 

Funkcje:

  • Szyfrowanie: serwer z ustawionym public: true jest zabezpieczony przez atakiem Man in The Middle (MiTM). Ed25519 służy do uwierzytelniania tożsamości serwera i ochrony przed atakami typu Man-in-the-Middle (MITM), natomiast X25519 jest wykorzystywany do bezpiecznego uzgadniania kluczy sesyjnych. Serwer z ustawionym public = true wysyła do publicznej zaufanej listy serwerów (serverlist to zaufany webservice) swój publiczny identity_key, który pobierają klienci łączący się z serwerem i w ten sposób potwierdzają tożsamość serwera co chroni przed MitM. Obliczony klucz SessionKey dla ChaCha20-Poly1305 jest używany do szyfrowania komunikacji transportowej, osobny obliczony klucz SenderKey ChaCha20 jest obliczany do szyfrowania strumienia audio. Dzięki zastosowaniu Ed25519 i X25519 SessionKey oraz SenderKey nie jest w żaden sposób przesyłany tylko jest obliczany po każdej stronie co znacząco poprawia bezpieczeństwo.
    W przypadku serwerów public = false wciąż Ed25519 służy do uwierzytelniania tożsamości serwera, a X25519 jest wykorzystywany do bezpiecznego uzgadniania kluczy sesyjnych, ale klienci nie mogą potwierdzić tożsamości serwera przez co warstwa transportowa jest narażona na atak MitM, bo serwer nie jest zgłoszony do publicznej listy serwerów i nie opublikował swojego identity_key w serverlist (serverlist to zaufany webservice z listą serwerów), co oznacza, że klienci nie mają możliwości potwierdzenia tożsamości serwera, ale komunikacja jest wciąż w pełni szyfrowana.
  • Synchronizacja: automatyczna synchronizacja list użytkowników i kluczy
  • Publiczna lista: możliwość zgłoszenia serwera do globalnego katalogu VoxMotoChat
  • Administracja: interfejs CLI (komendy)
  • Ochrona przed Atakami Man-in-the-Middle (przed podsłuchem): VoxMotoChat uniemożliwia osobom trzecim przejęcie lub zmodyfikowanie transmisji/pakietów/rozmowy dzięki wielowarstwowej weryfikacji (dotyczy tylko serwerów widocznych na publicznej liście serwerów)

Szyfrowanie - dlaczego takie rozwiązanie?

  • Serwer nie posiada "kluczy głównych": serwer nie generuje i nie posiada kluczy prywatnych klientów, nie posiada jednego Klucza Sesji ChaCha20 (każdy klient ma obliczany dedykowany klucz sesji), nie posiada kluczy do odszyfrowania audio. Każda sesja każdego użytkownika posiada swój własny, unikalny i tymczasowy fundament kryptograficzny. Klucze prywatne nigdy nie opuszczają telefonu użytkownika, a klucze prywatne serwera nie opuszczają serwera. Klucze po stronie klienta i serwera są zawsze generowane nowe przy każdym połączeniu (nowej sesji), a identity_key serwera (do podpisu) jest zawsze generowany na nowo przy każdym uruchomieniu serwera.
  • Efemeryczny Handshake (Ed25519, X25519) i Efemeryczna Sesja (ChaCha20-Poly1305)
  • Wydajność: Ed25519 i X25519 jest używane do handshake i ustalania kluczy do szyfrowania warstwy transportowej i do szyfrowania warstwy audio (dodatkowo w przypadku serwerów, które wysłały identity_key do serverlist komunikacja jest chroniona przed atakiem Man-in-the-Middle (MitM)). Szyfrowanie ChaCha20 (ChaCha20-Poly1305) jest zoptymalizowane pod instrukcje procesorów ARM w telefonach dzięki czemu telefony szybko i wydajnie szyfrują komunikację.
  • Bezpieczeństwo: wszystkie klucze są generowane w pamięci RAM telefonu tylko na czas połączenia z serwerem. Nawet jeśli ktoś przechwyci cały ruch UDP, nie pozna kluczy sesji warstwy transportowej lub warstwy audio.
  • Perfect Forward Secrecy (PFS): dzięki generowaniu nowych kluczy szyfrowania na potrzeby warstwy transportowej i warstwy audio oraz ustalaniu nowych Kluczy Sesji ChaCha20 przy każdym połączeniu (aplikacji VoxMotoChat) z serwerem, kompromitacja jednej sesji nie pozwala na złamanie nowych i historycznych sesji. Każdy klient generuje swój własny klucz i ma wygenerowane indywidualne Klucze do szyfrowania (Klucz Sesji warstwy transportowej do szyfrowania transmisji z serwerem oraz Klucz Sender do szyfrowania warstwy audio)
    Nawet jeśli napastnik w przyszłości przechwyciłby ruch serwera i złamałby zabezpieczenia serwera, nie będzie w stanie odszyfrować przechwyconych już pakietów historycznych z poprzednich sesji ponieważ każde połączenie jest szyfrowane innymi kluczami.
  • Double Encryption:
    • Szyfrowanie Transportowe (Client-to-Server) - chroni całą komunikację UDP między aplikacją a serwerem. Ukrywa przed osobami trzecimi typy pakietów, nazwy użytkowników, metadane.
    • Szyfrowanie End-to-End (Client-to-Client) - dodatkowe szyfrowanie payloadu audio. Serwer nie posiada kluczy E2EE użytych do szyfrowania audio poszczególnych użytkowników. W momencie otrzymania pakietu audio, serwer odszyfrowuje jedynie warstwę transportową, aby rozesłać pakiet do odbiorców, ale sama treść audio pozostaje dla niego zaszyfrowana (nieczytelna). Serwer pełni rolę przekaźnika/routera pakietów audio i przekazuje zaszyfrowane pakiety audio dalej, nie mając wiedzy na temat przesyłanej treści.

 

Informacje techniczne

Jeśli serwer znajduje się za routerem (NAT), należy przekierować port na adres IP maszyny serwerowej.

 

Porty

Usługa Protokół Port Opis
Serwer UDP 27977 domyślny port komunikacyjny serwera, port przychodzący/wychodzący (wymaga przekierowania jeśli za NAT)
Webservice TCP 443 do komunikacji z webservice VoxMotoChat jeśli serwer jest publiczny, port wychodzący (nie wymaga przekierowania)

 

Mechanizm bezpieczeństwa (Rate Limiting)

Serwer posiada wbudowany ogranicznik zapytań. Po przekroczeniu limitu pakiety są ignorowane, a w logach pojawia się ostrzeżenie.

 

Logi

Logi są zapisywane w formacie czytelnym dla człowieka oraz rotowane codziennie o północy. Stare pliki są automatycznie kompresowane.

 

Mechanizm Auto-Cleanup

Serwer automatycznie:

  • Usuwa puste pokoje po 5 sekundach
  • Usuwa wygasłe tokeny zaproszeń
  • Rozłącza klientów, którzy nie wysyłają sygnału heartbeat/nie odpowiadają na ping (konfigurowalne w config.json w sekcji timeouts)

 

Plik konfiguracyjny (config.json)

Plik config.json musi znajdować się w tym samym katalogu co plik wykonywalny serwera.

Przykładowy config.json

{
    "server": {
      "port": 27977,
      "bind_address": "0.0.0.0",
      "public_address": "",
      "statusbar": 1,
      "server_name": "Self-Hosted VoxMotoChat Server",
      "public": true,
      "password_protected": false,
      "password_hash": ""
    },
    "logging": {
      "logDir": "logs",
      "filename": "voxmotochat.log",
      "dateFormat": "YYYY-MM-DD",
      "maxSize": "50m",
      "maxFiles": "7d",
      "level": "INFO"
    },
    "timeouts": {
      "clientCheckInterval": 20000,
      "clientTimeout": 600000
    }
}

Sekcja server

Parametr Typ Opis
port int Port UDP, na którym nasłuchuje serwer (domyślnie: 27666)
bind_address string Adres IP do powiązania (bind). Użyj 0.0.0.0, aby nasłuchiwać na wszystkich interfejsach (domyślnie: 0.0.0.0)
public_address string Adres serwera, który zostanie zgłoszony do publicznej listy serwerów (jeśli serwer jest publiczny -> public: true). Co oznacza, że bind_address może być 0.0.0.0, a w public_address można ustawić np. domenę lub dowolny inny adres IP np. "public_address": "server.domain.com" i serwer będzie widoczny na publicznej liście serwerów (na liście serwerów w aplikacji) z adresem server.domain.com. Jeśli public_address jest pusty lub niepoprawny to serwer wyśle do serwisu z listą serwerów to co jest wpisane w bind_address (w przypadku 0.0.0.0 i "public": true serwis listy serwerów odczyta adres publiczny z którego przyszło zgłoszenie)
statusbar int 1 włącza pasek statusu na górze konsoli, 0 wyłącza
server_name string Nazwa serwera widoczna dla klientów i na liście publicznej (max 96 znaków, dopuszczone znaki w nazwie serwera: litery, cyfry, spacje, myślniki, kropki, kratki, podkreślenia)
public boolean [true/false] (domyślnie: false) Jeśli true, serwer będzie widoczny na publicznej liście serwerów w aplikacji VoxMotoChat. Jeśli false, serwer nie będzie widoczny na liście serwerów i łączyć się do niego można będzie wpisując adres serwera i port w polu "niestandardowy adres serwera" w przeglądarce serwerów w aplikacji
password_protected boolean [true/false] (domyślnie: false) Jeśli true to serwer będzie sprawdzać hasło dostępu (na podstawie password_hash) do serwera zanim klient będzie mógł połączyć się z serwerem/pokojami.
password_hash string [bcrypt hash] Hash bcrypt z hasłem dostępu do serwera (używane jeśli "password_protected": true).
Hash wygenerować można komendą np. voxmotochat-server-amd64 --hashpass hasło

Sekcja logging

Nazwa pliku logu jest rotowana co 24h.

Parametr Typ Opis
logDir string Katalog, w którym będą przechowywane pliki logów (np. "logs")
filename string Nazwa pliku logu
dateFormat string format daty
level string Poziom logowania do pliku: DEBUG, INFO, WARN, ERROR
maxSize string Maksymalny rozmiar pliku logu przed rotacją (np. "100m")
maxFiles string Czas przechowywania starych logów (np. "7d")

Sekcja timeouts

Parametr Typ Opis
clientCheckInterval int Częstotliwość sprawdzania aktywności klientów (ms) (zalecane minimum 10000), wzór na czas: sekundy x 1000=wartość
clientTimeout int Czas (w ms), po którym klient jest rozłączany jeśli nie odpowiada na ping od serwera (zalecane minimum 300000 = 5 min), wzór na czas: minuty x 60 x 1000 = wartość

clientTimeout - minimalny zalecany Timeout to 5 min (optymalny Timeout to 15-20 min (15000-20000)) ponieważ w przypadku zaników internetu w trakcie jazdy, klient może nie odpowiadać na ping przez nawet kilka minut, utrzymanie połączenia z takim klientem pozwala zminimalizować ilość ponownych (automatycznych) połączeń z serwerem, które musi wykonać aplikacja VoxMotoChat na telefonie, jak tylko telefon odzyska połączenie z internetem to aplikacja natychmiast wysyła pakiety audio, które odbiera serwer. Gdy serwer wykryje, że klient nie odpowiada to wyrzuca danego klienta z pokoju co wiąże się z tym, że gdy klient odzyska internet to aplikacja musi ponownie zestawić połączyć z serwerem (bo klient został wyrzucony z serwera) i dołączyć do wybranego pokoju żeby mógł wysyłać do serwera pakiety audio.

 

Uruchomienie serwera - service w Linux

Żeby uruchomić serwer należy ściągnąć plik binarny serwera odpowiedni dla systemu w którym będzie serwer uruchamiany. Należy ustawić plik jako wykonywalny (np. chmod +x voxmoto-server-amd64, a następnie ./voxmoto-server-amd64).

 

Wymagania systemowe (minimalne)

  • CPU: 1 Ghz (zależy od ilości użytkowników na serwerze, im więcej użytkowników tym więcej CPU będzie potrzebne)
  • RAM: 128 MB (zależy od ilości użytkowników na serwerze, im więcej użytkowników tym więcej RAM będzie potrzebne)
  • HDD: 50-100 MB (plik binarny + trochę miejsca dla logów. Im więcej użytkowników i logów tym więcej miejsca potrzebne)
  • System operacyjny: AlmaLinux / Debian / Ubuntu
  • Architektura: x86-64 (PC/serwer dedykowany/VPS), ARM64 (Raspberry Pi 3+/Orange Pi 3+), ARM32/ARMv7 (Raspberry Pi Zero W/Zero 2 W itd)
  • Golang: zainstalowane środowisko Go (zalecana wersja 1.25 lub nowsza).

Obsługa interfejsu CLI (komendy)

Po uruchomieniu serwer oferuje interaktywną konsolę.

Komendy:

  • help - Wyświetla listę wszystkich dostępnych poleceń.
  • status - Wyświetla ogólne statystyki: wykorzystanie procesora, pamięć RAM, liczbę klientów i przepustowość.
  • statusbar - Włącza (1)/wyłącza (0) stały pasek stanu u góry ekranu.
  • tree - Wyświetla hierarchiczną strukturę serwera (Pokoje -> Użytkownicy).
  • users - Wyświetla listę wszystkich podłączonych użytkowników (wraz z identyfikatorem UID, adresem IP i statusem synchronizacji).
  • rooms - Wyświetla listę aktywnych pokoi.
  • handshakes - Wyświetla listę klientów w trakcie nawiązywania połączenia.
  • pending - Wyświetla listę wszystkich klientów oczekujących na synchronizację listy klientów.
  • pending - Wyświetla listę klientów oczekujących na synchronizację listy klientów pokoju
  • inboxes - Wyświetla wszystkie skrzynki odbiorcze na serwerze.
  • inboxes - Wyświetla skrzynki odbiorcze dla konkretnego pokoju.
  • tokens - wyświetla wszystkie tokeny przypisane do pokoju (tj. tylko 6 znaków).
  • kick [uid] [powód] - wymusza rozłączenie użytkownika o podanym identyfikatorze UID. Przykład: kick 1 niewłaściwe zachowanie.
  • loglevel <DEBUG|INFO|WARN|ERROR> - Ustawia poziom logowania dla konsoli CLI.
  • exit - Bezpiecznie wyłącza serwer, wyrejestrowując go z listy publicznej.

 

Uruchomienie serwera jako usługa (w screen)

Kroki:

  1. Wstęp
  2. Utworzenie pliku voxmotochatserver.service
  3. Utworzenie pliku voxmotochatserver.sh
  4. Utworzenie config.json
  5. Przeładowaniu service
  6. Uruchomienie
  7. Sprawdzenie działania
  8. Firewall

Krok 1

Stwórz użytkownika voxmotochatserver (lub dowolnego innego tylko pamiętaj żeby zmienić wpisy voxmotochatserver na nazwę swojego użytkownika oraz ścieżki odpowiednio dla utworzonego użytkownika).

sudo adduser voxmotochatserver 

Pliki serwera są w dziale download, należy ściągnąć odpowiedni plik i umieścić w /home/voxmotochatserver


Ściąganie odpowiedniego pliku do architektury systemu:

Linux AMD64 (x86-64)

curl -L -o voxmoto-server-amd64 https://voxmotochat.com/download-process?file=%2Ffiles%2Fserver%2Flatest%2Fvoxmotochat-server-amd64

lub
Linux ARM64 (Raspberry Pi 3+ / Orange Pi 3+)

curl -L -o voxmoto-server-arm64 https://voxmotochat.com/download-process?file=%2Ffiles%2Fserver%2Flatest%2Fvoxmotochat-server-arm64

lub
Linux ARM32 ( Raspberry Pi 1, 2, Zero, Zero 2 itd,)

curl -L -o voxmoto-server-armv7 https://voxmotochat.com/download-process?file=%2Ffiles%2Fserver%2Flatest%2Fvoxmotochat-server-armv7

Sprawdzenie czy jest golang zainstalowany

go version



Instalacja GoLang (jeśli nie ma w systemie)

AlmaLinux

sudo dnf install golang

Debian/Ubuntu/Raspbian

sudo apt update
sudo apt install golang

lub

sudo apt install golang-go



Krok 2

Utworzenie pliku /etc/systemd/system/voxmotochatserver.service

sudo tee /etc/systemd/system/voxmotochatserver.service > /dev/null << 'EOF'
[Unit]
Description=Voxmotochat server screen session
After=network.target

[Service]
Type=forking
User=voxmotochatserver
WorkingDirectory=/home/voxmotochatserver
ExecStart=/usr/bin/voxmotochatserver.sh
ExecStop=/usr/bin/screen -S voxmotochatserver -X quit
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Krok 3

Utworzenie pliku /usr/bin/voxmotochatserver.sh

sudo tee /etc/systemd/system/voxmotochatserver.service > /dev/null << 'EOF'
#!/bin/bash

cd /home/voxmotochatserver
screen -AmdS voxmotochatserver bash -c '
while true; do
    ./voxmotochat-server-amd64
    echo "Server crashed. Restarting in 5 seconds..."
    sleep 5
done
'
EOF
  • pamiętaj aby zmienić nazwę voxmotochat-server-amd64 na nazwę twojego pliku

Krok 4

Utworzenie pliku /home/voxmotochatserver/config.json

sudo tee /home/voxmotochatserver/config.json > /dev/null << 'EOF'
{
    "server": {
      "port": 27977,
      "bind_address": "0.0.0.0",
      "public_address": "",
      "statusbar": 1,
      "server_name": "Self-Hosted VoxMotoChat Server",
      "public": true,
      "password_protected": false,
      "password_hash": ""
    },
    "logging": {
      "logDir": "logs",
      "filename": "voxmotochat.log",
      "dateFormat": "YYYY-MM-DD",
      "maxSize": "50m",
      "maxFiles": "7d",
      "level": "INFO"
    },
    "timeouts": {
      "clientCheckInterval": 20000,
      "clientTimeout": 600000
    }
}
EOF

Krok 5

Po utworzeniu plików wykonaj:

przeładowanie serwisów

sudo systemctl daemon-reload

aktywowanie usługi voxmotochatserver

systemctl enable voxmotochatserver.service

uruchomienie usługi voxmotochatserver

systemctl start voxmotochatserver.service

Krok 6

Zaloguj się jako użytkownik voxmotochatserver np.

su voxmotochatserver

Krok 7

następnie

screen -r voxmotochatserver

w konsoli pojawi się screen (komendą screen -ls można sprawdzić listę uruchomionych usług w screen) z konsolą serwera VoxMotoChatServer (opuszczenie konsoli screen -> CTRL+A+D), teraz możesz wpisać komendę help żeby wyświetlić dostępne komendy. To wszystko, serwer uruchomiony.



8. Firewall

jeśli jest włączony firewall na serwerze to należy dodać port serwera VoxMotoChat do firewalla

AlmaLinux firewall-cmd:

sudo firewall-cmd --permanent --add-port=27977/udp
sudo firewall-cmd --reload

sprawdzenie

sudo firewall-cmd --list-ports

lub

sudo firewall-cmd --list-all

Wynik: ports: 27977/udp

Debian ufw:

sudo ufw allow 27977/udp

sprawdzenie

sudo ufw status numbered

wynik: 27977/udp ALLOW Anywhere

Debian iptables:

sudo apt install iptables-persistent
sudo iptables -A INPUT -p udp --dport 27977 -j ACCEPT
sudo netfilter-persistent save