Persistente OpenVPN Verbindung (Reconnect, mehrere Netzwerkadapter)

CyberNation_RX

Cadet 4th Year
Registriert
Jan. 2016
Beiträge
101
Hallo,

ich habe auf meinen Notebook eine OpenVPN Verbindung zu meinem Server eingerichtet. Diese startet automatisch beim Systemstart und tunnelt den gesamten Internet Verkehr. Dies soll mich unteranderem in fremden Netzwerken etwas schützen.

Das Problem ist, dass der VPN nicht richtig reconnected, z.B. wenn zwischendurch das WLAN mehrmals abbricht oder wechselt. Auch beim wechsel auf das LAN Adapter (eth0) kommt es gelegentlich zu Unterbrechungen. Da die Route 0.0.0.0 noch auf die VPN Gateway zielt, habe ich keine Internet Verbindung mehr (immerhin besser als ungeschützt zu Surfen). Die Lösung ist dann den Dienst (openvpn) neuzustarten, dies ist auf dauer aber sehr umständlich.

In der Client.conf habe ich folgende Werte gesetzt, scheint aber nicht sonderlich zu helfen. :(

persist-key
persist-tun


Hat jemand von euch eine Idee?:)

Mein System:
Linux Mint
Kernel: 3.19
OpenVPN 2.3.2
 
Du kannst in der .conf noch keepalive einstellen. Dabei schickt OpenVPN in regelmäßigen Abständen einen Ping durch den Tunnel damit die Session nicht vom Betriebssystem auf inaktiv gesetzt wird.

Darüberhinaus kommen mir so aus dem Stegreif keine weiteren hilfreichen Optionen in den Sinn. Man könnte über das Management Interface ein Script anbinden, das zyklisch den Status des Servers prüft, ein paar Pings ausführt und dann gegebenenfalls den Tunnel neustartet.

*edit
Hm.. Ich überlege gerade.. Zumindest die zweite Lösung benötigt aber Zugriff auf den OpenVPN-Server, weil dort das Management Interface läuft. Bei zB Cyberghost o.ä. entfällt das natürlich.
Keepalive müsste aber auch in der client.conf funktionieren.

Beispiel für keepalive:

client.conf

keepalive 10 120


Dabei wird alle 10 Sekunden ein Ping abgesetzt und wenn 120 Sekunden keine Antwort kam, ist der Server down.


*edit2:

Ein Script kann man natürlich trotzdem schreiben. Zyklisch im Hintergrund alle x Sekunden Pingen, etc. und je nach Ergebnis dem OpenVPN-Prozess ein entsprechendes Signal schicken (SIGHUP bzw. SIGUSR1 für Tunnelrestart mit/ohne Config neu einlesen)
 
Zuletzt bearbeitet:
Hi Raijin,

Danke für die Tipps, habe jetzt erstmal KeepAlive eingetragen, muss jetzt mal schauen ob es hilft.:)
Habe den OpenVPN Server auf einem VPS eingerichtet, von daher habe ich Vollzugriff. Sollte KeepAlive nicht helfen probiere ich es mal mit dem eigenen Skript.
 
Ok, KeepAlive scheint wirklich zu helfen. Musste die Ping Zeiten allerdings ein wenig reduzieren und bin auf TCP umgestiegen, auch wenn dass evtl. von der Performance nicht so gut ist. :hammer_alt:
 
Stimmt, TCP ist bei VPN suboptimal. Wenn es nu aber wie gewünscht stabil läuft, ist das ja halb so wild.
 
Verdammt so richtig rund läuft es immer noch nicht. Irgendwas muss ich doch falsch eingestellt haben, selbst auf meinem Smartphone läuft OpenVPN stabil und das wechselt auch ständig zwischen WLAN und Mobilfunk.

Hier ist meine OpenVPN Konfiguration:

Code:
client
dev tun
proto tcp
remote 46.xx.xx.xx 9666
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
keepalive 1 15
ca ca.crt
cert client.crt
key client.key
ns-cert-type server
comp-lzo
verb 5

Alternative wäre ein Script in ifup/ifdown welches die IP des tun Adapters vom VPN Server anpingt und bei Fehlschlag den Service neustartet. Scheint mir aber auch nicht so die sauberste Lösung zu sein.
Code:
ping -c 5 10.0.1.6 > echo "ok" || service openvpn restart

