Gerät per VPN und Ethernet-Port mit gleicher IP-Adresse mit Fritzbox verbinden

Klingt gut.

Habe mal angefangen. Nicht über den ggf. unschönen Shellscript-Programmierstil beschweren ;-). Ein neues Image für die Box mit udpsvd muss ich erst noch bauen. Ebenso den Teil auf dem Pi.

Code:
[U][I]check_semaphore.sh[/I][/U]
#!/bin/bash

# calculate time (in seconds) since semaphore file was last accessed
tsla=`expr $(date +%s) - $(date +%s -r semaphore)`

# if file has not been accessed for > 60 seconds, activate VPN connection, otherwise deactivate it
if [ $tsla -gt 60 ]
then
        # heartbeat signal has not been received for >60 seconds, so activate VPN connection
        # (Raspberry Pi not present)
        echo "vpn:settings/connection0/activated=1" | ./set.lua
else
        # semaphore file has been accessed during the last 60 seconds
        # Raspberry Pi is present, deactivate VPN connection
        echo "vpn:settings/connection0/activated=0" | ./set.lua
fi


[U][I]update_semaphore.sh[/I][/U]
#!/bin/sh

touch semaphore

Das Aktivieren bzw. Deaktivieren je nach Timestamp der semaphore Datei klappt damit schon ganz gut, soweit ich sehen kann. Großartig quittieren oder so brauch ich für meinen Anwendungsfall nicht, denke ich.

Womit polle ich auf der Fritzbox? cronjob? Wenn ich gerade nicht verquer denke, müsste es ja theoretisch ausreichen, diesen nur alle z.B. 30 Minuten oder so laufen zu lassen. Ich würde dann bei eintreffendem UDP-Paket im update_semaphore Script dann nicht nur den Timestamp der Datei aktualisieren sondern anschließend gleich das check_semaphore Script ausführen, so dass das Deaktivieren der VPN-Verbindung sofort passiert, da dies "zeitkritischer" ist, als der andere Fall, bei dem die Verbindung wieder aktiviert wird. Wenn ich den Pi von zuhause wieder mit nach Extern nehme, brauche ich die aktivierte VPN-Verbindung ja erst frühestens 30 Minuten später.

Dann werde ich mich demnächst mal mit dem UDP-Teil beschäftigen...
 
Zuletzt bearbeitet:
Ich würde vor der Verwendung von "set.lua" erst noch prüfen, ob es überhaupt notwendig ist ... Hintergrund wäre die Überlegung, daß es u.U. zu einem Abbau mit anschließendem Neuaufbau der Verbindung kommen dürfte/würde, da (meines Erachtens, müßte ich auch noch einmal testen) dort einfach der avmike entsprechend neu getriggert wird (am Ende wohl vom ctlmgr). Solange dabei nicht noch einmal geprüft wird, daß sich der Zustand wirklich ändert, wäre eine regelmäßige Unterbrechung die Folge von wiederholten (unnötigen) Aktivierungen.

Spätestens wenn es unabhängige weitere VPN-Verbindungen gibt (dann muß man ggf. auch den richtigen Index ja erst ermitteln), wird so etwas sonst unangenehm.

Wenn schon Freetz verwendet wird, würde ich am ehesten mit "crond" die regelmäßige Abfrage realisieren - also genau mit dem erwähnten "cron-job". Das halte ich für effektiver als ein Skript in einer Schleife ... wobei es eine Frage der Intervalle der Abfrage ist. Ab 5 Minuten würde ich zum "crond" greifen, darunter zu einer Schleife mit "sleep" (oder zum Patch für die "crontab", damit nicht > 12 Nachrichten pro Stunde alleine für diesen Job das Syslog-Protokoll zumüllen.

Wenn es nur um das Setzen eines einzelnen Parameters geht, ist vermutlich auch "ctlmgr_ctl" schneller und besser (solange die betreffenden Werte darüber erreichbar sind), das Lua-Variableninterface spielt seine Vorteile erst dann aus, wenn es um die Abfrage von vielen Daten geht (eben die Liste aller VPN-Verbindungen anstelle einer einzelnen bzw. sogar nur anstelle eines einzelnen Attributes).

Damit man das auch "von außen" sehen kann, was da mit der VPN-Verbindung gerade passiert, würde ich entweder im Syslog, im AVM-Eventlog oder mit den bunten Lichtern am Router noch den jeweiligen Zustand signalisieren.

Wenn Du tatsächlich die Bash als Shell verwendest (auf der FRITZ!Box und/oder auf dem RasPi), dann könnte man natürlich auch gleich damit das UDP-Handling (beim Senden von Paketen) machen, dann braucht es (vermutlich) kein zusätzliches "netcat".
 
Ich gehe stark davon aus, dass keine weiteren Verbindung hinzukommen (daher auch der fest einprogrammierte Index), aber man weiß ja nie. Klingt auf jeden Fall richtig, zu prüfen, ob sich der Zustand wirklich ändert.

Kenne mich mit ctlmgr_ctl nicht aus, und da deine Scripte so schön funktionieren und ich nicht unbedingt Wert auf "schnell" und "besser" lege, würde mir das so ausreichen. Wenn alles funktioniert und ich unerwarteterweise mal viel Zeit und Lust habe, kann ich dann ja über Optimierungen nachdenken :)

