Nginx als Reverse Proxy mit websocket für FHEM

Begonnen von h3llsp4wn, 16 Februar 2017, 14:37:53

Vorheriges Thema - Nächstes Thema

h3llsp4wn

Hallo zusammen,

u.a. da ich FHEM hinter nginx betreibe und auch die TabletUI gerne auf websocket umstellen wollte, stellt sich mir die Frage bzgl. Konfiguration von nginx. Nun bin ich da leider
kein Experte - allerdings kann ich entweder nur FHEM hinter dem Proxy erreichen oder dann nur den websocket - beides an localhost:8083 zu binden klappt nicht. Dazu müsste
ich ggf. eine anderen Entry-Point haben, d.h. eine location für fhem (/fhem) und dann ggf. eine für den websocket (/fhem_ws) o.ä. - soweit ich das verstehen. Im Apache
könnte man da wohl mir rewrite rules was basteln. Ich möchte allerdings, da ich auch noch andere Dinge laufen habe nicht wieder alles auf Apache umbauen.

Daher die Frage - nutzt jemand ggf. nginx als reverse proxy und hat hier auch die websockets ans laufen bekommen - und wenn ja, wie?


Cheers,

h3ll

vbs


h3llsp4wn

Stimm - guter Hinweis :)


map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

upstream fhem {
server localhost:8083;
}

server {
        #listen   80; ## listen for ipv4; this line is default and implied
        #listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

        root /var/www;
        index index.html index.htm index.php;

        # Make site accessible from http://localhost/
        server_name localhost raspberrypi.fritz.box raspberrypi;

        location /fhem {
access_log off;

                proxy_pass http://localhost:8083;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
#proxy_read_timeout 150;
                proxy_redirect off;
                proxy_buffering off;
}
...


Den timeout hatte ich mal zum Test gesetzt ... wenn ich es so laufen lasse und im FHEM longpoll auf websocket setze, dann kann ich verbinden, aber meine Aufruf direkt ohne Port über den Proxy
gibt keine Rückmeldung mehr.

vbs

Vielleicht kannst du dir was mit der Variable $server_protocol und einem "if" basteln, aber besser wärs wie du ja auch schon gesagt hast, wenn die beiden Diensten unter getrennten locations erreichbar wären. Google bringt aber sofort "if is evil" :D https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/

h3llsp4wn

#4
Danke - service_protocol hatte ich gar nicht auf dem Schirm ... evil if habe ich auch schon gesehen  >:(, das wollte ich verhindern - trotzdem danke - ich werde es mal damit versuchen  ;).

Nachtrag - so läuft es jetzt bei mir - mit einem evil if und dem check gegen das upgrade. Der Umweg über die Variablen ist erforderlich, da nginx das setzen im if dieser Attribute nicht zulässt ... also
quasi auch schon wieder ein hack. Wer eine bessere Idee hat - her damit.

Anbei der fhem Block:


        location /fhem {
                access_log off;

                set $bla_remote_addr "";
                set $bla_proxy_add_x_forwarded_for "";
                set $bla_upgrade "";
                set $bla_connection "";
                set $bla_header "";

                if ($http_upgrade = "websocket") {
                        set $bla_remote_addr $remote_addr;
                        set $bla_proxy_add_x_forwarded_for $proxy_add_x_forwarded_for;
                        set $bla_upgrade $http_upgrade;
                        set $bla_connection "upgrade";
                        set $bla_header $host;
                }

                proxy_pass http://localhost:8083;
                proxy_set_header X-Real-IP $bla_remote_addr;
                proxy_set_header X-Forwarded-For $bla_proxy_add_x_forwarded_for;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $bla_upgrade;
                proxy_set_header Connection $bla_connection;
                proxy_set_header Host $bla_header;
                proxy_redirect off;
                proxy_buffering off;
        }


All-Ex

Habe das bei mir nicht hinbekommen. Du lässt bei deiner if-Lösung dann den map Befehl weg oder?

Wieso bleiben denn bei allen Verbindungen ohne connection upgrade die $bla Variablen auf ""?

h3llsp4wn

Hm ... weil ich diese dann nicht brauche? Bin aber kein Experte. So funktioniert es zumindest bei mir. D.h. eine richtige Antwort habe ich da nicht.

dela2017

Hi Hellspawn,

hast du vielleicht noch irgendeine Besonderheit?
Ich möchte eigentlich wohl das gleiche wie du; ich hab deinen Teil der Konfig übernommen, aber dennoch verliert die TabletUI immer die Connection; bzw. auch auf der FHEM Hauptseite erscheint praktisch die ganze Zeit: Connection lost, trying a reconnect every 5 seconds

Gruß,
Ingo

Civicoid

Danke für den Code!
Nun läuft mein FHEM wieder flüssig über NGINX.

8)
Fhem v5.9 @ MS-7877 Board mit J1900 als Server
mit Ubuntu 18.04.1 LTS, Nginx, Php7, TabletUI, Framework7, MQTT, JeelinkClone, Sduino, nanoCUL, maxCube, Synology-NAS
---
Sensoren/Aktoren:
EdiPlug, LaCrosse-Sensoren, MAX! Thermostate und Fensterkonakte, Alexa

