Leiten Sie den Datenverkehr über eine bestimmte Schnittstelle für einen Prozess unter Linux


20

Ist es möglich, den von einem Prozess verwendeten Datenverkehr über eine bestimmte Schnittstelle weiterzuleiten?

Zum Beispiel sollte der Netzwerkverkehr per Download-Anwendung immer die Schnittstelle verwenden, wlan0wohingegen alle anderen Anwendungen auf dem Computer verwenden sollten eth0.

Kann man eine solche Regel unter Linux haben?

Antworten:


22

Dies kann mit Linux-Netzwerk-Namespaces erfolgen.

Hier ist ein Artikel , der erklärt, wie. Grundsätzlich erstellen Sie einen Netzwerk-Namespace mit einer anderen Standardroute und führen dort die Prozesse aus, die diesen benötigen. Sie verbinden den neu erstellten Netzwerknamespace über eine Bridge mit dem physischen Adapter (andere Lösungen sind natürlich möglich).

Update: Ab Kernel 3.14 ist es noch einfacher, Kontrollgruppen zu verwenden, wie in diesem Artikel beschrieben . Sie müssen:

1) Definieren Sie eine net_cls-Kontrollgruppe, um die Pakete eines bestimmten Prozesses mit einer Klassen-ID zu versehen (oder einer Gruppe von Prozessen, beachten Sie, dass keine Eltern-Kind-Beziehung zwischen ihnen bestehen muss).

2) Verwenden Sie das Modul iptables cgroup (hinzugefügt in Linux 3.14), um die Pakete zu markieren

3) Verwenden Sie das Richtlinien-Routing (IP-Regel fwmark hinzufügen ....), um eine neue Routing-Tabelle für die markierten Pakete zu erstellen

Der Vorteil ist, dass wir das Überbrücken nicht machen müssen und dank cgroups alles viel dynamischer ist.


14

Ich habe sooo damit gekämpft, dass es hier eine KOMPLETTE Lösung gibt. Es wurde auf Ubuntu 15 und 16 getestet. Sie können es insbesondere mit OpenVPN verwenden, um bestimmte Apps außerhalb der VPN-Tunnelschnittstelle weiterzuleiten.

Die komplette "cgroup" -Lösung

Wie das funktioniert?

  • Der Linux-Kernel ordnet die App einer Kontrollgruppe zu . Der Netzwerkverkehr von Apps in dieser C-Gruppe wird durch ihre Klassen-ID auf Netzwerkcontrollerebene identifiziert.
  • iptables markiert diesen Datenverkehr und erzwingt, dass er mit der richtigen IP beendet wird
  • ip route verarbeitet den markierten Datenverkehr in einer anderen Routingtabelle mit einer Standardroute zu der von Ihnen gewünschten Gateway-IP.

Automatisiertes Skript

Ich habe ein novpn.sh- Skript erstellt, um die Installation und Ausführung von Abhängigkeiten zu automatisieren. Getestet auf Ubuntu.

Starten Sie zuerst Ihr VPN.

wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/cf8b37fbe6c3f50a0be825eb77cafa3e0134946f/novpn.sh
# If you don't use eth0, edit the script setting.
sudo chmod +x novpn.sh
./novpn.sh traceroute www.google.com
./novpn.sh --help

Handbuch HowTo

Installieren Sie zunächst die cgroup-Unterstützung und -Tools:

sudo apt-get install cgroup-lite cgmanager cgroup-tools

Neustart (möglicherweise nicht erforderlich).

Sie benötigen iptables 1.6 .0+. Holen Sie sich die iptables 1.6.0-Release-Quelle , extrahieren Sie sie und führen Sie diese aus ( --disable-nftablesFlag vermeidet Fehler):

sudo apt-get install dh-autoreconf bison flex
./configure --prefix=/usr      \
            --sbindir=/sbin    \
            --disable-nftables \
            --enable-libipq    \
            --with-xtlibdir=/lib/xtables
make
sudo make install
iptables --version

Nun ist die echte Konfig. Definieren Sie eine Kontrollgruppe mit dem Namen novpn. Prozesse in dieser Gruppe haben die Klasse 0x00110011(11:11).

sudo su
mkdir /sys/fs/cgroup/net_cls/novpn
cd /sys/fs/cgroup/net_cls/novpn
echo 0x00110011 > net_cls.classid

Nun nehmen wir an, dass die Schnittstelle, die Sie für die bestimmte App verwenden möchten, eth0eine Gateway-IP von ist 10.0.0.1. Ersetzen Sie diese durch das, was Sie wirklich wollen (Informationen erhalten Sie von ip route). Laufen Sie immer noch als root:

# Add mark 11 on packets of classid 0x00110011
iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x00110011 -j MARK --set-mark 11

# Force the packets to exit through eth0 with NAT
iptables -t nat -A POSTROUTING -m cgroup --cgroup 0x00110011 -o eth0 -j MASQUERADE

# Define a new "novpn" routing table
# DO THIS JUST ONCE !
echo 11 novpn >> /etc/iproute2/rt_tables

# Packets with mark 11 will use novpn
ip rule add fwmark 11 table novpn

# Novpn has a default gateway to the interface you want to use
ip route add default via 10.0.0.1 table novpn

