Einheitliche Adresse des Interfaces ohne Portangabe mit Browserweiche

Begonnen von Grinsekatze, 28 Dezember 2016, 20:44:20

Vorheriges Thema - Nächstes Thema

Grinsekatze

Hallo ins Rund,

ich habe zzt. ein umfangreicheres Projekt vor um die Nutzung von Fhem zu vereinfachen und somit den WAF in meinem Haus zu verbessern.

Dazu möchte ich zum einen den Aufruf des Webinterfaces vereinfachen. Es soll nur noch eine Adresse für alle Interfaces ansteuerbar sein und der Nutzer muss nicht den Port wählen. Eine Browserweiche soll erkennen, mit welchem Gerät das Webinterface aufgerufen wird und entsprechend selbstständig zwischen WEB und WEBphone (und ggf. WEBtablet) weiterleiten. Im Frontend kann dann ggf. ein Button am Seitenende angebracht werden, der das manuelle Wechseln ermöglicht.
Das sollte mit Mod_Rewrite möglich sein?

Weiter werden die o.g. Webinterfaces beschränkt, sodass nicht benötigtes nicht angezeigt wird (z.B. das Input Feld oder der Save Button). Auf einem weiteren Port werde ich dann ein Admin-Frontend einrichten, welches dann z.B. über den URL-Zusatz"/administrator" (z.B. http://meinefhemseite.local/administrator") erreichbar wird. Nicht benötigte Seiten (z.B. ausgeblendete Räume aber auch der direkte Aufruf der "Original-Fhem-Adressen" - z.B. "http://meinefhemseite.local:8083") sollen gänzlich nicht von den Nutzern erreichbar sein.
Das Admin-Interface sollte über einen Reverse-Proxy realisierbar sein. Das ausblenden der Inhalte mit FHEM-Boardmitteln möglich sein. Das händische Aufrufen sollte mit iptables unterdrückt werden können.

Ebenfalls möchte ich, dass wie schon eingangs erwähnt nur der Aufruf einer Webadresse (ohne Portangabe) notwendig ist. Die Browserweiche erledigt den Rest. Jedoch soll dies "hinter den Kulissen" geschehen. Der Benutzer soll also nicht einfach weitergeleitet werden, sondern die Adresse bleibt bestehen (maximal soll zwischen z.B. "http://meinefhemseite.local" und "http://mobile.meinefhemseite.local" differenziert (und weitergeleitet) werden.
Das sollte ebenfalls mit einem Reverse-Proxy möglich sein.

Die Seite wird dann mittels SSL abgesichert. Jeder Client bekommt ein eignes Zertifikat, damit sich der User nicht extra mit Namen und Passwort authentifizieren muss.


Hat das schon einmal Jemand umgesetzt (bzw. in Teilen umgesetzt) und kann mir hier Tipps geben oder auf Stolpersteine hinweisen? Was haltet ihr generell davon?

Danke

felixh

Moin,

Die Ideen die du genannt hast finde ich durchaus richtig.
Im Prinzip kannst du da jeden Reverse Proxy (apache2,ngingx,haproxy) vorschalten.

Ich habe für mich den haproxy davor geschaltet damit ich SSL und authentifizierung machen kann.  zudem wollte ich nur 1 Addresse haben, die Sowohl intern als auch aus dem Internet erreichbar ist. und das klappt ziemlich gut.

Den einzigen Stollperstein den ich bis jetzt hatte war, dass die Zertifakte bzw der Private key nicht mit ECDSA sein Sollten.

Thorsten Pferdekaemper

Hi,
ich habe das ganze mit FTUI gemacht. Auch mit viel Ausblenden und Wahl verschiedener Fhemweb-Instanzen wird das mit Fehmweb wahrscheinlich nicht so der Hit.
...dann lieber gleich einen richtigen Webserver (apache2 etc, wie schon erwähnt) einsetzen und mit FTUI arbeiten.
Gruß,
   Thorsten
FUIP

Grinsekatze

Danke für die Antworten. FTUI hab ich noch nicht mit experimentiert - bis jetzt habe ich hier zum Testen SmartVisu. Aber ich werde mir FTUI mal angucken - es sieht ja schon mal recht interessant aus.

Grinsekatze

Hm, ich habe es mal mit dem Reverse Proxy probiert - zunächst auf meinem Desktop zum Testen.
den Port 8083 kann ich so auch auf das Unterverzeichnis /fhem (meines Desktops) legen. Doch wenn ich die weiteren Ports auf andere Verzeichnisse Mappen möchte, dann erhalte ich bei denen im Browser nur eine 404-Fehlermeldung.

Kann mir hier Jemand behilflich sein?

Ebenfalls habe ich gesehen, dass ich später die eigentlichen Instanzen nicht mit iptables blocken muss, sondern nur das Attribut GLOBAL aus der jeweiligen FEHMWEB-Definition nehmen muss.

meine VHOSTS sieht zzt. so aus:
NameVirtualHost *:80

<VirtualHost *:80>
    ProxyRequests Off
    <Proxy *>
        Order Deny,Allow
        Allow from all
    </Proxy>

    ProxyPass /fhem http://192.168.178.29:8083/fhem
    ProxyPassReverse /fhem http://192.168.178.29:8083/fhem
    <Location /fhem>
        Order Deny,Allow
        Allow from all
    </Location>

    ProxyHTMLURLMap /fhem/   /fhem/
    ProxyHTMLURLMap /   /fhem/

</VirtualHost>

<VirtualHost *:80>
    ProxyRequests Off
    <Proxy *>
        Order Deny,Allow
        Allow from all
    </Proxy>

    ProxyPass /mobile http://192.168.178.29:8086/fhem
    ProxyPassReverse /mobile http://192.168.178.29:8084/fhem
    <Location /admin>
        Order Deny,Allow
        Allow from all
    </Location>

    ProxyHTMLURLMap /fhem/   /mobile/
    ProxyHTMLURLMap /   /mobile/
</VirtualHost>

Atouk

So, wie ich die Sache sehe, kannst Du keine zwei Virtualhosts auf denselben Port lauschen lassen - der erste Virtualhost greift sich schon die ganze Kommunikation, also dürfte vermutlich für den zweiten nichts ankommen (ohne Deine config im Detail analysiert zu haben, wie ich zugeben muss 8) )

Ich vermute, Du nutzt Apache2? Ich frage nur, weil ich den Eintrag in sites-available machen würde. Eine vhosts-Datei ist mir bisher nicht aufgefallen (oder ich habe es falsch vertanden und vhosts ist Deine Datei unter sites-available).

Du schriebst, Du wolltest am Client erkennen, auf welche Instanz es gehen soll - Deinen Ansatz lese ich aber so, dass Du (erstmal?) verschiedene Pfade nutzen willst. Mit mod_rewrite kann man wohl auf beliebige Variablen reagieren, aber das ist mir (momentan) zu aufwändig, mir reichen die verschiedenen Pfade erstmal.

Meine bisherige Lösung sieht so aus:

<VirtualHost *:80>

# Definitionen für meinen regulären Webserver.
# [..] 

# Redirect /fhem_norm auf Port 8083
ProxyRequests off
ProxyPass /fhem_norm/ http://localhost:8083/
ProxyHTMLURLMap http://localhost:8083 /fhem_norm

<Location /fhem_norm/>
        ProxyPassReverse /
# entweder (zumindest auf Raspi3):
        SetOutputFilter INFLATE;proxy-html;DEFLATE
# oder:
#        SetOutputFilter  proxy-html
#        RequestHeader    unset  Accept-Encoding
# - end of "oder" -
        ProxyHTMLURLMap  /      /fhem_norm/
        ProxyHTMLURLMap  /fhem_norm  /fhem_norm
        AddDefaultCharSet UTF-8
# Folgt: Passwortabsicherung über User und Group
        </Location>
</Virtualhost>


Das müsste dann auf beliebige Pfad-Port-Kombinationen erweiterbar sein.

Es sieht soweit alles gut aus, longpoll funktioniert auch, nur werden leider keine SVG-Plots angezeigt. Der Bereich bleibt leer (bzw. es wird auch kein Platz reserviert).

Mit Copy&Paste aus dem Seitenquelltext habe ich ein "no logdevice" als Ausgabe erhalten, Seitenquelltext hiervon zeigt mir einen 404-Fehler. Selbe Untersuchung an der "Originalseite" (ohne redirect, also direkt auf dem Port) deutet darauf hin, dass die SVGs als XML ausgegeben werden - was aufgrund des "SetOutputFilter" nicht durchkommt.
Im Netz findet man einen mod_proxy_xml (oder so ähnlich), den man manuell installieren muss, aber dazu las ich, dass es nicht funktioniere - probiert habe ich es nicht. Vielleicht wäre das ein Ansatz? Oder sich die Output-Filter mal zu Gemüte führen.
Ansonsten habe ich zu XML-Redirect bisher nur wenig gefunden, wollte da momentan auch nicht mehr Zeit investieren.

PS: Wenn ich die Location /fhem auf http://localhost:8083/fhem redirecte und ProxyHTMLInterp On eintrage (aber dafür den SetOuputFilter komplett weglasse), wird alles sauber umgeleitet, also SVGs auch angezeigt. Allerdings schaffe ich das derzeit nur mit dem Originalpfad (/fhem) - Umbenennen klappt nicht. Zudem habe ich - unter bestimmten Umständen, die ich momentan nicht reproduzieren kann (dazu muss ich erst alle Varianten wieder durchprobieren) bei komplexen "Räumen" einen oder mehrere Timeouts pro Aufruf im apache2/error.log. Die Anzeige funktioniert, also ist es eher ein akademisches Problem.

PPS: Aktiviert habe ich aktuell mod_proxy, mod_proxy_html, mod_proxy_http (und mod_sed zum probieren, aber das wäre wieder ein anderer Ansatz - da passt dann irgendwann die work-waf-balance nicht mehr ;) )

