Forum: PC-Programmierung DNS als Weiche zwischen zwei Servern verwenden


von Philipp K. (philippk) Benutzerseite


Lesenswert?

Hallo

Ich habe folgende Ausgangslage:

1) Ich habe ein Embedded Linux Gerät mit einem Webserver am laufen 
(Server).

2) Zusätzlich habe ich ein weiteres Gerät (Client) welches über Ethernet 
meistens direkt am Server angeschlossen ist, kann aber auch über 
Switches etc. weiter entfernt sein.


Auf dem Client läuft ebenfalls ein Embedded Linux. Der Client hat nur 
einen Touchscreen, keine weiteren Bedienmöglichkeiten. Darauf ist ein 
Browser installiert (voraussichtlich Chromium) welcher im Kiosk-Mode 
läuft, hat also keinerlei zusätzliche Bedienung.

Wenn der Client keine Verbindung zum Server aufbauen kann, soll dies dem 
Benutzer optisch ansprechend mittels einer Webseite gezeigt werden. Auf 
keinen Fall darf jemals eine Fehlerseite z.B. ERR_NAME_NOT_RESOLVED des 
Browsers angezeigt werden. Denn ohne F5 Taste zum aktualisieren kommt 
man von einer solchen Seite nie wieder weg. Stattdessen soll eine andere 
lokal auf dem Client gespeicherte Webseite angezeigt werde z.B. mittels 
eines weiteren lokalen Mini-Webservers auf dem Client.

Meine Idee ist es nun, auf dem Client einen DNS-Dienst so zu 
konfigurieren, dass dieser die Anfragen des Browsers an den Server 
weitergibt falls dieser erreichbar ist. Falls nicht, leitet er diese auf 
den lokalen Webserver weiter. Der DNS-Dienst muss zwingend alle Anfragen 
auflösen, damit der Browser immer eine Webseite zur Anzeige bekommt und 
nie eine Fehlerseite anzeigt.


Da ich mich mit Netzwerken nicht so gut auskenne ist nun meine Frage an 
euch, ob jemand einen eleganteren Weg kennt wie man ein solches Problem 
lösen könnte.


Danke im Voraus und Grüsse
Philipp

von Jan H. (j_hansen)


Lesenswert?

Philipp K. schrieb:
> Wenn der Client keine Verbindung zum Server aufbauen kann, soll dies dem
> Benutzer optisch ansprechend mittels einer Webseite gezeigt werden. Auf
> keinen Fall darf jemals eine Fehlerseite z.B. ERR_NAME_NOT_RESOLVED des
> Browsers angezeigt werden. Denn ohne F5 Taste zum aktualisieren kommt
> man von einer solchen Seite nie wieder weg.

Und wie kommst du von der Fehlerseite wieder weg?
Was willst du denn überhaupt machen? Eine Webseite anzeigen und 
periodisch neu laden, ohne sonstige Eingriffsmöglichkeiten des 
Benutzers? Dann lade den Seiteninhalt über JavaScript und schaue nach, 
ob was sinnvolles zurückkommt.

von Michael (Gast)


Lesenswert?

DNS Anfragen werden üblicherweise vom Betriebssystem gecacht.
Das bedeutet Du machst eine Auflösung, Dein Server ist gerade da, gibt 
dem Client seine IP zurück und beim nächsten Aufruf der Seite macht der 
Client nicht nochmal eine DNS-Anfrage weil er die Antwort ja schon 
kennt.

Was Jan vorschlägt klingt vernünftiger ...

von yesitsme (Gast)


Lesenswert?

Du könntest einen Proxy verwenden, der im Fehlerfall eine andere Seite 
zurückgibt.

von Noch einer (Gast)


Lesenswert?

Das wird so nicht zuverlässig funktionieren. Wenn der Browser die IP 
hat, fragt er nie wieder beim DNS nach. Beim Browserstart funktioniert 
alles. Eine Stunde später fällt der Server aus. Und dein Browser benutzt 
weiter die alte IP.

Ich würde es direkt im HTML/Javascript machen. Entweder traditionell mit 
Frames. Nur der innere Frame wird neu geladen. Die Navigation bleibt 
stehen. Kannst auch einen Javascript-Mechanismus bauen; wenn sich der 
innere Frame nicht bei der Navigation anmeldet, wird nach einem Timeout 
eine Fehlerseite geladen.

Oder du machst es modern als Single-Page-Webapp. Es wird nur eine 
einzige Htmp-Seite geladen. Die holt nur Rohdaten vom Server und ändert 
mit Javascript ihren Inhalt.

von trostpreis (Gast)


Lesenswert?

Das könnte man gut mit Python lösen, mal schnell "hingerotzt":

-------- snippet on ----------
1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
4
import urllib2, os
5
6
while 1
7
8
    try:
9
        seite = urllib2.urlopen(http://pfad/zum/server/seite.htm).read()
10
    except:
11
        seite = open(/home/user/hilfsseite.htm).read()
12
13
    os.system("/usr/bin/chromium")
-------- snippet off ----------

Die Hilfsseite liegt auf dem Client, Dein Browser fragt immer nur die 
lokale Hilfsseite ab. Wird komplizierter bei mehreren Seiten, dann 
müsste die Hauptseite auf dem Server absolute Pfade zu den anderen 
Seiten auf dem Server enthalten anstelle von relativen Pfaden.

von trostpreis (Gast)


Lesenswert?

P.S. da muss natürlich noch rein, dass die Variable "seite" auf dem 
Client gespeichert wird, etwa mit
1
    html = open(path_data, "w")
2
    html.write(seite)
3
    html.close()

von trostpreis (Gast)


Lesenswert?

noch ein PS: hinter das "while 1" gehört natürlich ein Doppelpunkt:
1
while 1:

von Horst (Gast)


Lesenswert?

Stabil und flixibel wird das nur mit einem lokalen Proxy laufen.

von Philipp K. (philippk) Benutzerseite


Lesenswert?

Hallo zusammen

Dass das mit DNS nicht so richtig funktioniert leuchtet mir nun ein.
Die Python Lösung hat meiner Meinung nach den Nachteil, dass diese nicht 
mehr greift, sobald die Verbindung einmal zustande gekommen ist.

Bei der Javascript/Frames Lösung habe ich ein bisschen bedenken, da die 
Webseite auf dem Server bereits diverse Javascripts & AJAX verwendet. Ob 
das Konfliktfrei funktionieren wird weiss ich nicht.

Die Variante mit einem Proxy gefällt mir bis jetzt am besten. Ich werde 
das mal mit squid versuchen, oder gibt es etwas einfacheres?

von Manfred (Gast)


Lesenswert?

Noch einer schrieb:
> Das wird so nicht zuverlässig funktionieren. Wenn der Browser die IP
> hat, fragt er nie wieder beim DNS nach.

Der Browser wird keine IPs cachen, das macht das Betriebssystem - bei 
Windows abzufragen mit "ipconfig /displaydns".

Ich hoffe doch, dass dieser Cache die Lifetime "TTL" berücksichtigt, der 
DNS also eine TTL von nur wenigen Sekunden liefern sollte.

von bluppdidupp (Gast)


Lesenswert?

Manfred schrieb:
> Der Browser wird keine IPs cachen, das macht das Betriebssystem - bei
> Windows abzufragen mit "ipconfig /displaydns".

Mindestens Chrome cached definitiv selbst DNS-Einträge unabhängig vom 
Betriebssystem.

von trostpreis (Gast)


Lesenswert?

noch eine Lösung:

bluppdidupp schrieb:
> Mindestens Chrome cached definitiv selbst DNS-Einträge unabhängig vom
> Betriebssystem.

Nö, gerade ausprobiert:

mit Chromium www.mikrocontroller.net aufgerufen, Seite reloaded: geht

/etc/hosts manipuliert:
127.0.0.1 www.mikrocontroller.net

Seite reloaded: geht nicht

/etc/hosts manipuliert (auskommentiert):
# 127.0.0.1 www.mikrocontroller.net

Seite reloaded: geht nicht

Daraus folgt: wenn man per Programm in einer Dauerschleife (z.B. alle 30 
Sekunden) die /etc/hosts manipuliert (abhängig, ob Server erreichbar 
oder nicht), kann das vom TE erstellt Problem gelöst werden.

von trostpreis (Gast)


Lesenswert?

Korrektur:

nach dem auskommentieren geht der Zugriff auf www.mikrocontroller.net 
wieder (habe die Zeile kopiert, aber nicht korrigiert)

von bluppdidupp (Gast)


Lesenswert?

Keine Ahnung ob Chrome und Chromium da abweichend sind oder was die 
genauen Umstände sind, ich bin bei Chrome unter Windows auf jedenfall 
davon auch betroffen:
https://superuser.com/a/203702

von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

Der dnsmasq vom Android liest die /system/etc/hosts genau
einmal beim Starten. Danach kann Mann da schreiben was Mann will...

Was zuverlaessig funktioniert, ist per iptables den Request
im Fehlerfall an die passende Adresse zu schicken.
Im Beispiel lauscht lokal auf dem Androiden ein Webserver
auf dem Port 1080.
1
su -c iptables -t nat -A OUTPUT -p tcp -d 1.0.0.1 --dport 80 -j DNAT --to-destination 127.0.0.1:1080

Das su muss Mann sich selber kompilieren. Die su aus Androidpaketen
kennen die Option "-c" oft nicht.

Ein:
1
su -c iptables -t nat -D OUTPUT 1

stellt die normalen Verhaeltnisse wieder her.
Ein Script das die Erreichbarkeit des richtigen Servers
pollt, schaltet dann dazwischen um.

von c.m. (Gast)


Lesenswert?

trostpreis schrieb:
> Das könnte man gut mit Python lösen, mal schnell "hingerotzt":
>
1
> 
2
> #!/usr/bin/python
3
> # -*- coding: utf-8 -*-
4
> 
5
> import urllib2, os
6
> 
7
> while 1
8
> 
9
>     try:
10
>         seite = urllib2.urlopen(http://pfad/zum/server/seite.htm).read()
11
>     except:
12
>         seite = open(/home/user/hilfsseite.htm).read()
13
> 
14
>     os.system("/usr/bin/chromium")
15
> 
16
>

ich würde das ähnlich machen - an der netzwerkconfig rum zu schrauben 
ist keine gute idee, denn das netzwerk ist nicht der grund warum der 
server nicht erreichbar ist.
es ist, wie es in obigem code beschrieben wird: eine resource soll 
geladen werden, und wenn das nicht funktioniert soll eine meldung 
ausgegeben werden. wenn es ein normales GUI programm wäre, und eine 
datei geöffnet werden sollte, würde auch keiner auf die idee kommen im 
fehlerfall fix mal einen hardlink zu setzen um die nicht ladbare datei 
durch eine dummy datei zu ersetzen.

meine idee wäre lokal auf dem client einen http-server mit php zu haben, 
die index.php hat im html-header "reload alle 10 sec" stehen (genaue 
syntax weiß ich nicht auswendig, bin kein web entwickler :).
im php-script wird versucht die externe resource zu laden, und wenn das 
nicht funktioniert, wird eine interne resource geladen, oder 
fehlermeldung ausgegeben.
der browser auf dem client lädt die index.php einmal, und dann halt 
immer wieder - der inhalt der seite wird durch das php-script bestimmt.

und noch was zu obigem code: es wäre von vorteil wenn man der 
urllib-klasse sagen könnte wie lange der timeout sein darf, nicht dass 
das laden der server-seite 30 sekunden lange versucht wird.

von trostpreis (Gast)


Lesenswert?

c.m. schrieb:
> und noch was zu obigem code: es wäre von vorteil wenn man der
> urllib-klasse sagen könnte wie lange der timeout sein darf, nicht dass
> das laden der server-seite 30 sekunden lange versucht wird.

urllib2 kann ein timeout: 
https://stackoverflow.com/questions/2712524/handling-urllib2s-timeout-python

von c.m. (Gast)


Lesenswert?

trostpreis schrieb:
> c.m. schrieb:
>> und noch was zu obigem code: es wäre von vorteil wenn man der
>> urllib-klasse sagen könnte wie lange der timeout sein darf, nicht dass
>> das laden der server-seite 30 sekunden lange versucht wird.
>
> urllib2 kann ein timeout:
> https://stackoverflow.com/questions/2712524/handling-urllib2s-timeout-python

hab ich mir gedacht, ist ja auch sinnvoll :)

von Imonbln (Gast)


Lesenswert?

Abgesehen davon das ich $irgendwas mit Chrom nicht mehr instinktiv als 
embedded ansehen würde (vielleicht haben sich die Zeiten ja geändert).

Möchte ich nochmal die Lösung mit den Proxy ansprechen. Klar kann man 
das sicher auch in Python machen und das wäre wahrscheinlich auch mein 
erster ansatz das mit den try/except umzusetzen.
Aber wenn es ein Produkt werden soll, wäre meine Empfehlung den Nginx, 
alternativ den lighttpd als Proxy auf den Client zu installieren.
Beide habe ich schon erfolgreich in embedded Projekten eingesetzt und 
hätten im Vergleich zu der Python Lösung den charmanten Vorteil nur noch 
Konfiguriert werden müssen.
Beide vor allen aber der Nginx haben sich schon 1000 Fach als Proxy 
bewährt. Bei der Python Lösung fängst du von 0 an und musst selbst 
erstmals alle Fehler und Fallen finden und beheben.
Abgesehen davon hat so eine Proxylösung, egal ob Homebrew Python oder 
Nginx denn Vorteil das auch fälle wie DNS geht, Webserver weg gleich mit 
gecovert werden.

von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

> an der netzwerkconfig rum zu schrauben

Das tut es ja nicht.
Der Request wird von der nat/Output-Regel nur an ein anderes Ziel
geschickt. Das funktioniert in einer anderen Anwendung schon heute
bestens und zuverlaessig.
An der Netzwerkkonfiguration wird dadurch nichts geaendert.
Irgendwelche Cachingprobleme treten dabei nicht auf.
Die Dummy/Fehler-Webseite muss natuerlich auch passende
http-Parameter zurueckgeben.

Kommerzielle Loadbalancer machen das auch nicht viel anders.

Wer aber nur in PHP frickeln kann, wird es wohl damit versuchen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.