Wie verwende ich Namespaced-OpenVPN für VPN pro Anwendung?

Wie verwende ich Namespaced-OpenVPN für VPN pro Anwendung?

Dies ist wahrscheinlich eher eine Anfängerfrage, aber ...

Ich verwende Ubuntu 18.04.3 LTS und habe eineVPNdie ich für einige Anwendungen verwenden möchte. Ich habe mirnamespaced-openvpnund es funktioniert! Der Vorbehalt besteht darin, dass ich mich nicht lokal mit dieser Anwendung verbinden kann (zu Verwaltungszwecken).

Gibt es eine Möglichkeit, einen bestimmten Port innerhalb des VPN-Tunnels an den lokalen Host weiterzuleiten?ohne dass der VPN-Tunnel sie für andere Zwecke verwendet und dadurch zu viele Informationen preisgibt?

Was ich bereits kann:

  • laufennamespaced-openvpn-Skript:sudo ./namespaced-openvpn --namespace vpn --config /etc/openvpn/vpn-xxxxx.ovpn
  • Anwendung innerhalb des Netzwerk-Namespace ausführen:sudo ip netns exec vpn application

Was ich erreichen möchte:

  • Verbindung zur Anwendung herstellen, die innerhalb des VPN-Tunnels (z. B. an Port 1234) vom realen lokalen Host ( enp3s0Ethernet-Adapter) aus gestartet wurde
  • Leiten Sie diesen Port so weiter, dass ich von meinen anderen Computern in meinem LAN darauf zugreifen kann

Antwort1

Viele Jahre zu spät, aber falls jemand darauf stößt, wie ich es mir in den letzten paar Tagen gewünscht hätte,
hoffe ich, dass es jemandem hilft.

Zunächst gibt es hier namespaced-vpn, das etwa 90 % der Arbeit übernimmt, um alles zum Laufen zu bringen.
https://github.com/slingamn/namespaced-openvpn

Und hier ist eine Antwort auf eine Frage, die fast genau dieser ähnelt und mir sehr geholfen hat, obwohl ich nicht verstanden habe, was und warum die Dinge getan wurden. https://unix.stackexchange.com/questions/391193/how-to-forward-traffic-between-linux-network-namespaces

Ich werde versuchen, anhand der Informationen, die ich bei meinen Recherchen gefunden habe, zu erklären, was ich nach vielen Versuchen und Irrtümern verstanden habe.
Der relevanteste Teil für die Weiterleitung von Verbindungen zu Ihrem Dienst (nicht vom PC, auf dem der Dienst ausgeführt wird) ist meiner Meinung nach dieser (beachten Sie das Ausrufezeichen nach PREROUTING):

iptables -t nat -A PREROUTING ! -s 10.0.0.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2

Wobei 10.0.0.0/24die IP-Bereiche repräsentiert, die NICHT weitergeleitet werden sollen.
Dies dient hauptsächlich dazu, eine Routing-Schleife zu verhindern, bei der alle über das 10.0.0.0/24Subnetz erreichbaren Dienste zu sich selbst zurückgeleitet werden.
--dport 80 dient nur zur Weiterleitung von Paketen, die Port 80 suchen, also eine Webserververbindung.
10.0.0.2ist die veth-Schnittstelle, die INNERHALB des Namespace verschoben wurde, in dem Ihr Server ausgeführt wird.
Dies sorgt dafür, dass eingehende Pakete, die NICHT aus 10.0.0.0/24dem Subnetz kommen und den Dienst über Port 80 suchen, ihre Ziel-IP in übersetzt bekommen 10.0.0.2. Beispiel: 192.168.1.200:80wird zu 10.0.0.2:80, was vermutlich die Schnittstelle innerhalb des Namespace ist, in dem sich Ihr Server befindet.

Ich habe mehrere VPN-Tunnel in mehreren Namespaces eingerichtet und in Betrieb. Wenn ich die PREROUTING-Regel nicht zu meinen iptables hinzufüge, kann ich von außerhalb meines PCs in meinem LAN nicht auf die Ressource zugreifen.

Wenn Sie von Ihrem eigenen PC aus darauf zugreifen möchten, müssen Sie eine Regel wie die folgende hinzufügen:
iptables --table nat --append OUTPUT --destination 192.168.1.2 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
Wenn Sie also in den Browser des PCs, auf dem sich der Server befindet, eingeben, 192.168.1.2um auf Ihren Server zuzugreifen, wird dies stattdessen dorthin weitergeleitet 10.0.0.2.

Ich werde versuchen, einen Teil meines Setups zu erklären ...