Mal sehen, vielleicht findest Du ja noch den Dreh mit den SVFGs...?

Grinsekatze

Hallo Atouk,

ja, das meine ursprüngliche Config fehlerhaft ist habe ich gemerkt. Ich habe vor ein paar Tagen, wie Du auch anmerktest, für ein VHOST mehrere Locations eingetragen (für jeden Pfad). Das funktioniert auch soweit.

Ich teste den Apache-Kram zzt. erstmal auf meinem Windows System. Da heisst die Datei vhosts, entspricht aber der sites-available.

Atouk

Ok, danke für die Klärung. Ich ging von Linux aus wg. iptables (und da ich mehrere Raspis habe, spielt immer einer Testsystem, da ist die Migration auf das "Produktionssystem" noch etwas einfacher).

In Deinem vorletzen Beitrag las ich noch von "404". Prima das es jetzt bei Dir klappt. Bin sehr neugierig: Werden bei Dir denn SVG-Plots angezeigt, und wenn ja, womit hast Du die vollständige "Reverse" Ersetzung hinbekommen?

Ich habe noch eine Weile daran rumgebastelt - ein Fehler (der einzige?) ist definitv, dass die URL bei <embed src="/fhem/SVG_...." nicht durch /fhemnorm/SVG_" bzw. "/fhemnorm/fhem/SVG..." ersetzt wird. Ob es wirklich NUR daran liegt, muss ich mal mit einer eigenen kleinen Seite testen. Momentan finde ich noch nicht raus, was bei FHEM ankommt - schon der proxy-debug-Befehl aus der (m.E. sehr sperrigen) Apache-Doku erzeugt bei mir einen Fehler. Ggf. doch mal in mod_sed einarbeiten und eigene Ersetzungen vornehmen, wenn hier keiner mehr eine zündende Idee hat. :(

