moziloCMS Logo
Spring Control Das Spring-Management System

Funktion des Proxy-Servers

Da weder der Spring selbst noch der Dacia-Server in der Lage sind, zeitgesteuert zu arbeiten, und ein Handy nun mal zur Maschinensteuerung nicht gemacht wurde, wurde aus diesem Grunde der Proxy-Server entwickelt. Er kann mehrere Springs gleichzeitig managen und übernimmt die Kommunikation mit dem Dacia-Server. Damit das funktioniert, benötigt der Proxy eine Datenbank. Und zwar keine relationale Datenbank wie MariaDB, sondern eine objektorientierte Datenbank. Ich habe mich für MongoDB entschieden. Sie lässt sich leicht installieren und konfigurieren. Diese Datenbank läuft bei mir auf einem Linux mit ARM-Prozessor, also einem kleinen Pi. Der ist sehr sparsam, was den Stromverbrauch angeht, und auch ausreichend schnell für diese Aufgabe. Die Datenbank ist sozusagen der Dreh- und Angelpunkt. Der Client kommuniziert mit der Datenbank, und der Proxy kommuniziert mit der Datenbank. Es findet also keine direkte Kommunikation zwischen dem Proxy-Programm und der App statt. Alles läuft über die Datenbank. Der Client holt sich die Daten von der Datenbank und schreibt sie auch in diese hinein. Der Proxy holt sich die Daten vom Dacia-Server und schreibt sie in die Datenbank. Er holt sich auch die Daten von der Datenbank, wertet diese aus und sendet dann die Befehle an den Dacia-Server.

Die Verbindung zwischen der App und der Datenbank ist TLS-verschlüsselt. Das Ganze funktioniert nur mit öffentlichen Zertifikaten, sonst nicht. Deshalb wird auch ein Name benötigt, über den auf die Datenbank zugegriffen werden kann. Dieser Name ist dann über ein Zertifikat abgesichert. Da ich keine feste IP habe, benutze ich einen DynDNS-Dienst. Welcher Dienst verwendet wird, ist egal; ich habe mich für ydns entschieden. Es geht aber auch jeder andere Dienst. Das Zertifikat wird von Let's Encrypt erstellt, das genauso wie der DynDNS-Dienst, die Datenbank und das Linux nichts kostet. Folgende Schritte müssen durchgeführt werden.


Der neue Proxy


Ab der Client-Version 1.3 wird ein neuer Proxy benötigt. Es hat sich einiges geändert. So wird nicht mehr MongoDB als Datenbank verwendet, sondern die Simple-Database, eine von mir entwickelte Datenbank. Die Anmeldung wurde vereinfacht und die Installation auch.

Diese Anleitung ist im entstehen, sie ist also noch fehlerhaft und unvollständig.

Als Hardware dient ein kleiner pi. Ich selbst habe zum testen einen kleinen orange-pi mit 1GB und einer SD-Karte.Das hat für ein paar Autos gereicht. Als ein Profile allerdings zu groß wurde wegen sehr vieler Log-Einträge, das war nicht so gut. Also ist so ein kleiner pi nur für ca. 1-3 Autos geeignet. Wenn die Log-Einträge nicht zu groß sind, dann sicher auch für mehr Autos.
Da ich selbst nicht mit Windows arbeite, gibt es auch keine Anleitung für Windows. Es ist jedoch kein Problem diese Anleitung auch auf Windows zu übertragen. Sollte dabei jemand Probleme haben, so kenn er sich gerne an mich wenden. ich helfe gerne dabei weiter. die Erfahrungen werden dann in diese Anleitung einfließen.

Folgende Schritte müssen für die Installation gemacht werden.
  • Portweiterleitung einrichten
  • Einen DynDNS-Provider suchen & eine Domain erzeugen
  • Webserver installieren und HTTPS für die Domain einrichten
  • Certbot installieren
  • Zertifikate mit Certbot erzeugen
  • Den proxy_dacia und proxy_api auf den Server kopieren
  • Den proxy_api als autostart einrichten
  • Den proxy_dacia als wiederholtes ausführen einrichten
  • Den Client anbinden

Das sieht erstmal viel aus, ist jedoch längst nicht so schlimm. Die Skripte, die gebraucht werden, liefere ich alle mit. Die Änderungen, die gebraucht werden, liefere ich auch mit.

Wie wird nun der Proxy für die App installiert?
Der Proxy selbst braucht keine Installation. Er wird nur auf das System kopiert und läuft dann sofort. Das ist alles. Mehr später.

Die Installation des Webserver