Beispiel-Namespace:ip netns add ns_example

Erstellen Sie ein Veth-Paar. Eine Seite bleibt im Root-/normalen Namespace (ich nenne das host), die andere Seite wechselt in den Namespace mit VPN.
ip link add dev ihost type veth peer name ivpn

Verschieben Sie die VPN-Seite des Veth-Paares in den Zielnamespace:
ip link set dev ivpn netns ns_example

Weisen Sie dem von Ihnen erstellten Veth-Paar IPs zu.

Ich verwende /32, weil ich nur genau diese IP zuweisen möchte und keinen Bereich. Andernfalls werden beim Hochfahren der Geräte automatisch einige Routen in meine ip routeTabelle eingefügt, was mein Routing für meine anderen Namespaces durcheinander bringt.

Der Hostseite zuordnen.
ip addr add 10.0.0.1/32 dev ihost

Um die Zuweisung zur VPN-Seite vorzunehmen, die in den Namespace verschoben wurde, müssen Sie dem Befehl Folgendes voranstellen:
ip netns exec TARGET_NAMESPACE

So weisen Sie der VPN-Seite eine IP zu:
ip netns exec ns_example ip addr add 10.0.0.2/32 dev ivpn

Rufen Sie jetzt die Schnittstellen auf.

ip link set dev ihost up

ip netns exec ns_example ip link set dev ivpn up

Hier füge ich Routen und iptables hinzu, um den Datenverkehr zwischen ihnen fließen zu lassen.
Um vom Stamm-Namespace zur VPN-Seite () zu gelangen 10.0.0.2, verwenden Sie die Schnittstelle ihost und schreiben Sie die Quelladresse in die Stamm-Namespace-Seite ( 10.0.0.1) um.
ip route add 10.0.0.2/32 dev ihost src 10.0.0.1

Machen Sie genau dasselbe, aber aus der entgegengesetzten Perspektive innerhalb des VPN-Namespace.
ip netns exec ns_example ip route add 10.0.0.1/32 dev ivpn src 10.0.0.2

Jetzt füge ich dieselben Operationen hinzu, iptablesdie zwar getrennt sind ip route, aber ähnliche Aufgaben erfüllen.

10.0.0.2Die Quelladresse aller Pakete wird umgeschrieben in10.0.0.1
iptables --table nat --append POSTROUTING --destination 10.0.0.2/32 --jump SNAT --to-source 10.0.0.1

Genau dasselbe, aber entgegengesetzte Perspektive und innerhalb des Namespace.
ip netns exec ns_example iptables --table nat --append POSTROUTING --destination 10.0.0.1/32 --jump SNAT --to-source 10.0.0.2

Wenn ich das richtig verstehe, dienen die Umschreibungen der Quelladresse nur dazu, sicherzustellen, dass das Paket weiß, wie es wieder aus dem Namespace herauskommt und umgekehrt.

Jetzt zum Beispiel: Um auf eine Torrent-Web-Benutzeroberfläche im Namespace auf Port 8080 zuzugreifen, mache ich Folgendes.
Jedes Paket, das an meine LAN-IP geht (Beispiel: Ich gebe es 192.168.1.2:8080im Browser ein). Es wird das Ziel in den Namespace umschreiben, in dem mein Torrent-Client läuft (Beispiel: 10.0.0.2).
iptables --table nat --append OUTPUT --destination 192.168.1.2/32 --protocol tcp --match tcp --dport 8080 --jump DNAT --to-destination 10.0.0.2
Diese Regel leitet speziell nur Port 8080 weiter und diese Regel gilt für Sie, damit Sie auf den Dienst AUF DEM PC zugreifen können, auf dem der Dienst läuft. Jeder andere PC im Netzwerk, der darauf zugreift, 192.168.1.2:8080benötigt die PREROUTING-Regel, die ich oben in der Antwort erwähnt habe (ändern Sie einfach --dport 80 in --dport 8080 oder welchen Port/welches Protokoll Sie auch immer benötigen).

Für Leute, die diese Methode und das Skript namespaced-vpn.py verwenden. Sie könnten Probleme haben, wenn Sie Ihr VPN jemals zurücksetzen müssen. Namespaced VPN löst eine Ausnahme aus, wenn es Schnittstellen innerhalb Ihres Zielnamespaces erkennt, die nicht die loLoopback-Schnittstelle sind.
Hier ist der Teil, der bei mir Ausnahmen auslöst, wenn ich namespaced-vpn.py verwende, wenn mein Zielnamespace bereits existiert und meine Veth-Paare enthält.