Grinsekatze

Also meine Apache Config sieht zzt. noch so aus:
NameVirtualHost *:80

<VirtualHost *:80>
    ServerName smarthome.local
    ServerAlias www.smarthome.local
    ServerAdmin webmaster@smarthome.local

LoadModule proxy_module      modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule headers_module    modules/mod_headers.so
#LoadFile   /usr/lib/libxml2.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule xml2enc_module modules/mod_xml2enc.so

ProxyRequests off
ProxyPass /fhem http://192.168.178.29:8083/fhem
ProxyPass /tablet http://192.168.178.29:8084/fhem
ProxyPass /phone http://192.168.178.29:8085/fhem
ProxyPass /admin http://192.168.178.29:8086/fhem
ProxyHTMLURLMap http://192.168.178.29:8083/fhem /fhem
ProxyHTMLURLMap http://192.168.178.29:8084/fhem /tablet
ProxyHTMLURLMap http://192.168.178.29:8085/fhem /phone
ProxyHTMLURLMap http://192.168.178.29:8086/fhem /admin

<Proxy *>
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
</Proxy>

<Location /fhem>
ProxyPassReverse /
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
  ProxyHTMLURLMap / /fhem/
ProxyHTMLURLMap /fhem/ /fhem/
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>

<Location /tablet>
ProxyPassReverse /
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
  ProxyHTMLURLMap / /tablet/
ProxyHTMLURLMap /fhem/ /tablet/
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>

<Location /phone>
ProxyPassReverse /
Order Deny,Allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable On
  ProxyHTMLURLMap / /phone/
ProxyHTMLURLMap /fhem/ /phone/
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>

<Location /admin>
ProxyPassReverse /
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
  ProxyHTMLURLMap / /admin/
ProxyHTMLURLMap /fhem/ /admin/
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>
</VirtualHost>


