Redundante OpenVPN-Verbindungen mit erweitertem Linux-Routing über ein unzuverlässiges Netzwerk

9

Ich lebe derzeit in einem Land, das viele Websites blockiert und unzuverlässige Netzwerkverbindungen zur Außenwelt hat. Ich habe zwei OpenVPN-Endpunkte (z. B. vpn1 und vpn2) auf Linux-Servern, mit denen ich die Firewall umgehen kann. Ich habe vollen Zugriff auf diese Server. Dies funktioniert recht gut, bis auf den hohen Paketverlust bei meinen VPN-Verbindungen. Dieser Paketverlust variiert je nach Zeit zwischen 1% und 30% und scheint eine geringe Korrelation zu haben, meistens scheint er zufällig zu sein.

Ich denke darüber nach, einen Heimrouter (auch unter Linux) einzurichten, der OpenVPN-Verbindungen zu beiden Endpunkten aufrechterhält und alle Pakete zweimal an beide Endpunkte sendet. vpn2 würde alle Pakete von zu Hause an vpn1 senden. Der Rücktransport würde sowohl direkt von vpn1 nach Hause als auch über vpn2 gesendet.

       +------------+
       |    home    |
       +------------+
        |          |
        | OpenVPN  |
        |  links   |
        |          |
     ~~~~~~~~~~~~~~~~~~ unreliable connection
        |          |
+----------+   +----------+
|   vpn1   |---|   vpn2   |
+----------+   +----------+
        |
       +------------+
       | HTTP proxy |
       +------------+
             |
         (internet)

Zur Verdeutlichung: Alle Pakete zwischen Home und dem HTTP-Proxy werden dupliziert und über verschiedene Pfade gesendet, um die Wahrscheinlichkeit zu erhöhen, dass eines von ihnen eintrifft. Wenn beide eintreffen, kann die erste Sekunde stillschweigend verworfen werden.

Die Bandbreitennutzung ist sowohl auf der Startseite als auch auf der Endpunktseite kein Problem. vpn1 und vpn2 liegen nahe beieinander (3 ms ping) und haben eine zuverlässige Verbindung.

Gibt es Hinweise, wie dies mit den in Linux verfügbaren erweiterten Routing-Richtlinien erreicht werden kann?

konrad
quelle

Antworten:

8

Verwenden Sie die Bonding-Infrastruktur auf der Home- und der vpn1-Seite und insbesondere die Einstellung mode = 3, mit der der Datenverkehr auf allen Schnittstellen übertragen wird, die zu einer Bond gehören.

Weitere Informationen zum Konfigurieren der Bindung finden Sie im hervorragenden Handbuch unter http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.37.y.git;a=blob;f = Dokumentation / Vernetzung / Bindung.txt; h = 5dc638791d975116bf1a1e590fdfc44a6ae5c33c; hb = HEAD

jap
quelle
Ich habe dieses Setup getestet und es funktioniert fantastisch. Der Paketverlust wird durch eine redundante Verbindung zu nur einem Server von ca. 5% auf 0,0-0,1% reduziert!
Konrad
7

Ich habe die Antwort von @ user48116 verwendet und es funktioniert wie ein Zauber. Das Setup ist eigentlich ganz einfach!

HINWEIS : Ich habe dies mit zwei Verbindungen zu nur einem Server implementiert, da dies das Problem für mich bereits gelöst hat. Wenn Sie ein Setup mit zwei Servern versuchen möchten, ist es wahrscheinlich am einfachsten, die Portweiterleitung zu verwenden, um den UDP-Port vom zweiten Server zum ersten weiterzuleiten, und dasselbe Rezept wie hier beschrieben zu verwenden. Ich habe das allerdings nicht selbst getestet.

Stellen Sie zunächst sicher, dass Sie einen 2.6-Kernel mit Bonding-Unterstützung haben (Standard in allen modernen Distributionen) und ifenslave installiert haben.

Als nächstes legen Sie dies in Ihrem /etc/rc.local oder einem anderen Ort ab, den Sie bevorzugen, aber stellen Sie sicher, dass es ausgeführt wird, bevor openvpn gestartet wird (da es versucht, sich an bond0 zu binden):

Klient:

modprobe bonding mode=broadcast
ifconfig bond0 10.10.0.2 netmask 255.255.255.0 up

Sie können hier bei Bedarf Routing hinzufügen. Stellen Sie jedoch sicher, dass Sie das richtige Routing auch von der anderen Seite ausführen.

route add -net 10.7.0.0/24 gw 10.10.0.1

Server:

modprobe bonding mode=broadcast
ifconfig bond0 10.10.0.1 netmask 255.255.255.0 up

Erstellen Sie ein Skript /etc/openvpn/tap-up.sh (und vergessen Sie nicht, es als ausführbar mit chmod a + x tap-up.sh zu markieren):

#!/bin/sh
# called as: cmd tap_dev tap_mtu link_mtu ifconfig_local_ip ifconfig_netmask [ init | restart ]
ifenslave bond0 "$1"

Fügen Sie als Nächstes eine Bridge0a.conf und eine Bridge0b.conf zusammen mit einem gemeinsam genutzten Schlüssel zu / etc / openvpn / hinzu. Die Dateien sind für a und b bis auf einen anderen Port gleich (verwenden Sie beispielsweise 3002 für b). Ersetzen Sie 11.22.33.44 durch die öffentliche IP Ihres Servers.

Klient:

remote 11.22.33.44
dev tap
port 3001
rport 3001
secret bridge.key
comp-lzo
verb 4
nobind
persist-tun
persist-key
script-security 2
up /etc/openvpn/tap-up.sh

Server:

local 11.22.33.44
dev tap
port 3001
lport 3001
secret bridge.key
comp-lzo
verb 4
script-security 2
up /etc/openvpn/tap-up.sh

Vergessen Sie nicht, / etc / defaults / openvpn zu bearbeiten, um sicherzustellen, dass Ihre neuen VPN-Konfigurationen gestartet werden. Starten Sie Ihre Computer neu oder laden Sie rc.local und starten Sie openvpn manuell neu.

Jetzt können Sie Ihr Setup testen:

# ping 10.10.0.1
PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data.
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=50.4 ms
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=52.0 ms
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=52.2 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=53.0 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=53.1 ms (DUP!)
--- 10.10.0.1 ping statistics ---
2 packets transmitted, 2 received, +6 duplicates, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 50.428/51.786/53.160/0.955 ms

Wenn alles gut geht und die Zeile gut ist, werden für jedes ICMP-Paket vier Antworten angezeigt: Ihre Pakete werden auf der lokalen Seite dupliziert, und die Antworten auf diese beiden Pakete werden auf der Remote-Seite erneut dupliziert. Dies ist kein Problem für TCP-Verbindungen, da TCP einfach alle Duplikate ignoriert.

Dies ist ein Problem für UDP-Pakete, da es an der Software liegt, Duplikate zu verarbeiten. Beispielsweise liefert eine DNS-Abfrage vier Antworten anstelle der erwarteten zwei (und verwendet die vierfache normale Bandbreite für die Antwort anstelle der zweimaligen):

# tcpdump -i bond0 -n port 53
listening on bond0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:30:39.870740 IP 10.10.0.2.59330 > 10.7.0.1.53: 59577+ A? serverfault.com. (33)
13:30:40.174281 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
13:30:40.174471 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
13:30:40.186664 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
13:30:40.187030 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)

Viel Glück!

konrad
quelle