Ein Logging klingt auch nicht verkehrt, ist aber auch maximal nice to have.
 
Ich gehe stark davon aus, dass keine weiteren Verbindung hinzukommen
Das kannst Du für Deine Situation sicherlich am besten einschätzen ... ich will trotzdem noch einmal (für spätere Leser) festhalten, daß die Liste der VPN-Verbindungen auch diejenigen enthält, die für Benutzer eingerichtet werden (hier geht es ja sogar um eine solche) und von diesen dann auf mobilen Geräten verwendet werden können.

Es wäre schon recht ärgerlich, wenn einen entweder eine "zu kurz gedachte Lösung" von der künftigen Verwendung weiterer VPN-Verbindungen dann generell abhält oder wenn man sich dann erst an die Korrekturen macht bzw. diese u.U. sogar vergißt und dann mit "merkwürdigen Phänomenen" bei den VPN-Verbindungen konfrontiert wird.

Das Aufsuchen der richtigen VPN-Verbindung anhand ihres Namens kostet gerade mal 2-3 Zeilen Skript-Code (in Shell) und auch bei der Abarbeitung entstehen fast keine Kosten, wenn man das Abfrageergebnis mehrfach verwendet:
Code:
#! /bin/sh
# Werte auslesen
values="$(echo "VPN=vpn:settings/connection/list(activated,name)" | queries.lua)"
# Namen (erster Parameter) suchen
index=$(echo "$values" | sed -n -e "s|^VPN_\([0-9]*\)_name=\"$1\"\$|\1|p")
# "Indexnamen" für den Zugriff auf die richtige Verbindung ermitteln, wird beim Setzen von Werten benötigt
conn=$(echo "$values" | sed -n -e "s|^VPN_${index}_index=\"\(.*\)\"\$|\1|p")
# aktuellen Status auslesen
state=$(echo "$values" | sed -n -e "s|^VPN_${index}_activated=\"\(.*\)\"\$|\1|p")
Zwar könnte man auch hingehen und mutmaßen, daß der "ctlmgr-Index" so einer Verbindung immer um eins kleiner ist als der Wert, der sich aufgrund meiner Zählung ab "1" ergibt (dann könnte man ja einfach die Zähler in queries.lua anders initialisieren) ... aber der Aufwand zum "Ermitteln" liegt nahe null und wenn sich doch einmal die Syntax im FRITZ!OS ändern sollte, dann funktioniert die Lösung mit dem Auslesen immer noch (ggf. mit angepaßter Abfrage). Diese Zählung habe ich mir auch nicht einfach so ausgedacht, sie ist schon an die Debug-Ausgaben der Lua-Seiten von AVM angelehnt.

Ich würde hier aber ohnehin eher ein neues Skript für "luavar" schreiben, dem man den Namen der Verbindung übergibt und den gewünschten Status der VPN-Verbindung (oder einen definierten anderen Wert, wenn es nur um die reine Abfrage abseits der Notwendigkeit eines bestimmten neuen Zustands geht) und dann wird das alles in Lua abgehandelt - von der Abfrage des aktuellen Zustands über die Prüfung der Notwendigkeit der Änderung bis zu deren Ausführung. Das sähe in Lua dann zum Beispiel so aus:
Code:
#! /bin/luavar

local rc = 0;
local setstate;

local line = io.read("*line");
if (line == nil) then 
	rc = 1
end

local newstate, connection = string.match(line, "(.) (.*)");
if (connection == nil) then
	io.stderr:write("Missing connection name after new state value.\n\n");
	rc = 1;
end

if (newstate == "?") then
	setstate = 0;
else
	setstate = 1;
	if (newstate ~= "0" and newstate ~= "1") then
		rc = 1;
	end
end