Das ist ein erster Versuch. Ich werde noch SSL hinzufügen und den Redirect einpflegen. Auch werde ich die Autorisierung mit Client-Zertifikaten lösen und nicht durch eine Benutzer/Passwort-Liste.

Atouk

Danke für Deine conf., ich habe sie mir mal angeschaut, einiges übernommen und gesehen, dass man offenbar gar kein SetOutputFilter braucht. Aber das Ergebnis ist letztendlich unverändert - leider.

Zudem habe ich gestern entdeckt, dass noch weitere Probleme beim rewriting der URLs auftreten. Und falls ich nicht gerade einen kapitalen Bock beim Test Deiner Einstellungen geschossen habe, vermute ich, dass Du noch mit denselben Problemen kämpfst. Als Versuch habe ich Deine "phone"-Konfig bei mir (etwas abgewandelt) eingetragen:

- Die SVG-Plots funktionieren jetzt. Erstmal toll, aber letztendlich nur deswegen, weil der Link im Seitenquelltest (im embed-Tag) weiterhin auf /fhem/SVG... zeigt statt auf /tablet/fhem/SVG... (oder /tablet/SVG). Sprich: auch wenn Du auf 8084 die Daten holst, werden die SVGs über die 8083 gezogen. Netter Workaround  ;)
(Da ich /fhem/ nicht forwarded habe, sondern dafür /fhem_norm/ nahm, klappte es bei mir bisher nicht).

- Bei der phone-Variante (also Port 8084) werden in der fhem-Voreinstellung die Seitenaufrufe (Räume etc.) über ein Drop-Down realisiert. Auich diese Einträge werden nicht umgeschrieben - die weiteren Seiten werden also nicht mehr über /phone/, sondern über /fhem/ aufgerufen. Also Rückfall auf 8083.

Ich dachte zuerst, es läge daran, dass nur "/fhem/" umgeschrieben wird, aber nicht "/fhem?". Tatsächlich werden aber offenbar zu wenige URLs als solche erkannt, bzw. die rewrite-Rule greift hier nicht. Ein testweiser Brute-Force-Ansatz (ersetze alle "/fhem" ohne zweiten Slash) brachte folglich keinen Unterschied.
Es läuft immer wieder darauf hinaus, dass man einen Ansatz mit mod_sed ausarbeiten muss (oder mod_rewrite, kenne ich beides noch nicht näher), und dann mindestens /fhem/ und /fhem? abfangen muss.

Zur SSL-Absicherung: Ich habe zum Teil Freunde mit einem gewissen "technischen Handycap" auf meinem Webserver. Denen ein Zertifikat zur Installation für den Zugriff zu senden dürfte unweigerlich zur digitalen Vereinsamung führen. Öffentliche Zertifizierungsstelle war mir zu aufwändig - da hätte ich mindestens noch einen Mailserver zur Identifizierung einrichten müssen.

Da aber bei FHEM direkte Eingabe und Ausführung von perl-code möglich ist, ist mir das jetzt auch etwas zu heikel. Da werde ich mir SSL wohl nochmal ansehen müssen.

Grinsekatze

Danke, für das intensive Testen. So genau habe ich es mir jetzt noch nicht angucken können.

Zu SSL: So aufwändig ist es ja nicht, ein eigenes Zertifikat zu installieren. In der Regel nutzen die Leute ja je einen Browser (vom PC oder Smartphone oder Tablett). Also für jedes infragekommende Gerät ein Zertifikat erstellen (das machst Du ja und nicht deine Leute). Die Zertifikate dann per Mail an die Leute verteilen und ggf. eine kurze Installationsanleitung schreiben. Für's iPhone geht es wohl sehr einfach: Eine Email mit dem Cert drin und dieses dann im Mail Programm anklicken und auf Installieren klicken und schon kennt Safari es und es erscheint kein Warnhinweis beim ansurfen der Seite.


Atouk

Du machst Dir ja kein Bild, wie un-affin manche Leute sein können...  ::)

JoeALLb

in nginx könnte man soetwas in die Config integrieren, bei den anderen browsern geht dies sicher ähnlich!

if ($http_user_agent ~* "^iPhoneAgent$") {
   rewrite ^/(.*)$ http://local/fhem-phone/$1 permanent;
}
FHEM-Server auf IntelAtom+Debian (8.1 Watt), KNX,
RasPi-2 Sonos-FHEM per FHEM2FHEM,RasPi-3 Versuchs-RasPi für WLAN-Tests
Gateways: DuoFern Stick, CUL866 PCA301, CUL HM, HMLan, JeeLink, LaCrosse,VCO2
Synology. Ardurino UNO für 1-Wire Tests, FB7270