Habe ich irgendwas wichtiges in meiner Konfigurationsdatei vergessen? "resolv-retry infinite" ist gesetzt was für Laptops auf der OpenVPN Seite empfohlen wird. "persist-key" und "persist-tun" sind gesetzt, und mittlerweile ist auf keepalive auf Server und Client Seite aktiviert. Ich weiß nicht mehr weiter :(
 
Naja, keepalive tut eigentlich schon genau das. Wenn der Ping nicht durchgeht, sollte der Tunnel mit SIGHUP vollständig neugestartet werden. Gibt es allerdings anderweitige Probleme, während der Ping bzw. keepalive funktioniert, wird das natürlich nicht erkannt.


Ich persönlich habe zwecks externer Steuerung des VPN-Tunnel über eine eigene GUI das Management Interface aktiviert. Dazu fügst du einfach folgende Zeile in die Konfiguration ein:

management localhost port

Statt port musst du natürlich einen Port deiner Wahl eintragen, zB der VPN-Port mit angehängert 0 (zB 1194 -> 11940). Anschließend kannst du via Telnet mit OpenVPN kommunizieren und zB den Status abfragen "state". Als Antwort kommt dann sowas wie "123456789,CONNECTED, SUCCESS, 10.1.2.3". Das kannst du im Skript abfangen und mit "signal SIGHUP" einen vollständigen Reconnect auslösen. Das finde ich deutlich angenehmer als den Dienst radikal abzuschießen und neuzustarten. Oder aber man macht das ganz simpel von außen via "kill -s SIGHUP processid". Wobei da

Das Skript läuft bei mir auf dem OpenVPN-Server unter Linux und nutzt "expect", zur programmatischen Steuerung einer Telnet-Verbindung. Ich kann damit die Client-Liste abrufen, gezielt Clients kicken, das verbose-level ändern sowie den Tunnel neu starten.

Ein Auszug aus meinem Skript:
Code:
#!/usr/bin/expect

#exp_internal 1 # for debug

set timeout 5
set host [lindex $argv 0]
set port [lindex $argv 1]
set command [string tolower [lindex $argv 2]]
set param [lindex $argv 3]
log_user 0

if {[llength $argv] < 3} {
        send_user "Usage: ovpn_management.sh host port command (parameter)\n"
        exit 1
}

proc do_verbose {{level ""}} {
        # Send 'verb $level' command to set specified verbose level. Empty level returns current verbose level.
        send "verb $level\r"

        if {$level == ""} {
                expect {
                        timeout { send_user "Failed to get verbose level\n"; exit 1 }
                        -nocase "error" { send_user "Failed to get verbose level\n"; exit 1 }
                        -nocase -re "success: verb=(\[0-9]+)"
                }
                set level $expect_out(1,string)
        } else {
                # Wait for command response  (success / error)
                expect {
                        timeout { send_user "Failed to set verbose level\n"; exit 1 }
                        -nocase "error" { send_user "Failed to set verbose level\n"; exit 1 }
                        -nocase "success"
                }
        }

        return $level
}


# Start the telnet session
spawn telnet $host $port

# Wait for telnet connection to be ready
expect {
        timeout { send_user "Failed to get command prompt\n"; exit 1 }
        eof { send_user "Failed to connect to management console\n"; exit 1 }
        -nocase ">info:*"
}

switch -glob -- $command {
        -v      -
        -verb   -
        -verbose {
                set result [do_verbose $param]
                if {$result >= 0} {
                        send_user "Verbose level = $result\n"
                } else {
                        send_user "Failed to get verbose level\n"
                }
        }

        default {
                send_user "Unknown command '$command'\n"
                exit 1
        }
}


# Exit telnet session
send "quit\r"
close
Das ist nur ein Auszug aus dem Skript, eine Prozedur, die das Verbose-Level im laufenden Betrieb ändert oder abfragt. Mit "spawn" wird eine Telnet-Sitzung gestartet, Kommandos werden mit "send" abgesetzt und mit "expect" der Output geparsed. Mit "ovpn_management.sh localhost 11940 -v" bekommt man dann das verb-level zurück.
Das kann man auf das Kommando "state" umbauen und so auf zB "CONNECTED", "WAIT", "CONNECTING" o.ä. reagieren, je nachdem in welchem State man reagieren will. Anschließend sendet man das restart-signal (SIGHUP oder SUGUSR1) und los geht's.
 
Wow, vielen Dank Raijin. :)

Die Lösung mit dem Management Interface ist top!!!

you saved my day :heilig:
 
Zurück
Oben