Befehl zum Ausführen eines untergeordneten Prozesses "offline" (kein externes Netzwerk) unter Linux

15

Ich habe ein Programm, das ich im Offline-Modus testen möchte, ohne mein aktuelles Netzwerk herunterzufahren. Dieses Programm muss weiterhin eine Verbindung zu lokalen Sockets herstellen, einschließlich Unix-Domain-Sockets und Loopback. Es muss auch Loopback abhören und für andere Apps sichtbar sein.

Versuche, eine Verbindung zu einem Remote-Computer herzustellen, sollten jedoch fehlschlagen.

Ich möchte ein Programm haben , das funktioniert wie strace/ unshare/ sudound läuft einfach einen Befehl mit dem Internet (und LAN) verborgen und alles andere noch arbeiten:

$ offline my-program-to-test

Diese Frage hat Hinweise auf die Antwort: Netzwerkzugriff eines Prozesses blockieren?

Es gibt dort ein paar Vorschläge, wie Sie ausführen, während ein anderer Benutzer iptables manipuliert, oder unshare -n. In beiden Fällen kenne ich die Beschwörung nicht, Unix-Domain-Sockets und Loopback für das Hauptsystem freizugeben . Die Antworten auf diese Frage geben nur Aufschluss darüber, wie ich die Freigabe des gesamten Netzwerks aufheben kann.

Das Programm, das ich teste, muss immer noch eine Verbindung zu meinem X-Server und zu meinem D-Bus herstellen und sogar in der Lage sein, im Loopback auf Verbindungen von anderen Apps auf dem System zu warten.

Idealerweise möchte ich das Erstellen von Chroots oder Benutzern oder VMs oder Ähnlichem vermeiden, da dies genauso ärgerlich ist wie das Herausziehen des Netzwerkkabels. dh der Punkt der Frage ist, wie ich das so einfach wie möglich machen kann sudo.

Ich würde es begrüßen, wenn der Prozess zu 100% normal ausgeführt würde, mit der Ausnahme, dass Netzwerkaufrufe, die eine nicht lokale Adresse angeben, fehlschlagen würden. Im Idealfall sollte dieselbe UID, dasselbe Homedir, dasselbe PWD und dasselbe alles außer ... offline beibehalten werden.

Ich verwende Fedora 18, daher sind nicht portierbare Linux-Antworten in Ordnung (auch erwartet).

Ich bin sogar froh, dies durch das Schreiben eines C-Programms zu lösen, wenn es darum geht, also sind Antworten, die das Schreiben von C beinhalten, in Ordnung. Ich weiß nur nicht, welche Systemaufrufe das C-Programm ausführen müsste, um den externen Netzwerkzugriff zu widerrufen, während das lokale Netzwerk erhalten bleibt.

Jeder Entwickler, der versucht, den "Offline-Modus" zu unterstützen, würde dieses Dienstprogramm wahrscheinlich begrüßen!

Havoc P
quelle

Antworten:

9

Die traditionelle Antwort ist, das Programm als anderer Benutzer auszuführen und zu verwenden iptables -m owner. Auf diese Weise wird die Netzwerkkonfiguration freigegeben. Mit dem Aufkommen von Namespaces gibt es jedoch einen einfacheren Weg.

Mit Namespaces heben Sie die Freigabe des Netzwerks auf und erstellen dann eine virtuelle Netzwerkverbindung, wenn Sie einen eingeschränkten Netzwerkzugriff benötigen.

Um Unix-Domain-Sockets freizugeben , benötigen Sie nach diesem 2010-Patch lediglich einen ausreichend aktuellen Kernel, also 2.6.36 oder höher (dies ist bei allen aktuellen Distributionen zum Zeitpunkt des Schreibens der Fall, mit Ausnahme von RHEL / CentOS).

Führen Sie das Programm in einem eigenen IP-Namespace aus. Richten Sie vor dem Starten des Programms eine virtuelle Ethernet-Schnittstelle ein. Es scheint nicht viel Dokumentation zu geben; Ich habe die richtige Beschwörung in ein paar Blogs gefunden:

Im folgenden Snippet verwende ich den in der Manpage aufgelisteten ns_execis this-Wrapper, umsetns die Host-Seite der Netzwerkverbindung aus dem Prozess aufzurufen, der im eingeschränkten Namespace ausgeführt wird. Das brauchen Sie eigentlich nicht: Sie können die Host-Seite des Links von außerhalb des eingeschränkten Namespaces einrichten. Dies von innen zu tun, erleichtert lediglich die Ablaufsteuerung. Andernfalls benötigen Sie eine gewisse Synchronisierung, um die Verbindung einzurichten, nachdem sie hergestellt wurde, jedoch bevor Sie Ihr Programm starten.

unshare -n -- sh -c '
  # Create a virtual ethernet interface called "confined",
  # with the other end called "global" in the namespace of PID 1
  ip link add confined type veth peer name global netns 1

  # Bring up the confined end of the network link
  ip addr add 172.16.0.2/30 dev confined
  ip link set confined up

  # Bring up the global end of the network link
  ns_exec /proc/1/ns/net ifconfig global 172.16.0.1 netmask 255.255.255.252 up

  # Execute the test program
  exec sudo -E -u "$TARGET_USER" "$0" "$@"
' /path/to/program --argument

Sie müssen dies alles als root ausführen. Durch die Einführung von Benutzernamensräumen in Kernel 3.8 ist dies möglicherweise ohne besondere Berechtigungen möglich, es sei denn, Sie richten das globale Ende der Netzwerkverbindung ein.

Ich weiß nicht, wie ich localhost zwischen den beiden Namespaces teilen soll. Virtuelle Ethernet-Schnittstellen bilden eine Punkt-zu-Punkt-Brücke. Sie können iptablesWeiterleitungsregeln verwenden, um den Verkehr von / nach umzuleiten, lofalls dies gewünscht wird.

Gilles 'SO - hör auf böse zu sein'
quelle
Gute Zusatzinfo, danke. Ich denke, Veth gibt mir eine Verknüpfung zu "außerhalb" des Namespace, aber mein neuer Namespace entspricht immer noch einem separaten Netzwerkknoten, und nicht demselben Netzwerkknoten abzüglich der nicht lokalen Schnittstellen. Implikationen sind (?): Unix-Domain- / Abstract-Sockets würden immer noch fehlschlagen, und Loopback könnte über iptables weitergeleitet werden, aber bei der Weiterleitung wird keine gemeinsame Nutzung erzielt -ändernde) Ports müssten in beiden Namespaces sichtbar sein ... hier ist es unmöglich zu erraten, was ich will: - /
Havoc P
1

Dies kann auch mit iptables-Regel-Matching-Gruppen erreicht werden. Ich habe ein Tool geschrieben, um die Schritte zu abstrahieren. Es erfordert zwar Root-Berechtigungen für die Ersteinrichtung und ist ansonsten eine Setuid-Binärdatei, bietet aber meiner Meinung nach eine recht einfache Möglichkeit, das Problem in der Frage zu lösen. Es ist eine iptables-Version erforderlich, die aktuell genug ist und über die die richtigen Netfilter-Module verfügt.

https://github.com/quitesimpleorg/qsni

crtxcr
quelle
0

/ !! \ Dies ist wahrscheinlich keine gültige Antwort, da dies den gesamten Datenverkehr mit sich bringt, nicht nur den Datenverkehr einer einzelnen PID.

Ich habe es nicht verwendet, aber ich denke, Sie könnten möglicherweise Comcast verwenden:

https://github.com/tylertreat/Comcast

auf 100% Paketverlust eingestellt

Auch hier habe ich das nicht getestet, aber theoretisch geändert von der Readme-Datei können Sie Folgendes tun:


Linux

Unter Linux können Sie iptablesein- und ausgehende Pakete löschen.

$ iptables -A INPUT -m statistic --mode random --probability 1 -j DROP
$ iptables -A OUTPUT -m statistic --mode random --probability 1 -j DROP

Alternativ können Sie verwenden tc, die einige zusätzliche Optionen unterstützt.

$ tc qdisc change dev eth0 root netem reorder 0 duplicate 0 corrupt 1

Zurücksetzen:

$ tc qdisc del dev eth0 root netem
ThorSummoner
quelle