Voraussetzung: Ein 64-Bit-Linux oder Windows. Da ich selbst kein Windows habe, kann ich nur die Linux-Installation genau beschreiben. Da der Prozess jedoch sehr einfach ist, sollte er unter Windows sehr ähnlich ablaufen. Typischerweist installiert man Linux-Server meistens ohne eine GUI. Linux-Server braucht so etwas auch nicht. Es läst sich alles wunderbar über die Kommandozeile erledigen.
Solltet ihr den Proxy für Windows benötigen, so schreibt mich über das Springforum an. Ich kopiere ich nicht immer die aktuellsteVersion des Windows-Proxy in den Download-Bereich.


Die Portweiterleitung

Damit die Kommunikation von außen (also aus dem Internet) zu eurem Proxy-Server zu Hause funktioniert, muss der Router wissen, welches Gerät die Datenpakete erhalten soll. Das erreicht man mit einer Portweiterleitung.
Der Router bekommt eine Anfrage für Port 6443. Mit der Weiterleitung wird ihm gesagt: "Schicke alle Pakete für diesen Port bitte an den Computer mit der IP-Adresse 192.168.1.100 (wenn der Proxy auf dieser ip Installiert ist)".

Portweiterleitung am Beispiel einer Fritz!Box:

  • Gehe in das Webinterface deiner Fritz!Box (meist fritz.box oder 192.168.178.1).
  •   Navigiere zu Internet -> Freigaben -> Portfreigaben -> Gerät für Freigaben hinzufügen.
  • Wähle den Proxy-Server aus der Liste der Geräte aus oder trage seine IP-Adresse manuell ein.
  • Wähle bei Protokoll die Option TCP (und ggf. zusätzlich UDP).
  • Trage bei Von Port und Bis Port die benötigte Portnummer ein (z.B. 6443).
  • Speichere die Einstellung.

Wichtig für LetsEncrypt: Für die Einrichtung muß  vorübergehend auch Port 80 (HTTP) auf den Server weitergeleitet werden. Dieser kann nach erfolgreicher Zertifikats-Einrichtung wieder geschlossen werden. Das der Port jedoch für jede Erneuerung, die ca. alle 60 Tage statt findet, benötigt wird, kann er auch offen gelassen werden.

Wie finde ich meine IP-Adresse?
Auf deinem Proxy-Server in der Konsole den Befehl ip address eingeben. Dann nach der Zeile suchen, die mit inet beginnt und deine lokale IP (z.B. 192.168.xxx.xxx) anzeigt.

DynDNS - Deine Adresse im Internet

Die meisten Internet-Anschlüsse haben eine sich ändernde (dynamische) IP-Adresse. Damit man den Server trotzdem immer unter der gleichen Adresse erreichst, braucht man einen DynDNS-Dienst.

Die einfache Lösung (für Fritz!Box-Nutzer):
Jede Fritz!Box hat einen kostenlosen DynDNS-Dienst integriert. Du findest deine Adresse unter:
Internet -> Freigaben -> FritzBox Dienste.
Dort steht der persönlicher Name der Box, z.B. wirreszeuch.myfritz.net. Diesen Namen kannst Du verwenden.

Alternative (für alle anderen Router):
Falls der Router keinen eigenen Dienst anbietet, musst man sich bei einem DynDNS-Anbieter (z.B. noip.com oder duckdns.org) registrieren. Dort bekommst man einen Domainnamen (z.B. meinserver.ddns.net). Diesen Namen und die Zugangsdaten kann man dann meist in Router eintragen, damit er die Änderungen deiner IP-Adresse automatisch an den Anbieter meldet. Bei mir hat das nie funktionirt. ich lasse alle 5min ein Script auf dem Proxy laufen, welches die Adresse abgleicht. Dies ist auch bei IPV6 die einzige Möglichkeit. Bei Fragen: Das Forum hilft gerne, und ich auch.

Installation und Einrichtung des Webservers nginx

Je nach der Linux-Distribution installierst wird nginx mit einem der folgenden Befehle installiert:
  • Ubuntu/Debian: sudo apt update && sudo apt install nginx
  • Arch Linux: sudo pacman -S nginx

Grundkonfiguration prüfen:
  • Wechsle in das Konfigurationsverzeichnis: cd /etc/nginx
  • Prüfe, ob der Ordner sites-avaiable und sites-enabled existiert: ls -l
  • Falls nicht, lege ihn an: sudo mkdir sites-enabled und /oder sudo mkdir sites-avaiable

Die wichtigste Konfiguration: nginx als Reverse-Proxy
Jetzt musst Du nginx beibringen, dass er den Datenverkehr für deine Domain an deine Proxy-Api weiterleiten soll. Das nennt man "Reverse-Proxy".
Dazu gibt es zwei Möglichkeiten.
Lösche die default-Datei sofern vorhanden in sites-available und sites-enabled und erstelle eine neue Konfigurationsdatei (z.B. sudo nano /etc/nginx/sites-available/mein_proxy). Ersetze meinedomain.dyn.dns überall mit deinem eigenen DynDNS-Namen und 6443 mit dem Port, auf dem deine Proxy-Api läuft. Oder editiere in sites-available, sofern vorhanden, die Datei default mit nano, lösche den Inhalt und füge das hier ein.


