IP default route bei Verbindungsproblemen automatisch ändern

Vielen Dank schon mal für eure informativen Postings.

Ich hab mich zumindest vorerst für die Skript-Lösung entschieden. Die ist nicht perfekt, aber einfach und schnell umzusetzen und für meine Zwecke sollte es auch gut genug sein.
Bash:
#!/bin/sh
#
# Es gibt zwei Gateways zum Internet.
# Dieses Skript prüft via
# ping $TEST_IP_ADDR,
# ob $MAIN_GATEWAY funktioniert und falls nicht, wird das default gateway
# auf $BACKUP_GATEWAY gesetzt.
# Sobald dann $MAIN_GATEWAY wieder funktioniert, wird das default-gateway
# zurück auf $MAIN_GATEWAY gesetzt
# Das Prüfintervall beträgt $DELAY Sekunden
# ----------------------------------
# Konfiguration:
MAIN_GATEWAY="192.168.0.1"
BACKUP_GATEWAY="192.168.0.2"
TEST_IP_ADDR="8.8.8.8"
DELAY=30
# ----------------------------------
# Programm:

log()
{
    logger -p $1 -t "Change-Default-Gateway" $2
}

log-notice()
{
    log local0.notice "$1"
}

log-warning()
{
    log local0.warning "$1"
}

setnewgateway()
{
    route change default $1 >/dev/null
    if [ $? -eq 0 ]
    then
        log-notice "Default Gateway is set to $1"
    else
        log-warning "Setting Default Gateway to $1 is failed."
    fi
    return $?
}

test_connection()
{
    ping -q -c 3 $TEST_IP_ADDR >/dev/null
    return $?
}

while true
do
    CURRENT_DEFAULT_GATEWAY=$(route -4n get default|grep gateway:|cut -w -f 3)
    test_connection
    TEST_IP_REACHABLE=$?
    if [ $TEST_IP_REACHABLE -eq 0 ]
    then
        if [ "$CURRENT_DEFAULT_GATEWAY" = "$BACKUP_GATEWAY" ]
        then
            route delete -host $TEST_IP_ADDR $MAIN_GATEWAY >/dev/null
            setnewgateway $MAIN_GATEWAY
        fi
    else
        if [ "$CURRENT_DEFAULT_GATEWAY" = "$MAIN_GATEWAY" ]
        then
            # sicherstellen das 'ping $TEST_IP_ADDR' über $MAIN_GATEWAY geht:
            route add -host $TEST_IP_ADDR $MAIN_GATEWAY >/dev/null
            setnewgateway $BACKUP_GATEWAY
        fi
    fi
    sleep $DELAY
done
Das Skript ist zwar als Bash angegeben, aber das auch nur, weil ich Syntax-Highlighting haben wollte. Es ist ein POSIX-Shell-Skript und läuft auch ohne das eine Bash installiert ist.

benutzte Befehle: ping, route, logger, grep, cut, sleep

Die Grundidee ist die bereits schon erwähnte, das man eine Testadresse anpingt und wenn das fehlschlägt, setzt man die defaulte-route halt auf ein Backup-Gateway und wenn das Haupt-Gateway wieder funktioniert (also ping durch geht), dann setzt man die default-route wieder zurück aufs Haupt-Gateway.
Jeweilige Änderungen werden im System-Log vermerkt.

Das Skript ist darauf ausgelegt durchgängig zu laufen (hat ne Endlosschleife).
Wenn man die while-Schleife (inkl. sleep) weglässt kann man es aber auch nehmen, um es beispielsweise regelmäßig per CRON-Job auszuführen.

Man muss ein wenig aufpassen, wenn man es zum Beispiel mit Strg-C abbricht. Wenn das Strg-C während des pings kommt, dann wird halt das ping mit Fehler abgebrochen was dann u.U. Nachfolgeoperationen in einer Weise beeinflusst, die man nicht haben will.

Mit dem netstat - Befehl kann man sich auch immer mal die Routing-Tabelle angucken: netstat -rn

Du kannst mehrere Routingtables definieren
Ja. Das wäre auch ne elegante Lösung statt, wie ich es mache, da dem Test-Host ein festen Gateway zuzuweisen.
Das Einzige was man dann halt machen muss ist, die Systemvariable
net.fibs
zu erhöhen (die steht Standardmäßig auf 1 - also nur eine Routing-Tabelle erlaubt).

eignet sich auch der GW/DNS vom jeweiligen ISP der Leitung
Ja. Das ist ne gute Idee. So muss man für den Test-Ping nicht durchs halbe Internet.