# Unset reverse path filtering for all interfaces, or at least for "eth0" and "all"
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done

Führen Sie schließlich Ihre App auf der spezifischen Oberfläche aus:

exit
sudo cgcreate -t $USER:$USER -a $USER:$USER -g net_cls:novpn
cgexec -g net_cls:novpn traceroute www.google.com
# Close all Firefox windows first
cgexec -g net_cls:novpn firefox

Oder wenn Sie einen bereits laufenden Prozess in die cgroup verschieben möchten, können Sie das nicht! Das scheint an der NAT (Masquerade) -Funktion zu liegen: iptables -nvL -t natStimmt nicht überein, wenn die cgroup umgeschaltet wird, iptables -nvL -t manglestimmt aber überein.

# Get PID of the process (we'll then suppose it's 1234)
pidof firefox
# Add to cgroup - THIS DOESN'T WORK! Silently fails to produce the final result.
sudo echo 1234 > /sys/fs/cgroup/net_cls/novpn/tasks
# Remove - but this works...
sudo echo 1234 > /sys/fs/cgroup/net_cls

Credits: Keine Antwort hat wie erwartet funktioniert, aber eine Mischung aus beiden hat funktioniert: chripell answer evolware article Pro Prozess-Routing dauert es 2: Verwenden von Cgroups, Iptables und Richtlinien-Routing . Wie kann ich einen bestimmten Prozess NICHT über eine OpenVPN-Verbindung führen? , Kill Switch für OpenVPN auf Basis von Iptables


Vielen Dank für die tolle Antwort, wie mache ich das mit Apache? Ich habe versucht cgexec -g net_cls:novpn apache2und gab mir die ganze Liste der Variablen undefinierte Fehler!
Razzak

2
Die gleichen Fehler treten auf, wenn Sie apache2direkt vom Terminal aus ausgeführt werden. Das apache2liegt daran, dass normalerweise als Dienst mit gestartet wird systemctl start apache2. Das geht aber nicht cgexec. Das aufgerufene Programm muss ein übergeordnetes apache2Element des gewünschten ( ) - Prozesses sein, damit net_cls cgroup weitergegeben werden kann. Sie müssen also das Startskript finden. In diesem Fall ist es sudo cgexec -g net_cls:novpn /usr/sbin/apache2ctl start. Überprüfen Sie mit ./novpn.sh --list.
KrisWebDev

Es funktioniert nicht mehr in Ubuntu 16.04!
Razzak

2
Ich benutze es auf Ubuntu 16.04 und es funktioniert gut. Die Namen der Benutzeroberfläche haben sich in Ubuntu 16 geändert. Möglicherweise müssen Sie sie eth0durch etwas ersetzen enp7s0. Holen Sie sich die Informationen aus dem ifconfigBefehl.
KrisWebDev

Vielen Dank. Aber es funktioniert nicht auf Ubuntu 18.04 wegen cpmanager hat aufgrund eines Konflikts entfernt mit systemd
skonsoft


3

Durch die Kombination der hervorragenden Antworten von mariusmatutiae und KrisWebDev habe ich eine umfassend modifizierte Version des hervorragenden novpn.shSkripts von KrisWebDev erstellt . Während das Skript von KrisWebDev darauf ausgelegt ist, einen spezifischeren Juckreiz (das Ausführen und Verschieben von Prozessen innerhalb / außerhalb eines VPN) zu verhindern, können Sie in meiner Version grundsätzlich jeden Befehl in einer von Ihnen angegebenen Netzwerkumgebung ausführen. Sie können die Schnittstelle angeben, an die gebunden werden soll, die Standardroute, Ihre eigenen Iptables-Regeln, statische Routen, einen "Test" angeben, um zu bestätigen, dass alles wie gewünscht funktioniert, bevor Sie den Befehl ausführen. Sie können mehrere Konfigurationsdateien verwenden, um eine beliebige Anzahl spezifischer Netzwerkumgebungen zu definieren, in denen Sie Befehle / Prozesse ausführen können.

Ich habe es als Zusammenfassung hier gepostet: https://gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

Es kann sogar die cgroup / iptables / routing-Tabellen danach bereinigen!

Feedback erwünscht.

PS - Es wurde für Debian 8 (Jessie) entwickelt


Hallo @allnatural, ich möchte Ihr altnetworking.sh-Skript verwenden, aber was soll ich in die Konfigurationsdatei einfügen?
Cris70

0

Nicht pro Anwendung, nein. Sie können dies pro Port oder pro IP-Adresse usw. tun, oder eine Anwendung selbst kann an eine bestimmte Netzwerkkarte binden (und diese verwenden).

Sie können jedoch keine Regel dafür festlegen.


Ich habe eine Java-Anwendung. Ist es möglich, diese Anwendung an eine Benutzeroberfläche zu binden?
Suresh

Eine Java-Anwendung, für die Sie den Quellcode haben und die Interna neu programmieren können?
Majenko

Ich habe einen Java-Anwendungsquellcode, der die http-Bibliothek von Apache verwendet.
Suresh

Dann gehe ich zu stackoverflow.com und frage die dortigen Programmierer, wie sie Ihr Programm ändern sollen. Ich habe noch nie in Java programmiert.
Majenko
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.