Portweiterleitung zur Anwendung im Netzwerk-Namespace mit VPN

13

Ich konnte einen Netzwerk-Namespace einrichten, einen Tunnel mit openvpn einrichten und eine Anwendung starten, die diesen Tunnel im Namespace verwendet. Bisher so gut, aber auf diese Anwendung kann über eine Webschnittstelle zugegriffen werden, und ich kann nicht herausfinden, wie Anforderungen an die Webschnittstelle in meinem LAN weitergeleitet werden.

Ich folgte einer Anleitung von @schnouki, in der erklärt wurde, wie man einen Netzwerk-Namespace einrichtet und OpenVPN darin ausführt

ip netns add myvpn
ip netns exec myvpn ip addr add 127.0.0.1/8 dev lo
ip netns exec myvpn ip link set lo up
ip link add vpn0 type veth peer name vpn1
ip link set vpn0 up
ip link set vpn1 netns myvpn up
ip addr add 10.200.200.1/24 dev vpn0
ip netns exec myvpn ip addr add 10.200.200.2/24 dev vpn1
ip netns exec myvpn ip route add default via 10.200.200.1 dev vpn1
iptables -A INPUT \! -i vpn0 -s 10.200.200.0/24 -j DROP
iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o en+ -j MASQUERADE
sysctl -q net.ipv4.ip_forward=1
mkdir -p /etc/netns/myvpn
echo 'nameserver 8.8.8.8' > /etc/netns/myvpn/resolv.conf

Danach kann ich meine externe IP überprüfen und verschiedene Ergebnisse innerhalb und außerhalb des Namespaces erhalten, wie beabsichtigt:

curl -s ipv4.icanhazip.com
<my-isp-ip>
ip netns exec myvpn curl -s ipv4.icanhazip.com
<my-vpn-ip>

Die Anwendung wird gestartet, für dieses Beispiel verwende ich deluge. Ich habe mehrere Anwendungen mit einer Weboberfläche ausprobiert, um sicherzustellen, dass es sich nicht um ein schweres spezifisches Problem handelt.

ip netns exec myvpn sudo -u <my-user> /usr/bin/deluged
ip netns exec myvpn sudo -u <my-user> /usr/bin/deluge-web -f
ps $(ip netns pids myvpn)
 PID TTY      STAT   TIME COMMAND
1468 ?        Ss     0:13 openvpn --config /etc/openvpn/myvpn/myvpn.conf
9302 ?        Sl    10:10 /usr/bin/python /usr/bin/deluged
9707 ?        S      0:37 /usr/bin/python /usr/bin/deluge-web -f

Ich kann auf das Webinterface auf Port 8112 von innerhalb des Namespaces und von außerhalb zugreifen, wenn ich die IP von veth vpn1 spezifiziere.

ip netns exec myvpn curl -Is localhost:8112 | head -1
HTTP/1.1 200 OK
ip netns exec myvpn curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK
curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK

Ich möchte jedoch den Port 8112 von meinem Server an die Anwendung im Namespace umleiten. Ziel ist es, einen Browser auf einem Computer in meinem LAN zu öffnen und die Webschnittstelle mit http: // my-server-ip: 8112 abzurufen (my-server-ip ist die statische IP des Servers, der die Netzwerkschnittstelle instanziiert hat).

BEARBEITEN: Ich habe meine Versuche, iptables-Regeln zu erstellen, entfernt. Was ich versuche, ist oben erklärt und die folgenden Befehle sollten ein HTTP 200 ausgeben:

curl -I localhost:8112
curl: (7) Failed to connect to localhost port 8112: Connection refused
curl -I <my-server-ip>:8112
curl: (7) Failed to connect to <my-server-ip> port 8112: Connection refused

Ich habe DNAT- und SNAT-Regeln ausprobiert und aus gutem Grund eine MASQUERADE durchgeführt, aber da ich nicht weiß, was ich tue, sind meine Versuche erfolglos. Vielleicht kann mir jemand helfen, dieses Konstrukt zusammenzustellen.