unter OpenBSD gibt es ifstated
ifstated könnte man im Prinzip nehmen. Letztlich würde ich damit aber auch nix anderes machen als in meinem einfachen Skript.
Aber ja. Es ist ein interessantes Tool, was ich bis dato noch gar nicht kannte.
 
Es sollte nicht nur ein Testhost angepingt werden, sondern nach dem Ausfallen von mehreren Pong's des ersten Testhosts sollten mehrere Ping's an den zweiten Testhost versendet werden. Wenn auch diese Ping's an den zweiten Testhost unbeantwortet bleiben, darf von einem Ausfall des Internetanschlusses ausgegangen werden und eine Umschaltung der Defaultroute durchgeführt werden.

Siehe dazu die bereits vorgängig verlinkte Anleitung zum Routerbetriebssystem LCOS => /Setup/WAN/Polling-Tabelle/

Mit der präsentierten Shellskriptlösung würde ein Serverausfall oder eine Serverwartung zu einer unnötigen Umschaltung der Defaultroute führen. Was kaum erwünscht ist. In der präsentierten Shellskriptlösung fehlt klar die Redundanz:

Weiter rate ich von der Verwendung von Anycast-Adressen ab (IP: 8.8.8.8).

Aktuell verwende ich für die Leitungsausfallerkennung mit ICMP-Polling (Ping/Pong) zwei möglichst verschiedene, weit auseinander liegende und voneinander unabhängige Server:
tick.switch.ch130.59.31.31
pop.gmx.net212.227.17.185
 
Es sollte nicht nur ein Testhost angepingt werden, sondern nach dem Ausfallen von mehreren Pong's des ersten Testhosts sollten mehrere Ping's an den zweiten Testhost versendet werden. Wenn auch diese Ping's an den zweiten Testhost unbeantwortet bleiben, darf von einem Ausfall des Internetanschlusses ausgegangen werden und eine Umschaltung der Defaultroute durchgeführt werden.

Siehe dazu die bereits vorgängig verlinkte Anleitung zum Routerbetriebssystem LCOS => /Setup/WAN/Polling-Tabelle/

Mit der präsentierten Shellskriptlösung würde ein Serverausfall oder eine Serverwartung zu einer unnötigen Umschaltung der Defaultroute führen. Was kaum erwünscht ist. In der präsentierten Shellskriptlösung fehlt klar die Redundanz:

Weiter rate ich von der Verwendung von Anycast-Adressen ab (IP: 8.8.8.8).

Aktuell verwende ich für die Leitungsausfallerkennung mit ICMP-Polling (Ping/Pong) zwei möglichst verschiedene, weit auseinander liegende und voneinander unabhängige Server:
tick.switch.ch130.59.31.31
pop.gmx.net212.227.17.185

Könntest du bitte keine hier im Forum allgemein bekannten Begrifflichkeiten erklären und Verlinken.

Wir sind hier nicht im pc-anfaenger-forum - jeder was was ein Ping und redudanz ist
 
Es sollte nicht nur ein Testhost angepingt werden, sondern nach dem Ausfallen von mehreren Pong's des ersten Testhosts sollten mehrere Ping's an den zweiten Testhost versendet werden.
Du hast Recht. Das war auch so ein bisschen der Sinn für die Funktion test_connection()
Die besteht ja im Grund nur aus einer Zeile aber der Hintergrund war, das man die mit einem besseren Test befüllen kann als einfach nur einen einfachen ping zu machen.

Siehe dazu die bereits vorgängig verlinkte Anleitung zum Routerbetriebssystem LCOS
Mein Skript hat ganz klar seine Unzulänglichkeiten und ist sicher nicht als enterprise-ready-Lösung gedacht.
Es ist aber einfach, kurz und leicht verständlich. Man braucht dafür auch nichts konfigurieren oder installieren. Man kopiert es einfach auf den entsprechenden Rechner passt ggf. die drei IP-Adressen an und führt es aus. Fertig.

Weiter rate ich von der Verwendung von Anycast-Adressen ab
Ich hatte jetzt 8.8.8.8 auch nur beispielhaft verwendet. Ich fand die Idee mit dem "DNS-Server vom Provider" und ähnliches viel netter.
Aber was spricht jetzt eigentlich gegen Anycast-Adressen? Spontan würde ich sagen, die sind sogar ganz gut geeignet, weil man da gewisse Redundanz "automatisch" drin hat.
 