if os.path.exists(os.path.join('/var/run/netns', namespace)):
        adapters = _adapter_names(namespace)
        if adapters != [b'lo']:
            LOG.error('Namespace %s already has adapters %s, exiting.' % (namespace, adapters))
            raise Exception

Hier ist eine Beispielmodifikation, die ich verwendet habe.
allowed_adapters = [b'lo', b'ivpn']
if os.path.exists(os.path.join('/var/run/netns', namespace)):
     adapters = _adapter_names(namespace)
     # Iterate and ensure all are in allowed list
     for a in adapters:
         if not a.split(b'@')[0] in allowed_adapters:
            LOG.error('Namespace %s has non-whitelisted adapters %s, exiting.' % (namespace, adapters))
            raise Exception

Achten Sie einfach darauf, einen Aufruf wie diesen für jede Schnittstelle hinzuzufügen, von der Sie erwarten, dass sie bereits am Ende der Funktion `def setup_namespace(namespace)` existiert. Ersetzen Sie LO durch den Namen des Geräts
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'LO', 'up'])

Beispiel:
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'ivpn', 'up'])

Wenn Sie einen BitTorrent-Client mit VPN-Schnittstelle verwenden, kann es sein, dass Ihr Client aus irgendeinem Grund zufällig Verbindungen abbricht. Sie wachen beispielsweise morgens auf und stellen fest, dass alle Ihre schönen Downloads 10 Minuten nach Ihrem Verlassen eingefroren wurden.
Ich glaube, dieses Problem liegt an der VPN-Software IE OpenVPN, die aus irgendeinem Grund (Fehler, Ping-Neustart usw.) eine erneute Verbindung zum VPN-Anbieter herstellt und eine neue IP-Adresse zugewiesen bekommt. Die VPN-Schnittstelle muss möglicherweise für den Bruchteil einer Sekunde offline genommen werden, um die Konfiguration zurückzusetzen, und dies führt zu Störungen des Clients (qBittorrent tut dies mit Sicherheit). Eine „Lösung“, mit der ich mich beschäftige, besteht darin, ein Skript zu schreiben, das erkennt, wenn die VPN-Schnittstelle eine neue IP-Adresse erhält oder aus irgendeinem Grund offline genommen wird. Das Skript sollte den Torrent-Client ordnungsgemäß beenden (wichtig: ordnungsgemäß, um eine Beschädigung/einen Dateisystemfehler zu vermeiden) und ihn dann neu starten. Ich habe noch kein funktionierendes Skript, aber das scheint ein guter Weg zur Lösung dieses Problems zu sein.

Antwort2

Okay. Es scheint, dass diese Frage zu kompliziert ist, als dass sie jemand wirklich beantworten könnte, oder vielleicht wurde sie schon einmal beantwortet und niemand wollte antworten.

Wie dem auch sei: Ich habe noch einen Tag daran gearbeitet und bin zu dem Schluss gekommen, dass ich, da ich nur daran interessiert bin, einen Port für die Weboberfläche einer Anwendung freizugeben, auch gleichsocat. So tat ich.

Nachdem ich die Namespaced-OpenVPN-Verbindung hergestellt und die Anwendung innerhalb dieses Netzwerk-Namespaces gestartet hatte, habe ich den folgenden Befehl in einem dedizierten Terminal ausgeführt:

sudo socat tcp-listen:PORT-TO-FORWARD-TO,fork,reuseaddr exec:'ip netns exec vpn socat STDIO tcp-connect\:127.0.0.1\:PORT-TO-LISTEN-TO',nofork

Anmerkungen:

  • PORT-TO-FORWARD-TOist der Port, an den der Port weitergeleitet werden soll (im Root-Netzwerk-Namespace)
  • PORT-TO-LISTEN-TOist der Port der Anwendung, den ich im Root-Namespace verfügbar machen möchte
  • 127.0.0.1Ich musste die tatsächliche Localhost-IP verwenden (nicht localhosteinen Namen, da dieser anscheinend nicht richtig aufgelöst wird)
  • Stellen Sie sicher, dass das Doppelpunktzeichen ( :) innerhalb der einfachen Anführungszeichen steht.
  • Ich bin nicht sicher, ob dies DNS-Lecks verursacht; soweit ich es überprüft habe, ist dies nicht der Fall, aber ich kann nicht sicher sein, da ich nicht weiß, wie ich es testen soll.

Was noch zu tun ist:

  • Automatisieren Sie alle Befehle, um die Anwendung zu starten und den Port beim Start weiterzuleiten: Ich brauche das derzeit nicht, aber wenn ich herausfinde, wie es geht, werde ich es hier hinzufügen

verwandte Informationen