Acheminer le trafic sur une interface spécifique pour un processus sous Linux

20

Est-il possible d'acheminer le trafic utilisé par un processus sur une interface spécifique?

Par exemple, le trafic réseau par application de téléchargement doit toujours utiliser l'interface wlan0alors que toutes les autres applications de la machine doivent utiliser eth0.

Est-il possible d'avoir ce genre de règle sous Linux?

Suresh
la source

Réponses:

22

Cela peut être fait en utilisant des espaces de noms de réseau Linux.

Voici un article qui explique comment. Fondamentalement, vous créez un espace de noms réseau avec une route par défaut différente et exécutez les processus qui en ont besoin. Vous connectez l'espace de noms réseau nouvellement créé à l'adaptateur physique avec un pont (mais d'autres solutions sont bien sûr possibles).

Mise à jour: à partir du noyau 3.14, il est encore plus facile d'utiliser des groupes de contrôle, comme décrit dans cet article . Vous devez:

1) définir un groupe de contrôle net_cls pour annoter les paquets d'un processus donné avec un classid (ou groupe de processus, notez qu'il ne doit pas y avoir de relation parent-enfant entre eux)

2) utilisez le module iptables cgroup (ajouté dans Linux 3.14) pour marquer les paquets

3) utiliser le routage de stratégie (règle ip ajouter fwmark ....) pour créer une nouvelle table de routage pour les paquets marqués

L'avantage est que nous n'avons pas à faire le pontage et tout est beaucoup plus dynamique grâce aux cgroups.

chripell
la source
14

J'ai tellement de mal avec ceci alors voici une solution COMPLÈTE. Il est testé sur Ubuntu 15 et 16. Vous pouvez notamment l'utiliser avec OpenVPN pour router certaines applications en dehors de l'interface du tunnel VPN.

La solution complète "cgroup"

Comment ça marche?

  • Le noyau Linux placera l'application dans un groupe de contrôle . Le trafic réseau des applications de ce groupe de contrôle sera identifié par leur ID de classe au niveau du contrôleur de réseau.
  • iptables marquera ce trafic et le forcera à sortir avec la bonne IP
  • ip route traitera le trafic marqué dans une table de routage différente, avec une route par défaut vers la passerelle IP que vous souhaitez.

Script automatisé

J'ai créé un script novpn.sh pour automatiser l'installation et l'exécution des dépendances. Testé sur Ubuntu.

Démarrez d'abord votre 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

HowTo manuel

Tout d'abord, installez le support et les outils de cgroup:

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

Redémarrez (peut ne pas être nécessaire).

Vous avez besoin d'iptables 1.6 .0+. Obtenez la source de publication d'iptables 1.6.0 , extrayez-la, puis exécutez ceci (l' --disable-nftablesindicateur évitera les erreurs) à partir du répertoire source d'iptables:

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

Maintenant, la vraie config. Définissez un groupe de contrôle nommé novpn. Les processus de ce groupe de contrôle auront un classid de 0x00110011(11:11).

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

Maintenant, nous supposerons que l'interface que vous souhaitez utiliser pour l'application spécifique est eth0avec une IP de passerelle 10.0.0.1. Remplacez- les par ce que vous voulez vraiment (obtenez les informations ip route). Exécuter toujours en tant que 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

Enfin, exécutez votre application sur l'interface spécifique:

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

Ou si vous souhaitez déplacer un processus déjà en cours d'exécution vers le groupe de contrôle, eh bien ... vous ne pouvez pas! Cela semble être dû à la fonction NAT (mascarade): iptables -nvL -t natne correspond pas lorsque le groupe de contrôle est commuté, mais iptables -nvL -t manglecorrespond.

# 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

Crédits: Aucune réponse ne fonctionnait comme prévu, mais une combinaison d'entre elles a fonctionné: chripell answer evolware article Par process routing take 2: using cgroups, iptables and policy routing , comment puis-je faire en sorte qu'un processus spécifique ne passe pas par une connexion OpenVPN? , Kill switch pour OpenVPN sur la base d'iptables

KrisWebDev
la source
Merci pour la bonne réponse, comment puis-je le faire fonctionner avec apache? J'ai essayé cgexec -g net_cls:novpn apache2et m'a donné toute la liste des erreurs non définies variables!
razzak
2
Vous obtiendrez les mêmes erreurs en exécutant apache2directement depuis le terminal. En effet, apache2est normalement lancé en tant que service, avec systemctl start apache2. Cependant, cela ne fonctionnera pas avec cgexec. Le programme appelé doit être un parent du apache2processus souhaité ( ) pour que le groupe de contrôle net_cls se propage. Vous devez donc trouver le script de lancement. Dans ce cas, c'est sudo cgexec -g net_cls:novpn /usr/sbin/apache2ctl start. Vérifiez avec ./novpn.sh --list.
KrisWebDev
Cela ne fonctionne plus dans Ubuntu 16.04!
razzak
2
Je l'utilise sur Ubuntu 16.04 et ça fonctionne bien. Les noms d'interface ont changé dans Ubuntu 16, vous pouvez remplacer le besoin de remplacer eth0par quelque chose comme enp7s0. Obtenez les informations de la ifconfigcommande.
KrisWebDev
Je vous remercie. Mais cela ne fonctionne pas sur Ubuntu 18.04 car cpmanager a été supprimé en raison d'un conflit avec systemd
skonsoft
3

En combinant les excellentes réponses de mariusmatutiae et KrisWebDev, j'ai créé une excellente version modifiée de l'excellent novpn.shscript de KrisWebDev . Alors que le script de KrisWebDev est conçu pour gratter une démangeaison plus spécifique (exécuter et déplacer des processus à l'intérieur / à l'extérieur d'un VPN), ma version vous permet d'exécuter essentiellement n'importe quelle commande dans un environnement réseau que vous spécifiez. Vous pouvez spécifier l'interface à laquelle se lier, la route par défaut, spécifier vos propres règles iptables, routes statiques, spécifier un "test" pour confirmer que tout fonctionne comme vous le souhaitez avant d'exécuter la commande ... etc). Il vous permet d'utiliser plusieurs fichiers de configuration afin que vous puissiez définir un nombre illimité d'environnements réseau spécifiques dans lesquels vous pouvez exécuter des commandes / processus.

Je l'ai posté comme un résumé ici: https://gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

Il peut même nettoyer les tables de cgroup / iptables / routage par la suite!

Commentaires bienvenus.

PS - Il est conçu pour Debian 8 (Jessie)

tout naturel
la source
Salut @allnatural, je voudrais utiliser votre script altnetworking.sh, mais que suis-je censé mettre dans le fichier de configuration?
Cris70
0

Pas par application, non. Vous pouvez le faire par port ou par adresse IP, etc., ou une application elle-même peut se lier à (et utiliser) une carte réseau spécifique.

Vous ne pouvez cependant pas définir de règle pour le faire.

Majenko
la source
J'ai une application java, est-il possible de lier cette application à une interface?
Suresh
Une application Java dont vous avez le code source et pouvez reprogrammer les internes?
Majenko
J'ai un code source d'application java qui utilise la bibliothèque http apache.
Suresh
Ensuite, je me dirigerais vers stackoverflow.com et demanderais aux programmeurs là-bas comment changer votre programme. Je n'ai jamais programmé en Java.
Majenko