Binden Sie ein Unix-Programm an eine bestimmte Netzwerkschnittstelle

40

Frage: Wie starte ich ein Programm und stelle dabei sicher, dass der Netzwerkzugriff über eine bestimmte Netzwerkschnittstelle erfolgt?

Fall: Ich möchte auf zwei verschiedene Computer mit derselben IP-Adresse (192.168.1.1) zugreifen, die jedoch über zwei verschiedene Netzwerkschnittstellen (eth1 und eth2) erreichbar sind.

Beispiel:

net-bind -D eth1 -exec {Program 192.168.1.1}
net-bind -D eth2 -exec {Program 192.168.1.1}

Das Obige ist eine Annäherung an das, was ich gerne hätte, inspiriert von der Hardware-Bindung, die über primusrun und optirun durchgeführt wurde .

Herausforderung: Wie in einem verwandten Thread vorgeschlagen , werden die verwendeten Schnittstellen nicht vom Programm, sondern vom Kernel ausgewählt (daher die Präbindungssyntax im obigen Beispiel).

Ich habe einige verwandte Lösungen gefunden, die unbefriedigend sind. Sie basieren auf der Bindung von Netzwerkschnittstellen über benutzerspezifisches Netzwerk-Blacklisting. dh Ausführen des Prozesses als Benutzer, der nur auf eine bestimmte Netzwerkschnittstelle zugreifen kann.

Skeen
quelle
Bedeuten Sie, dass Ihr Computer an zwei verschiedene Netzwerke angeschlossen ist, beide 192.168.1.0? Wie sieht Ihre Routing-Tabelle aus? Wenn Sie die für einen Prozess sichtbaren Schnittstellen einschränken möchten, ist die einfachste Lösung cgroups, ein schwererer Container.
Lgeorget
Ja, zwei verschiedene Netzwerke, beide im selben IP-Bereich. Ich bin nicht sicher, ob ich die sichtbaren Schnittstellen einschränken möchte. :)
Skeen
3
Was Sie fragen, ist aus einem guten Grund schwierig: Wenn zwei Netzwerke unter Verwendung derselben IP-Domäne miteinander verbunden sind, ist dies mit einem Aufzug in einem zweistöckigen Gebäude mit derselben Nummer vergleichbar. Der IP-Bereich kennzeichnet die Domäne, nicht die Ausgabeschnittstelle. Trotzdem muss es eine Möglichkeit geben, Ihr fehlerhaftes Netzwerkdesign mit iptables zu umgehen.
Lgeorget
Ich verbinde mein System mit zwei verschiedenen In-Place-Infrastrukturen, da die Infrastrukturen niemals für die Interaktion ausgelegt waren und daher das Netzwerkdesign in dieser Hinsicht fehlerhaft ist.
Skeen
1
Mein Argument gegenüber NATs war, dass sich in der Regel ganze Adressräume hinter dem NAT verstecken und die Kollision auftritt, wenn ich zwei NAT-Infrastrukturen verbinde. - Ich bin nicht in der Lage, die Infrastruktur zu verändern. - Ich habe versucht, Netzwerknamespaces mit virtuellen Netzwerkschnittstellenpaaren (eines im Namespace, eines im Stammnamespace) zu verwenden, um den Stammnamespace mit der physischen Schnittstelle zu verbinden und Programme im Netzwerknamespace auszuführen. - Dies scheint zu funktionieren, aber ich erhalte keinen Zugriff über den Root-Namespace hinaus (dh keinen Zugriff außerhalb des Computers selbst).
Skeen

Antworten:

35

Für Linux wurde dies bereits unter Superuser beantwortet - Wie werden verschiedene Netzwerkschnittstellen für verschiedene Prozesse verwendet? .

In der gängigsten Antwort wird ein LD_PRELOADTrick verwendet, um die Netzwerkbindung für ein Programm zu ändern. Moderne Kernel unterstützen jedoch eine wesentlich flexiblere Funktion namens "Netzwerknamespaces", die über das ipProgramm verfügbar gemacht werden. Diese Antwort zeigt, wie man das benutzt. Aus meinen eigenen Experimenten habe ich folgendes gemacht (als root):

# Add a new namespace called test_ns
ip netns add test_ns

# Set test to use eth0, after this point eth0 is not usable by programs
# outside the namespace
ip link set eth0 netns test_ns

# Bring up eth0 inside test_ns
ip netns exec test_ns ip link set eth0 up