Grinsekatze

#13
Zum Reverseproxy:

Ich habe eben bemerkt, dass bei meiner Config auch ein bearbeiten der myUtils und ausführen von Befehlen in der Kommandozeile nicht möglich sind. Beim speichern fehlt dann ein Slash zwischen admin und fhem.

Das konnte ich beheben, indem ich Slashes in der vhost-Datei eingefügt habe - hier am Beispiel des admin-"Verzeichnisses":

ProxyPass /admin/ http://192.168.178.29:8086/fhem
ProxyHTMLURLMap http://192.168.178.29:8086/fhem /admin/
<Location /admin/>
ProxyPassReverse /
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
  ProxyHTMLURLMap / /admin/
ProxyHTMLURLMap /fhem/ /admin/
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>


wäre ja auch zu leicht. Nun berücksichtigt er keine css-Dateien mehr.

Grinsekatze

Nachdem ich mich mal wieder mit dem Problem beschäftigt habe um es dann doch mal endlich zu lösen, bin ich nun einen Schritt weiter - danke an dieser Stelle auch an bugster_de, der mich auf die richtige Spur brachte.

Für die zu verwendenden FHEM WEB-Interfaces muss das Attribut webname deklariert werden. Nimmt man z.B. test, dann hört die entsprechende WEB-Instanz fortan auf /test im Browser.

Weiter ist es sinnvoll, den GLOBAL Zusatz der WEB-Interfaces zu entfernen, damit die Seiten nurnoch von dem Localhost aus erreichbar sind (und somit nur für Apache und nicht darauf zugreifende Geräte).

Meine Apache Konfiguration sieht nun so aus:
NameVirtualHost *:80

<VirtualHost *:80>
    ServerName smarthome.local
    ServerAlias www.smarthome.local
    ServerAdmin webmaster@smarthome.local

LoadModule proxy_module      modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule headers_module    modules/mod_headers.so
#LoadFile   /usr/lib/libxml2.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule xml2enc_module modules/mod_xml2enc.so

ProxyRequests off

<Proxy *>
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
</Proxy>

<Location /fhem>
# Within FHEM the WEB-Interface that's listening to Port 8083 must get the attribute webname admin (and no global attribute).
# Ex: define WEB FHEMWEB 8083
# attr WEB webname fhem
ProxyPass http://192.168.178.29:8083/fhem
ProxyPassReverse http://192.168.178.29:8083/fhem
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>

<Location /phone>
# Within FHEM the WEB-Interface that's listening to Port 8084 must get the attribute webname admin (and no global attribute).
# Ex: define WEBphone FHEMWEB 8084
# attr WEBphone webname phone
ProxyPass http://192.168.178.29:8084/phone
ProxyPassReverse http://192.168.178.29:8084/phone
Order Deny,Allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>

<Location /tablet>
# Within FHEM the WEB-Interface that's listening to Port 8085 must get the attribute webname admin (and no global attribute).
# Ex: define WEBtablet FHEMWEB 8085
# attr WEBtablet webname tablet
ProxyPass http://192.168.178.29:8085/tablet
ProxyPassReverse http://192.168.178.29:8085/tablet
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>

<Location /admin>
# Within FHEM the WEB-Interface that's listening to Port 8086 must get the attribute webname admin (and no global attribute).
# Ex: define WEBAdmin FHEMWEB 8086
# attr WEBAdmin webname admin
ProxyPass http://192.168.178.29:8086/admin
ProxyPassReverse http://192.168.178.29:8086/admin
Order deny,allow
# Deny from all
# Allow from 192.168.178
Allow from all
ProxyHTMLEnable on
ProxyHTMLExtended on
ProxyHTMLEvents onclick
RequestHeader unset Accept-Encoding
</Location>
</VirtualHost>


Ich kann also auf die folgenden Seiten zugreifen:

  • smarthome.local/fhem (das ist mein Computer-Client-Interface, wo nur benutzt und nicht verändert werden kann),
  • smarthome.local/phone (das ist mein Smartphone-Client-Interface, wo nur benutzt und nicht verändert werden kann),
  • smarthome.local/tablet (das ist mein Tablet-Client-Interface, wo nur benutzt und nicht verändert werden kann),
  • smarthome.local/admin (das ist mein Admin-Interface, wo verändert werden kann - dafür werde ich nur meinem Computer ein gültiges Zertifikat ausstellen, sobald eingerichtet),