if (rc == 1) then
	io.stderr:write("Usage:\n\techo \"state connection\" | vpn_connection.lua\n\n");
	io.stderr:write("Valid 'state' values are: 0 (deactivated), 1 (activated), ? (no change, query only)\n\n");
	io.stderr:write("'connection' has to be the name of an existing VPN connection.\n");
	os.exit(rc);
end

local columns = {};
local query = "vpn:settings/connection/list(name,activated)";
local result = box.multiquery(query);
for i, entry in ipairs(result) do
	if (entry[2] == connection) then
		local oldstate = entry[3];
		local name = entry[1];
		local output = "VPN_INDEX='"..name.."'\nVPN_NAME='"..connection.."'\nVPN_OLDSTATE="..oldstate;
		if (setstate == 1) then
			output = output.."\nVPN_NEWSTATE="..newstate;
			if (oldstate ~= newstate) then
				local cmtable = {};
				table.insert(cmtable, { ["name"] = "vpn:settings/"..name.."/activated", ["value"] = newstate } );
				local err = 0;
				local message = "";
				err, message = box.set_config(cmtable);
				output = output.."\nVPN_RESULT="..err;
				if (err ~= 0 and string.len(message) > 0) then
					output = output.."\nVPN_MESSAGE='"..message.."'";
				end
			end
		end
		print(output);
		os.exit(0);
	end
end

io.stderr:write("A VPN connection with name '"..connection.."' does not exist.\n");
os.exit(1);
Ein großer Teil ist unnötige Verzierung, weil man auch auf ausführliche Erläuterungen bei falschen Angaben verzichten könnte ... auf alle Fälle erzeugt dieses Skript ein paar Zeilen mit den Angaben zu einer VPN-Verbindung, die man in Shell-Code einfach mit einem "eval"-Statement in Shell-Variablen "überführen" und entsprechend weiterverarbeiten kann. Es ist eine Umarbeitung eines Lua-Skripts, welches ich auf mehreren FRITZ!Boxen im Einsatz habe, um meinem Nagios-Server Ergebnisse für Sensoren mit passiven Checks (hier eben für die aktivierten (und aufgebauten) VPN-Verbindungen) zu generieren.
 
Zuletzt bearbeitet:
Danke. Habe es mehr oder weniger mit meiner ursprünglichen Version am laufen. Muss nur die Fritzbox den "UDP-Server" noch beim Booten starten lassen (was ich nach kurzer Recherche vermutlich z.B. in der rc.custom tue?). Sollte dann alles funktionieren und ich wieder etwas Zeit haben, würde ich mir deine flexiblere und sicherlich bessere Lösung dann noch mal genauer ansehen.

Habe noch ein etwas merkwürdiges Phänomen, was ich mir nicht erklären kann. Trotz deaktivierter VPN-Verbindung in der Fritzbox erreiche ich von meinem Desktop-PC den RaspPi nicht, weder Ping, noch das WebIf des openmediavault auf dem Pi sind erreichbar. Auch von der Fritzbox selbst bekomme ich das Gerät nicht angepingt. Meine Synology Diskstation allerdings sieht das Backupziel als online und ich kann Backups auf den dort laufenden rsync-Server schreiben. Hast du dafür eine Erklärung?

Der Pi ist nun aktuell mit manuell konfigurierter WLAN-Verbindung verbunden.
 
PeterPawn: Hast du eine Idee, was die Ursache für mein Problem oben sein könnte? Danke vorab!
 
Das kann alles mögliche sein ... da muß man dann "from the roots" testen, angefangen bei der Prüfung, welche MAC-Adresse der PC da für den RasPi verwendet. Bei der FRITZ!Box ist das noch interessanter ... es wäre denkbar, daß sie selbst ihre Routing-Table gar nicht umgehend ändert, ich habe nur getestet, daß bei mir dann die Antworten auf ARP-Anfragen mit der FRITZ!Box als Proxy anstelle des entfernten Clients aufgehört haben, wenn ich die VPN-Verbindung deaktiviert habe. Wenn die Box die Routing-Tabelle weiterhin verwendet und der PC anstelle einer ARP-Anfrage immer die FRITZ!Box als (vermutliches) Gateway verwendet, dann gehen die Daten auf der FRITZ!Box an das falsche Interface ... dann muß man eben noch "von Hand" (also per Script) auf der FRITZ!Box die Routing-Tabelle vom Eintrag für "192.178.xxx.101/32 dev dsl" befreien.

Aber das ist nur Theorie ... erst einmal muß man die eigentliche Ursache eingrenzen und dazu gehört es nun mal, wie die Pakete auf L2/L3 aussehen, die da beim "ping" nicht ankommen.
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.