EDIT: Die Ausgabe von tcpdump von tcpdump -nn -q tcp port 8112. Es überrascht nicht, dass der erste Befehl ein HTTP 200 zurückgibt und der zweite Befehl mit einer abgelehnten Verbindung endet.

curl -Is 10.200.200.2:8112 | head -1
listening on vpn0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 10.200.200.1.36208 > 10.200.200.2.8112: tcp 82
IP 10.200.200.2.8112 > 10.200.200.1.36208: tcp 145

curl -Is <my-server-ip>:8112 | head -1
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP <my-server-ip>.58228 > <my-server-ip>.8112: tcp 0
IP <my-server-ip>.8112 > <my-server-ip>.58228: tcp 0

EDIT: @schnouki hat mich auf einen Artikel der Debian-Administration hingewiesen, in dem ein generischer iptables-TCP-Proxy erklärt wird . Angewandt auf das vorliegende Problem würde das Skript folgendermaßen aussehen:

YourIP=<my-server-ip>
YourPort=8112
TargetIP=10.200.200.2
TargetPort=8112

iptables -t nat -A PREROUTING --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort
iptables -t nat -A POSTROUTING -p tcp --dst $TargetIP --dport $TargetPort -j SNAT \
--to-source $YourIP
iptables -t nat -A OUTPUT --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort

Leider wurde der Datenverkehr zwischen den Veth-Schnittstellen blockiert und nichts anderes passierte. @Schnouki schlug jedoch auch die Verwendung socatals TCP-Proxy vor und dies funktioniert einwandfrei.

curl -Is <my-server-ip>:8112 | head -1
IP 10.200.200.1.43384 > 10.200.200.2.8112: tcp 913
IP 10.200.200.2.8112 > 10.200.200.1.43384: tcp 1495

Ich habe das seltsame Port-Shuffling noch nicht verstanden, während der Datenverkehr über die veth-Schnittstellen läuft, aber mein Problem ist jetzt gelöst.

pskiebe
quelle
Haftungsausschluss: Ich habe überhaupt keine Erfahrung mit vethGeräten (finde das aber sehr interessant ... ;-)). Haben Sie tcpdumpüberprüft, wie weit die eingehenden Pakete kommen? Wenn tcpdump -i veth0nichts tcpdumo -i loangezeigt wird, ist dies möglicherweise erforderlich.
Hauke ​​Laging
Ich habe die non-verbose Ausgabe von tcpdump
pskiebe am

Antworten:

8

Ich hatte schon immer Probleme mit iptables-Weiterleitungen (wahrscheinlich meine Schuld, ich bin mir ziemlich sicher, dass es machbar ist). Aber für einen Fall wie Ihren ist es IMO einfacher, dies im Benutzerland ohne iptables zu tun.

Grundsätzlich müssen Sie einen Daemon in Ihrem "Standard" -Arbeitsbereich haben, der den TCP-Port 8112 überwacht und den gesamten Datenverkehr auf den 10.200.200.2-Port 8112 umleitet. Es handelt sich also um einen einfachen TCP-Proxy.

So geht's mit socat :

socat tcp-listen:8112,reuseaddr,fork tcp-connect:10.200.200.2:8112

( Diese forkOption wird benötigt, um zu verhindern socat, dass die Verbindung nach dem Schließen der ersten Proxy-Verbindung beendet wird.)

BEARBEITEN : reuseaddrwie in den Kommentaren vorgeschlagen hinzugefügt .

Wenn Sie es unbedingt mit iptables machen wollen, gibt es eine Anleitung auf der Debian-Administrationsseite . Aber ich bevorzuge socatimmer noch fortgeschrittenere Dinge - wie das Proxysetzen von IPv4 auf IPv6 oder das Entfernen von SSL, damit alte Java-Programme eine Verbindung zu sicheren Diensten herstellen können ...