Klouse

Hallo,

grundsätzlich scheint es zu funktionieren, leider erhalte ich jedoch ebenso wie dela2017 regelmäßig disconnect Meldungen.

Hat noch jemand einen Tipp für uns?

Danke!

LG,
Klaus

sickboy79

Hi,

Danke h3llsp4wn für deine Konfiguration. Ich habe mal eine Konfiguration basierend auf der NGINX Anleitung im Wiki und deiner Konfiguration für das Thema Websockets als Vorschlag mal im Wiki zusammengetragen.

https://wiki.fhem.de/wiki/Diskussion:HTTPS-Absicherung_%26_Authentifizierung_via_nginx_Webserver

Was meint ihr? Aktuell kann ich noch keine Verbindungsabbrüche beobachten.

LG,
Tobias

vbs

Das hier macht mir wie gesagt Sorgen (und ist auch der Grund warum ich es nicht nutze):
https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/


sickboy79

Hi VBS,

so lange es bei einem if block bleibt sehe ich an dieser Stelle kein Problem. Natürlich gäbe es alternativen mit zusätzlichen nginx modulen, aber die gezeigte Konfiguration wird bei mehr als 90 % der Anwendungen ohne Probleme funktionieren.

If is not so evil afterall if you understand how it works :-)


flocki

#13
Guten Morgen,
ich habe jetzt schon diverse Foreneinträge ausprobiert und auch im Internet gesucht, aber bisher habe ich nichts gefunden.
Habe das problem das ich zwar fhem angezeigt bekomme, aber nur das menü als Text auf weißem Hintergrund und ohne Funktion.
Scheint als ob css nicht weiter durch gegeben werden.

Habe eine RP1 auf dem der NginX V1.6.2 (Selbstkompilierte Version 1.9.9 funktionerte genauso wenig) als ReverseProxy mit https läuft und alle Anfragen zum RP3 wo fhem läuft weitergibt an FHEMWEB auf Port 8086 (diesen nur für interne Anfragen freigegeben und daher ohne Passwort und ohne Attr. HTTPS.

Hier mal mein Code vom Reverse Proxy

nginx.con (Funktioniert soweit, hier komme ich auch andere Geräte im Net von außerhalb)

worker_processes  1;

events {
    worker_connections  1024;
}


http {
    # HTTP Basic Authentication
    auth_basic "watchdog";
    auth_basic_user_file .htpasswd;


# SSL Zertifikate von letsencrypt
ssl_certificate /etc/letsencrypt/live/Domain.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/Domain.de/privkey.pem;

    server_tokens off;

    include       mime.types;
    default_type  application/octet-stream;

include sites-enabled/*;

    sendfile        on;
   
    keepalive_timeout  65;

    #gzip  on;

# Standard Server Port 80 mit umleitung auf 443
    server {
listen 80 default_server;
        return 301 https://$host;
        }

# Standard Server mit Port 443
    server {
        listen       443 ssl default_server;

#server_name Domain.de;
        server_name  localhost;

         location / {
            root   /var/www/html;
            index  index.html index.htm;
        }
    }
}


fehm.conf

server {
listen 443 ssl;
server_name fhem.*;
location / {
  set $my_http_upgrade "";
  set $my_connection "Connection";
 
  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_http_version 1.1;
  proxy_set_header Upgrade $my_http_upgrade;
  proxy_set_header Connection $my_connection;
 
  if ($http_upgrade = "websocket") {
set $my_http_upgrade $http_upgrade;
set $my_connection "upgrade";
  }

  proxy_pass http://fhem-IP:8086/fhem;
  proxy_read_timeout 20736000;
  proxy_buffering off;
}
}


Habt Ihr einen Tipp für mich was ich noch versuchen könnte?

fiedel

Hi flocki,

bei mir läuft die angehängte, selbst zusammengesuchte config problemlos mit NGINX 1.11.12 (kompiliert) und "standard FHEMWEB". Die aus unserem WIKI habe ich nicht ans Laufen bekommen.  Gleichzeitig können die Spezis ja mal drübergucken, ob grobe Sicherheitsschnitzer drin sind (z.B. ob die freigegebenen TLS- Versionen und Verschlüsselungsalg. noch sicher sind).

Gruß
Frank
FeatureLevel: 6.1 auf Wyse N03D ; Deb. 11 ; Perl: v5.14.2 ; IO: HM-MOD-RPI-PCB + VCCU|CUL 868 V 1.66|LinkUSBi |TEK603
HM: SEC-SCO|SCI-3-FM|LC-SW4-PCB|ES-PMSW1-PL|RC-4-2|SEN-MDIR-O|SEC-WDS-2
CUL: HMS100TF|FS20 S4A-2 ; OWDevice: DS18S20|DS2401|DS2406|DS2423