Hier nun eine Konfiguratinsdatei für nginx.  


server {
    listen 80 default_server;
    listen [::]:80; #  IPv6 (optional, wenn kein IPV6 vorhanden dann unbedingt mit # auskommentieren)
    server_name meinedomain.dyn.dns;
}


  • Mitsudo  nginx -t kan man die Konfiguration testen
  • Mit sudo systemctl restart nginx den Webserver neu starten
  • Mit sudo systemctl status nginx testen, ob er läuft


Das LetsEncrypt-Zertifikat mit Certbot

Jetzt holen wir uns das kostenlose SSL-Zertifikat für eine verschlüsselte Verbindung.

    Certbot installieren:
    Der einfachste Weg ist die Installation mit snapd.
  
    sudo apt update
    sudo apt install snapd
    sudo snap install --classic certbot
    sudo ln -s /snap/bin/certbot /usr/bin/certbot


Das Zertifikat

Den Domain-Namen holt sich certbot aus der nginx-Datei. Deshalb muß nur auf der Kommandozeile

  sudo certbot --nginx
  
ausgeführt werden.
Stelle sicher, dass die Portweiterleitung für Port 80 aktiv ist und dein DynDNS-Name von außen erreichbar ist!

Automatische Verlängerung einrichten:
LetsEncrypt-Zertifikate laufen nach 90 Tagen ab. Certbot kümmert sich automatisch um die Verlängerung. Teste die automatische Verlängerung mit:

sudo certbot renew --dry-run

Wenn dieser Befehl fehlerfrei durchläuft, ist alles eingerichtet.


Nginx-Datei erweitern

So ungefähr sollte die Datei nun aussehen:


server {
    server_name meinedomain.dyn.dns;


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/meinedomain.dyn.dns/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/meinedomain.dyn.dns/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = meinedomain.dyn.dns) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 default_server;
    listen [::]:80;
    server_name springcontrol.ydns.eu;
    return 404; # managed by Certbot

}


Wir werden sie erweitern um den Teil, der für die Verschlüsselung, Komprimierung und Weiterleitung zuständug ist:

  gzip on;
    gzip_types application/json text/plain text/css application/javascript;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_vary on;
    
    ssl_session_cache shared:SSL:10m;

    # Proxy-Einstellungen für den Dart-Server
    location / {
        proxy_pass http://127.0.0.1:8080; # Leitet alle Anfragen an deinen Dart-Server auf Port 8080 weiter
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off; # Wichtig, um relative Weiterleitungen korrekt zu handhaben

        # Optional: Timeout-Einstellungen für den Proxy
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }


Das bedeutet, das unser neue Datei so aussieht. Der Port 80 wird für die Erneuerung von Zertifikaten benötigt. Deshalb bleibt er erhalten.
Der Port, der Standardmäßig auf 443 steht, kann auf Euren Wunschport hin abgeändert werden. Ich hab ihn auf den Port 6443 geändert.Das kann man machen, muß man aber nicht:


server {
    server_name springcontrol.ydns.eu;

    listen [::]:6443 ssl ipv6only=on; # managed by Certbot
    listen 6443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/meinedomain.dyn.dns/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/meinedomain.dyn.dns/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    gzip on;
    gzip_types application/json text/plain text/css application/javascript;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_vary on;
    
    ssl_session_cache shared:SSL:10m;

    # Proxy-Einstellungen für den Dart-Server
    location / {
        proxy_pass http://127.0.0.1:8080; # Leitet alle Anfragen an deinen Dart-Server auf Port 8080 weiter
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off; # Wichtig, um relative Weiterleitungen korrekt zu handhaben

        # Optional: Timeout-Einstellungen für den Proxy
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

server {
    if ($host = meinedomain.dyn.dns) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 default_server;
    listen [::]:80;
    server_name springcontrol.ydns.eu;
    return 404; # managed by Certbot

}


Der Aufbau des Proxy

Der Proxy ist die Schnittstelle zwischen der App und dem Dacia-Server. Er besteht aus zwei Programmen:

Proxy-Api

Die Proxy-Api kommuniziert indirekt mit dem Client. Da die Verbindung verschlüsselt und auf Wunsch auch komprimiert sein soll, habe ich mich entschlossen, diese Aufgaben einem anderen Programm zu überlassen. So etwas kann ein Webserver viel besser. Ich verwende dazu den nginx-Webserver. Er ist sehr schnell und für diese Aufgabe hervorragend geeignet. Der Client baut also eine verschlüsselte Verbindung mit dem Webserver auf. Dieser wiederum entschlüsselt alles und gibt es an die Proxy-Api weiter. Die Proxy-Api schreibt dann entweder Befehle, die vom Client kommen, in die Datenbank, oder holt Autodaten aus der Datenbank und gibt diese an den Webserver zurück. Der Webserver verschlüsselt und komprimiert die Daten dann und gibt sie an den Client weiter.
Die Proxy-Api läuft, genauso wie der Webserver, dauerhaft.

Die Reihenfolge ist also:

Client -> Webserver -> Proxy-Api -> Datenbank

...und natürlich auch umgekehrt.

Wie funktioniert nun die Registrierung? Dafür gibt es zwei Möglichkeiten:
  • Der Proxy wird mit dem Parameter -a gestartet. In diesem Modus werden alle User, bei denen die Anmeldung am Dacia-Server funktioniert, automatisch in der Datenbank angelegt. Als Anmeldedaten werden die Zugangsdaten für den Dacia-Server verwendet. Das Passwort kann jedoch vor der endgültigen Anmeldung geändert werden, sodass es nicht dem Passwort für den Dacia-Server entsprechen muss.
  • Der Server startet ohne den Parameter -a. In diesem Fall muss jeder User mit einem kleinen Script manuell angelegt werden, bevor er mit dem Proxy arbeiten kann. Dieser Modus eignet sich besonders dann, wenn man den Server nur für sich selbst und eventuell ein oder zwei weitere Personen betreiben möchte.

Oder man startet den proxy_api mit -a, registriert sich, und startet ihn da

Proxy-Dacia

Das ist der zweite Teil des Proxys. Er übernimmt die Kommunikation mit dem Dacia-Server und speichert die empfangenen Daten in der Datenbank. Für ihn gibt es zwei Betriebsarten:
  • Er läuft, wie die Proxy-Api, dauerhaft durch und prüft minütlich, ob etwas zu tun ist.
  • Er startet, prüft, ob etwas erledigt werden muss, und beendet sich anschließend wieder. In diesem Modus sollte er von einem Cron-Job minütlich aufgerufen werden.
Die empfohlene Methode ist der Aufruf über einen Cron-Job jede Minute.

Installation des Proxy

Was welche Teile machen, das wurde oben besprochen. Nun kommen wir zur Installation. Es wird eine .env Datei benötigt die einen Schlüssel zur Verschlüsselung bereithält. Diese Datei kann einfach erzeugt werden durch:

echo "JWT_SECRET=Mein geheimes Passwort" > .env

Sie muß im gleichen Verzeichnis sein wie die beiden Programme proxy_api.exd und proxy_dacia.exe.
Die beiden Dateien müssen ausführbar sein. Wenn mit Linux gearbeitet wird, dann ist alles ok, da die Dateien bereits als Ausführbar markiert runtergeladen werdn. Macht Ihr da mit einem Windows, dann müssen sie wahrscheinlich ausführbar gemacht werden.

In dem Ordner, in dem die beiden Dateien sind einfach die Programme aufrufen mit ./proxy_api.exe und ./proxy_dacia.exe

Sollte es nicht finktionieren, dann macht einfach chmod 775 proxy_api.exe und chmod 775 proxy_dacia.exe

Nun wird die Versionsnummer angezeigt, und welche Parameter benötigt werden.

Installation Proxy-Api

Dieser läuft als Dienst. Er sollte also gestartet werden, sobald der Server gestartet wird. Dazu wird eine Datei unter /etc/systemd/system/ angelegt, z.B. proxy_api.service.

[Unit]
Description=Dacia API Proxy Service
After=network.target

[Service]
Type=simple
User=dein-Username
WorkingDirectory=/home/dein-Username/springcontrol/
ExecStart=/home/dein-Username/springcontrol/proxy_api.exe -p /home/dein-Username/springcontrol -a
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target

Mit sudo systemctl start proxy_api wird er gestartet, und mit sudo sytemctl stop proxy_api  wird er beendet. Mit sudo systemctl status proxy wird der aktuelle Status angezeigt. Damit der Proxy beim Systemstart auch geladen wird, kan man folgenden Befel machen: sudo systemctl enable proxy_api

Installation Proxy_Dacia

Dieser Teil des Proxy sollte jede Minute einmal gestartet werden. Dazu einfach mit sudo nano /etc/crontab die Datei editieren und folgenden Eintrag machen:

* * * * *     Dein-Username /home/dein-Username/springcontrol/proxy_dacia.exe -p /home/dein-Username/springcontrol/ -m normal -k

Das ist alles. Die Verzeichnisstruktur wird automatisch für die Datenbank angelegt.

Nun sollte alles funktionieren.