Beachten Sie jedoch, dass alle Verbindungen in Deluge von Ihrer Server-IP-Adresse stammen und nicht von der tatsächlichen Client-IP-Adresse. Wenn Sie dies vermeiden möchten, müssen Sie einen echten HTTP-Reverseproxy verwenden, der die ursprüngliche Client-IP zur Proxy-Anforderung in einem HTTP-Header hinzufügt.

Schnouki
quelle
1
Du hast gerade meinen Tag gemacht! Ich bin nie darauf gestoßen, socatund es erfüllt genau das, was ich seit einiger Zeit mit iptables versucht habe. Ich habe mehrere Anwendungen getestet und sie funktionieren alle einwandfrei, stellen über tun0 eine Verbindung zur Außenwelt her und bieten über veth1 weiterhin Zugriff auf ihre Weboberfläche.
Pskiebe
1
Nach einigen Tests habe ich die reuseaddrFlagge hinzugefügt . Dies verhindert port already in useFehler beim schnellen Starten und Stoppen von socat:socat -4 TCP-LISTEN:8112,reuseaddr,fork TCP:10.200.200.2:8112
pskiebe
7

Das Verbinden des Netzwerknamensraums mit dem Hauptnamensraum stört mich immer. Normalerweise erstelle ich einen Namespace, weil ich ihn isoliert haben möchte. Abhängig davon, was Sie mit Namespaces erreichen möchten, kann die Erstellung von Interconnects diesen Zweck zunichte machen.

Aber selbst isoliert möchte ich es der Einfachheit halber immer noch über das Netzwerk stöbern.

Mit dieser Lösung können Sie die Isolation beibehalten und einige Verbindungen trotzdem weiterleiten. Sie müssen nicht das gesamte Netzwerk zwischen den beiden Netzwerknamespaces erstellen, um nur einen Port weiterzuleiten. Führen Sie dies in dem Namespace aus, in dem Sie Verbindungen akzeptieren möchten. Muss als root ausgeführt werden, damit ip netns execes funktioniert.

socat tcp-listen:8112,fork,reuseaddr \
  exec:'ip netns exec myvpn socat STDIO tcp-connect\:127.0.0.1\:8112',nofork

Es wartet auf Verbindungen in einem Netzwerk-Namespace, in dem Sie es ausführen, auf Port 8112, und der verbundene Client wird execausgeführt ip netns exec myvpn ..., um den Rest im myvpnNetzwerk-Namespace auszuführen. Sobald er sich im myvpnNetzwerk-Namespace befindet, wird erneut eine Verbindung mit einem anderen hergestellt socat.

AnyDev
quelle
Arbeiten wie ein Zauber
ca.
Da ich mit der Linux-Administration nicht allzu viel Erfahrung habe und es mich einige Zeit gekostet hat, dies herauszufinden: Stellen Sie sicher, dass Sie beide :Zeichen in Anführungszeichen setzen, da sonst möglicherweise ein Fehler auftritt ... wrong number of parameters (2 instead of 1)(2 oder 3). Ansonsten: funktioniert super! Vielen Dank!
Igor
2

Für Hochwasser ist hier meine Lösung. Iptables werden nicht benötigt. Hier sind die Schritte:

  1. Starten Sie Ihren OpenVPN-Tunnel
  2. Erstellen Sie einen Namespace und bringen Sie Ihren OpenVPN-Tunnel dorthin:
ip netns addieren $ NS
# Warten Sie, bis der TUN angezeigt wird
while [[$ (ip route | grep $ TUN | wc -l) == 0]]; schlafe 1; erledigt
MY_IP = $ (IP-Adresse zeigt $ TUN | grep inet | cut -d '' -f6 | cut -d '/' -f1)
# Die Art und Weise, wie Sie die Gateway-IP extrahieren, kann für Ihre OpenVPN-Verbindung unterschiedlich sein
GATEWAY_IP = $ MY_IP
# meine $ TUN (VPN-Schnittstelle) in den Namespace einsperren
ip link set $ TUN netns $ NS
# Rufe die Schnittstelle mit einem Subnetz auf (das dem entspricht, das mir vom VPN-Server gegeben wurde)
ip netns exec $ NS ifconfig $ TUN $ MY_IP / 24 up
# Loopback starten
ip netns exec $ NS ifconfig lo 127.0.0.1/8 up
# Einrichten des Remote-Gateways (Ihre Point-to-Point-VPN-IP-Adresse)
ip netns exec $ NS route füge den Standardwert gw $ GATEWAY_IP hinzu
  1. Stellen Sie eine Verbindung zwischen Ihrem Standard-Namespace und dem von Ihnen erstellten her:
# Richten Sie veth-Schnittstellen für die Kommunikation zwischen Namespaces ein
IP-Link hinzufügen veth0 Typ veth Peer-Name veth1
# Verschieben Sie den zweiten Wert in Ihren Namespace
ip link set veth1 netns $ NS
# Geben Sie eine IP vom nicht verwendeten IP-Bereich bis zum ersten Veth an
ifconfig veth0 10.1.1.1/24 up
# Und der zweite
ip netns exec $ NS ifconfig veth1 10.1.1.2/24 up
# TODO: Richten Sie eine Brücke zwischen der veth1- und der eth-Schnittstelle ein, damit diese mit dem LAN kommunizieren kann
# Richten Sie den DNS-Client ein. ip netns emuliert /etc/resolv.conf mit dieser Datei:
mkdir -p / etc / netns / $ NS
echo "nameserver 8.8.4.4"> /etc/netns/$NS/resolv.conf
  1. Führen Sie Ihren Deluged in der $ NS und Ihr Deluge-Web in Ihrem Standard-Namespace aus. Zeigen Sie mit deluge-web auf die IP-Adresse 10.1.1.2, unter der deluged auf die Verbindung wartet.

Voila! Sie haben sich hinter dem VPN abgesichert, während das Web in Ihrem Heimnetzwerk frei zugänglich ist

Vlad
quelle
2

@ AndrDevEKs Antwort ist nützlich. Um dies zu erweitern, möchten Sie möglicherweise nicht installieren socat. In diesem Fall können Sie dasselbe mit einem leicht verschachtelten SSH-Portforward-Setup erreichen. Insbesondere die Funktion der Portweiterleitung zu / von einem Unix-Domain-Socket ist hier nützlich, da Unix-Domain-Sockets unabhängig von Netzwerk-Namespaces arbeiten:

sudo ip netns exec myvpn su -c "ssh -N -L /tmp/myunixsock:localhost:8112 localhost" $USER &
ssh_pid1=$!
ssh -N -L localhost:8112:/tmp/myunixsock localhost &
ssh_pid2=$!

Aufräumen:

sudo kill $ssh_pid1
kill $ssh_pid2
rm /tmp/myunixsock

Der erste ssh -N -Lwird im myvpn-Namespace gestartet. Dadurch wird ein Unix-Domain-Socket erstellt /tmp/myunixsockund abgehört. Eingehende Verbindungen werden an localhost: 8112 (innerhalb des myvpn-Namespace) weitergeleitet. Der zweite ssh -N -Lwird im Standardnamespace gestartet. Dadurch wird ein empfangsbereiter TCP-Port erstellt und eingehende Verbindungen an den Unix-Domain-Socket weitergeleitet.

Damit dies funktioniert, muss sshin Ihrem Netzwerk-Namespace Folgendes funktionieren, sofern dies nicht bereits geschehen ist (und der Betrieb ohne Kennwort ist hilfreich):

sudo ip netns exec myvpn ip link set up dev lo
sudo ip netns exec myvpn /usr/sbin/sshd -o PidFile=/run/sshd-myvpn.pid
ssh-copy-id localhost
Digitales Trauma
quelle