# Use dhcp to get an ipv4 address for eth0
ip netns exec test_ns dhclient eth0

# Ping google from inside the namespace
ip netns exec test_ns ping www.google.co.uk

Es ist auch möglich, Netzwerk-Namespaces in gewissem Umfang mit den Befehlen unshareund zu verwalten nsenter. Auf diese Weise können Sie auch separate Bereiche für PIDs, Benutzer und Einhängepunkte erstellen. Weitere Informationen finden Sie unter:

Graeme
quelle
"nach diesem Zeitpunkt kann eth0 nicht mehr von Programmen außerhalb des Namespaces verwendet werden."
Skeen
1
@Skeen, ja, vermutlich würden Sie eine Schnittstelle, die von keinem anderen Programm verwendet wird, in den Namespace verschieben und Ihre Hauptschnittstelle normal verwenden.
Graeme
1
@Graerne; Beide Schnittstellen werden aktiv genutzt; Ich kann es mir nicht leisten, die Schnittstellen abzubauen.
Skeen
und was ist mit Standard-Gateway? wvdialzum Beispiel scheint es überhaupt nicht einzurichten ... also muss es im Namespace selbst definiert werden
Flash Thunder
Könnten Sie Anweisungen einschließen, wie man das rückgängig macht? Wollen Sie einfach ip netns remove test_nswieder normal werden? Oder müssen Sie etwas Besonderes tun?
Multihunter
17

Ich akzeptiere Graemes Antwort. Dies ist nur eine Nachverfolgung, um die Änderungen zu erklären, die ich an seinem Vorschlag zur Lösung meines Problems vorgenommen habe.

Anstatt die physische Schnittstelle im Namespace zu binden, habe ich ein virtuelles Netzwerkschnittstellenpaar mit einem Ende im Netzwerknamespace und einem Ende im Stamm erstellt. Pakete werden dann über dieses virtuelle Netzwerk vom Namespace zum Root-Namespace und dann zur physischen Schnittstelle weitergeleitet. - Als solche kann ich alle meine gewöhnlichen Datenübertragungen ausführen und außerdem Prozesse starten, die nur auf eine bestimmte Schnittstelle zugreifen können.

# Create the eth0 network namespace
ip netns add eth0_ns

# Create the virtual network pair
ip link add v_eth0a type veth peer name v_eth0b

# Move v_eth0a to the eth0_ns namespace, the virtual pair is now split
# between two network namespaces.
ip link set v_eth0a netns eth0_ns

# Configure the ends of the virtual network pairs
ip netns exec eth0_ns ifconfig v_eth0a up {{NAMESPACE_IP}} netmask {{NAMESPACE_NETMASK}}
ifconfig v_eth0b up {{ROOT_NS_IP}} netmask {{ROOT_NS_NETMASK}}

# Setup routing from namespace to root
ip netns exec eth0_ns route add default gw {{ROOT_NS_IP}} dev v_eth0a

# Setup IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s {{ROUTE_SOURCE}}/24 -o {{NETWORK_INTERFACE}} -j SNAT --to-source {{ROUTE_TARGET}}

Nachdem die Schnittstellen für eth0 und eth1 mit ihren jeweiligen Namespaces eth0_ns und eth1_ns eingerichtet wurden, können Programme auf der angegebenen Schnittstelle über ausgeführt werden.

ip netns exec eth0_ns fish
ip netns exec eth1_ns fish
Skeen
quelle
4
Gut gemacht! Ich denke, Sie können auch ein Bridge-Gerät erstellen und den Standard-Namespace und das virtuelle Paar mit einem der physischen Geräte verbinden. Dies sieht jedoch äquivalent aus.
Graeme
1
Ich habe versucht, das virtuelle und das physische Gerät zu verbinden. Ich konnte mit dieser Lösung nicht auf das externe Netzwerk zugreifen.
Skeen
2
Das habe ich gemacht, aber nur aus dem neuen Namespace. Ich denke, das Problem, das ich hatte, hing mit dem Netzwerkmanager zusammen, aber ich habe es nicht herausgefunden, oder ich hätte meine Antwort aktualisiert.
Graeme
Ich habe das gleiche Problem, aber ich habe diese Lösung nicht verwendet. Was genau muss ich im letzten Schritt in {{ROUTE_SOURCE}} und {{ROUTE_TARGET}} eingeben?
Litov
@Graeme, zumindest unter Ubuntu konnte ich die Konnektivität sowohl im Namespace als auch im globalen Namespace wiederherstellen, indem ich dhclient <bridge>per here ausgab .
Chris Hunt
4