Aber was spricht jetzt eigentlich gegen Anycast-Adressen? Spontan würde ich sagen, die sind sogar ganz gut geeignet, weil man da gewisse Redundanz "automatisch" drin hat.
Ne, weil das immer auf den kürzesten Pfad geht, auch aus Sicht des Rückwegs der Gegenstelle und weil das meist ein paar viele Server auf einer IP sind. Sprich, wenn du die 8.8.8.8 via route1 dauerbepingst, bleibt die 8.8.8.8 für deine Clients auf route1 festgenagelt, auch wenn du gerade auf route2 geswitched hast.
Das wird dann doof, wenn man z.B. irgendein dubioses IoT hat, das 8.8.8.8 als DNS für sich fest nutzt und man das nicht ändern kann, weil halt Billigplasteding.

Du brauchst pro Leitung/Route eine andere Pingziel-IP und bestenfalls ist das eine, die deine Clients hinterm Router niemals erreichen müssen.

Der Vorteil wenn man den jeweiligen GW oder DNS vom ISP nimmt ist, dass man diese IPs (meist) nicht vom anderen Anbieter erreichen kann (ein Fallstrick weniger), sowie kürzeste RTT (Interessant, wenn man viele Leitungen noch komplexer schalten möchte bzw. "Wechsle auf Leitung 27, Leitung 1-26 hat unterirdische Pingzeiten") . Der Nachteil ist halt, dass man dann nicht erkennt, ob der ISP eventuell ein Problem bei sich hat. Dürfte man aber vernachlässigen können, so selten wie das passiert. :)

@GrandDixence
Wirklich aus Interesse: Warum verlinkst du auf Wikipedia bez. ping und Redundanz?
 
@Andy_m4
Nettes script, sowas schwebte mir auch vor...aber ich und shellscripte das geht gar nicht; lieber bastel ich was in c, python oder sogar java oder irgendeiner anderen obskuren Sprache.

@mr44er
das mit dem hardcodierten DNS wäre mir wahrscheinlich auch erst aufgefallen, wenn ich darüber stolpere.... Ist ein sehr guter Punkt, den ich im Hinterkopf behalten sollte.
 
aber ich und shellscripte das geht gar nicht
Ja. Ich mag Shell-Skripte auch nicht sonderlich, weil man dort halt nicht den Komfort hat, den man bei "normalen" Programmiersprachen hat (nicht umsonst kommt ja heutzutage häufig Python und Co zum Einsatz, für Dinge die man früher mit Shell-Skripten gelöst hat). Obendrauf kommen noch so Hacks wie grep und cut, um irgendwelche Ausgaben zu "parsen" ('blind ausschneiden' triffts besser), was auch nicht sehr sauber und potentiell fehleranfällig ist.

Auf der anderen Seite ist das Shell-Skript aber sehr einfach. Die Frage ist, will ich mir irgendwie ein Python installieren müssen, nur um so ein Skript auszuführen. Vom RAM-Bedarf mal ganz abgesehen. Denn da musst Du halt immer ein Python-Interpreter (oder bei Java gar ne JVM) mitlaufen lassen, für eine eigentlich einfache Aufgabe.

Und ja. C würde gehen da ein C-Compiler eh bei FreeBSD mit installiert ist und man das auch hochgradig effizient wäre. Allerdings konnte ich das Shell-Skript quasi einfach mal eben schnell runterschreiben. Es ist im Grunde die Manifestation dessen, was ich sonst manuell gemacht hab. Das in ein C-Programm zu gießen hätte mich spürbar mehr Zeit gekostet.
Wenn Dir C lieber ist: Feel free to do it. :-)
 
Mein Verhältnis zu shellscripten ist noch viel viel schlimmer...ada, eiffel oder cobol sind wahrscheinlich freundlicher zu mir als sh.
Das Zeitproblem ist auch immer die Entscheidung für nicht-C...deshalb ja hier im Verlauf auch meine Idee mit dpinger, was letzlich insgesamt dasselbe macht wie dein script (mit einem sehr sehr minimalen "alarm-script").
 
Was ich noch vergessen hatte zu erwähnen: Falls die Backupleitung volumenbasiert ist, sollte man im Hinterkopf haben, dass sich die pings doch läppern. Bei 'nur' alle zehn Sekunden brät das regelmäßig in Richtung 1GB/Monat weg (ich pinge den DNS von o2-de 62.109.121.17), aber gut ich habe noch CARP, also doppelt. Und entgegen der Erwartung da es ja noch deren eigenes Netz ist, wird das trotzdem abgezogen. :rolleyes:
 
Zurück
Oben