Lösung I: Vorabladen einer bestimmten Bibliothek

  • App-Route-Jail : Verwenden Sie ld_preload, um die Verwendung des Schnittstellen-Gateways zu erzwingen (gute Idee, aber Root- oder Markierungsfähigkeiten erforderlich)

  • Proxybound : Verwenden Sie ld_preload, um einen Proxy für eine bestimmte Anwendung zu erzwingen (dies verwendet einen Proxy anstelle einer Schnittstelle).

  • Force-Bind : viele Funktionen, aber das Binden leckt (nicht zuverlässig)

  • Bind-Interface-IP : zu einfache und undichte Verbindungen (nicht zuverlässig)

  • Bind-IP : viel zu einfache und undichte Verbindungen (nicht zuverlässig)

Lösung II: Linux Userspace

  • Klassischer Linux-User-Space IP-Netns : Tolle Lösung, aber Root und Interface müssen vorhanden sein

  • Firejail : Firejail kann eine Anwendung zur Verwendung eines bestimmten Netzwerks zwingen, die Kompatibilität ist jedoch begrenzt (z. B. nicht kompatibel mit Tun-Schnittstellen). firejail benötigt kein rootfirejail --dns=8.8.8.8 --noprofile --net=eth0 --ip=192.168.1.1 app-command

  • Firejail mit netns : Firejail kann eine Anwendung zwingen, einen bestimmten Benutzerbereich zu verwenden, der separat erstellt wurde. Auf diese Weise können Sie Bereiche ohne root benennenfirejail --dns=8.8.8.8 --noprofile --netns=nameOfyourNS app-command

  • Firejail mit Maskerade und Brücke : Firejail eine Anwendung zwingen kann , eine verwenden spezifische Schnittstelle mit iptables Maskerade , ist dieser große und erfordert keine root aber dies erfordert ip_forward und Auswirkungen Sicherheit bedeuten könntefirejail --net=br0 firefox

Lösung III: Linux Iptables

Iptables können für diesen Zweck verwendet werden , erfordern jedoch ip_forward und können Auswirkungen auf die Sicherheit haben, wenn sie nicht richtig konfiguriert sind ( Beispiel 1 , Beispiel 2 , Beispiel 3 , Beispiel 4)

Lösungshinweise (I, II & III):

Wireguard

Wenn Sie ein VPN (insbesondere Wireguard) verwenden und diese Lösung auf eine Wireguard-Schnittstelle ( Wireguard mit Benutzerbereich ) anwenden möchten, können Sie den verknüpften Anweisungen folgen, um einen Benutzerbereich mit einer WG-Schnittstelle (und damit auf eine VPN-Schnittstelle beschränkt) zu erstellen ) kann auch mit kombiniert firejail --netns=containerwerden, um den Benutzerraum ohne root nutzen zu können.

So finden Sie das Schnittstellen-Gateway

Es gibt viele Lösungen, um das Gateway zu finden. Hier sind einige Befehle, die es erlauben, das verwendete Gateway zu finden

$ route
$ route -n
$ ip rule list
$ ip route show
$ netstat -rn
$ cat /etc/network/interfaces
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
$ traceroute www.google.com
$ ip route show 0.0.0.0/0 dev eth0

Wie benutzt man App-Route-Jail?

  • Erstellen Sie App-Route-Jail
git clone https://github.com/Intika-Linux-Network/App-Route-Jail.git
cd Approute-Utils
chown 755 make.sh
./make.sh
  • Das Hinzufügen einer Route für die zukünftig markierten Pakete (für die inhaftierte Anwendung) wird in diesem Beispiel 192.168.1.1als erzwungenes Gateway verwendet. Diese Routenregel wirkt sich nicht auf andere Anwendungen aus. Diese Manipulation muss beispielsweise nur einmal beim Systemstart durchgeführt werden, wenn Sie dies möchten Verwenden Sie diese Lösung täglich
ip rule add fwmark 10 table 100
ip route add default via 192.168.1.1 table 100
  • Starten Sie die Anwendung, die Sie ins Gefängnis bringen möchten
MARK=10 LD_PRELOAD=./mark.so firefox
  • Testen der WAN-IP-Adresse
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me
intika
quelle