Routage différent selon le programme

Bonsoir tout le monde,

Voilà, j’ai un mini pc qui fait office de HTPC avec XBMC. D’autres services réseaux tournent aussi dessous.

Et un de ces services nécessite une sécurité et une confidentialité très renforcées. Du coup, j’ai mis en place une connexion vpn sur le mini pc. Et ça marche très bien : tout le trafic réseau passe par le VPN.
Je suis bien content… enfin, presque…

Car TOUT le trafic réseau passe par le VPN et d’autres services gaspillent la bande passante de la connexion VPN… Or ces autres services ne nécessitent aucunement une confidentialité mais plutôt une rapidité de la connexion (ce qui n’est pas le cas du VPN).

Si vous avez compris mon petit soucis (enfin, je l’espère), je veux faire une sorte de routage par service. Schématiquement, je veux ça :

(service confidentiel) ===> ppp0 ===> (serveur VPN) =======> (Internet)
(le reste des services) ==> eth0 =============> (Internet)

C’est possible?
Merci d’avance.

Librement,

Oui.
Ici pour les explications les plus récentes (je crois, comme tu pourras le constater je n’y ai pas touché depuis un moment) isalo.org/wiki.debian-fr/ind … s_internet
Ici pour la méthode de sélection des process concernés : debian-fr.org/routage-select … 27620.html (new-group ou sg, et un routage sélectif à base de --gid-owner, cf. sections 1 et 5)

Attention quand même vu que ton service est confidentiel :

[quote]6) Comportement si l’interface est down

Lorsque l’interface eth1 n’est plus disponible, toutes les entrées correspondantes dans les tables de routage sont supprimées.

Cela signifie que :

  • les paquets précédemment routés vers l’accès internet secondaire (eth1 / 192.168.2.1) vont à nouveau utiliser l’accès principal (eth0 / 192.168.1.1).
  • les connexions existantes vont être bloquées car le pair (à l’autre bout d’internet) attend des paquets provenant de l’IP publique de l’accès internet secondaire et non pas de celle de l’accès internet principal. Elles se fermeront d’elles-mêmes lorsque tous les timeouts auront pris effet, ce qui peut durer assez longtemps et bloquer le process émetteur en attendant.
  • les nouvelles connexions vont utiliser l’accès principal.

Dans une version précédente de ce T&A j’avais indiqué une méthode pour bloquer les connexions dans ce cas de figure, mais je me suis aperçu que ça déconnait sévère. En attendant que moi ou quelqu’un d’autre trouve une solution fiable, il faudra se contenter de subir les restrictions expliquées ci-dessus.[/quote]
Il faudra donc bricoler toi-même pour trouver la solution à ça.

Ok merci! Je vais regarder ça.

edit:
Pour le problème interface down, j’ai déjà un script qui vérifie toute les minutes que le VPN est toujours UP et fait le nécessaire s’il est down.

Ça te laisse quand même une fenêtre d’une minute où tes paquets confidentiels sortent par la carte par défaut (non protégée).

Sinon, selon ce que tu veux faire précisément et le degré de “configurabilité” du logiciel client, ça serait pas plus simple un bête tunnel SSH ?

Ça te laisse quand même une fenêtre d’une minute où tes paquets confidentiels sortent par la carte par défaut (non protégée).
[/quote]
J’y ai pensé mais il suffit de bloquer le trafic sur l’interface par défaut (avec iptable), non?

Oui mais ça reviendra au point de départ. Tous le trafic va passer par le tunnel. Et puis, je n’ai qu’un VPN à disposition.

Hmm je sais pas trop. Peut-être un filtrage iptables --gid-owner sur eth0, mais vu comment le reroutage fonctionne c’est loin d’être certain (il faudrait intervenir après le reroutage, c’est devenu un peu flou pour moi depuis le temps).

Pardon, je me suis mal exprimé : pas un tunnel complet, mais du bête port-forwarding. Cela dit si tu n’as qu’un VPN à disposition et que tu ne peux pas utiliser SSH ça règle la question.

En effet si mes souvenirs sont bons le reroutage en sortie intervient après les chaînes OUTPUT. Il faudrait donc bloquer les paquets dans la chaîne POSTROUTING. Comme cette chaîne n’existe pas dans la table filter il faudrait le faire dans la table mangle, ce qui n’est pas très orthodoxe.

Une autre possibilité serait de réaliser le blocage au niveau du routage en créant une “nullroute” par défaut de faible priorité dans la table de routage alternative.

Déjà, merci pour ce tuto.

Ça semble marcher mais je bloque au niveau du marquage des paquets. Comme mon service confidentiel est lancé par un utilisateur spécifique, j’ai basé ma stratégie de routage sur le groupe de cet utilisateur. Pour tester, j’ai lancé la commande suivante :

Le connexion ne semble pas passé par le VPN. Or logiquement, la commande lancée par cet utilisateur est donc lancée par son unique groupe (non?).
Par contre, le résultat de la commande suivante est concluant :

La commande sg est-elle obligatoire même si le groupe est déjà le groupe par défaut de l’utilisateur?

J’ai voulu modifié ma stratégie de routage en se basant sur le nom d’utilisateur et non sur le groupe. Donc, pour le marquage des paquets, j’ai utilisé --uid-owner au lieu de --gid-owner. Mais ça ne marche pas.

[quote=“PascalHambourg”]Une autre possibilité serait de réaliser le blocage au niveau du routage en créant une “nullroute” par défaut de faible priorité dans la table de routage alternative.

Génial! Ça marche selon mes tests! Merci.

Bon finalement, ça marche avec la commande suivante :

Par contre, j’ai un soucis lorsque la connexion VPN est coupée. Ça ne marche plus lorsque je relance la connexion: les paquets ne sont pas ré-routés vers le chemin par défaut. Je suis obligé de redémarrer l’ordinateur.

Voilà le script lancer après l’ouverture de la connexion :

#!/bin/sh

USERGROUP=username
MARKER=78
IFACE=ppp0
IFACE_IP=$(ifconfig $IFACE | grep "inet adr" | sed 's/^.*adr:\([0-9]*.\)\.\([0-9]*.\)\.\([0-9]*.\)\.\([0-9]*.\).*$/\1.\2.\3.\4/')

# mise en place de la table de routage
ip route flush table $MARKER
ip route show table main | grep -Ev ^default | while read ROUTE; do ip route add table $MARKER $ROUTE; done
ip route add table $MARKER default dev $IFACE

# activation du routage
ip rule add fwmark $MARKER table $MARKER
ip route flush cache

# mise en place de la translation NAT
iptables -t nat -A POSTROUTING -o $IFACE -m mark --mark $MARKER -j SNAT --to-source $IFACE_IP

# marquage des paquets
iptables -t mangle -A OUTPUT -m owner --gid-owner $USERGROUP -j MARK --set-mark $MARKER

Et là, lorsque la connexion est coupée :

#!/bin/sh

USERGROUP=username
MARKER=78

ip route flush table $MARKER
ip route show table main | grep -Ev ^default | while read ROUTE; do ip route add table $MARKER $ROUTE; done
# bloquage des paquets
ip route add unreachable default metric 9999 table $MARKER

# marquage des paquets
iptables -t mangle -A OUTPUT -m owner --gid-owner $USERGROUP -j MARK --set-mark $MARKER

J’avais pensé que le problème venait du script de la déconnexion! mais si je le désactive, ça change rien.

Compare tes règles iptables lorsque ça marche et lorsque ça ne marche pas :

[code]# iptables -t nat -S

iptables -t mangle -S

iptables -t filter -S[/code]

De même que tes routes :

[code]# ip route show table main

ip route show table 78[/code]

hello
le module owner est pas fiable , je l’avais longuement tester en filtrant tout les utilisateur et tout le système certain paquet son mal identifier.

Par contre une autre solution consiste en sacrifiant du cpu ,de faire un script qui scan les processus avec leur pid et gid en bloquant par défauts, puis si la demande est faite crée une règle appropriée , je l’avais fait mai bon le souci c est que sa mange du cpu et sa laisse quand meme sujet a un ralentissement vu que quelque paquet seront bloquer avant l’ouverture. ce ralentissment n’a pas lieux si tu fait l’inverse ,tu scan pour fermer ce qui n’est pas autoriser, mai sa mange toujours du cpu.

l’autre solution est d’améliorer le module owner d’iptables,c’est open source :wink:
en identifiant le pid, ce qui était disponible a un moment mai semble abandoner ce qui est dommage, car un filtrage en sortie deviendrai vraiment utile :slightly_smiling:

ceci dit je sui pas expert reseau mai un fouineur :laughing:

Il faut bien comprendre que la correspondance owner se base sur l’UID et le GID effectifs du processus émetteur, qui peuvent être différents de l’UID et du GID de l’utilisateur ayant exécuté le processus. Par exemple la commande ping a le bit SUID, et donc les paquets qu’elle émet ont l’UID root quel que soit l’utilisateur qui l’exécute.

En effet, ça dépend du moment où l’expression entre $() est évaluée, avant ou après le su.
Entourée de guillemets doubles " ", c’est avant. Il aurait fallu l’entourer de guillemets simples ’ '.

Ton script de déconnexion n’annule pas tout ce qu’a fait le script de connexion. Il y a aussi des commandes qui n’ont pas besoin d’être exécutées à chaque lancement du VPN. Notamment la règle iptables SNAT n’est pas supprimée, donc si le VPN récupère une adresse IP différente à chaque connexion ça ne risque pas de marcher. Dans ce cas j’utiliserais plutôt la cible MASQUERADE qui est plus adaptée à cette situation.

Accessoirement, il serait beaucoup plus simple de placer ces scripts dans /etc/ppp/ip-{up,down}.d/ pour les faire exécuter automatiquement par pppd qui a le bon goût de leur passer les paramètres ($PPP_IFACE=interface, PPP_LOCAL=adresse…).

[quote=“PascalHambourg”]Ton script de déconnexion n’annule pas tout ce qu’a fait le script de connexion. Il y a aussi des commandes qui n’ont pas besoin d’être exécutées à chaque lancement du VPN. Notamment la règle iptables SNAT n’est pas supprimée, donc si le VPN récupère une adresse IP différente à chaque connexion ça ne risque pas de marcher. Dans ce cas j’utiliserais plutôt la cible MASQUERADE qui est plus adaptée à cette situation.
[/quote]
Effectivement t’as raison.
Lorsque ça marche :

root@htpc:~# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -o ppp0 -m mark --mark 0x4e -j SNAT --to-source 93.xx.xx.xx

root@htpc:~# iptables -t mangle -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A OUTPUT -m owner --gid-owner 109 -j MARK --set-xmark 0x4e/0xffffffff

Quand ça ne marche pas :

root@htpc:~# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -o ppp0 -m mark --mark 0x4e -j SNAT --to-source 93.xx.xx.xx
-A POSTROUTING -o ppp0 -m mark --mark 0x4e -j SNAT --to-source 80.xx.xx.xx

root@htpc:~# iptables -t mangle -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A OUTPUT -m owner --gid-owner 109 -j MARK --set-xmark 0x4e/0xffffffff
-A OUTPUT -m owner --gid-owner 109 -j MARK --set-xmark 0x4e/0xffffffff

Tu pourras m’expliquer ce que tu veux dire par “cible MASQUERADE”. Je ne m’y connais rien en routage/iptable. Sinon, comment réinitialiser les règles iptable?

[quote=“PascalHambourg”]
Accessoirement, il serait beaucoup plus simple de placer ces scripts dans /etc/ppp/ip-{up,down}.d/ pour les faire exécuter automatiquement par pppd qui a le bon goût de leur passer les paramètres ($PPP_IFACE=interface, PPP_LOCAL=adresse…).[/quote]
C’est ce que j’avais fait mais les scripts ne semblent pas exécuter! Je ne me suis pas encore cassé la tête sur ce problème. Du coup, je les lançais manuellement (pour le moment)

man iptables pour la définition d’une cible. SNAT est une cible, MASQUERADE une autre.
Ici, tu remplaces simplement “SNAT --to-source $IFACE_IP” par “MASQUERADE”. Et tu créées la règle une seule fois au démarrage, pas à chaque connexion du VPN (idem pour la règle iptables MARK et la règle ip rule au passage). Contrairement à une route, une règle iptables peut faire référence à une interface qui n’existe pas, et elle n’est pas effacée quand l’interface disparaît ; simplement elle ne s’appliquera à aucun paquet.

Les scripts placés là doivent obéir aux contraintes de run-parts (cf man run-parts). Notamment le nom ne doit comporter que des lettres, chiffres, tiret, underscore. Pas de point ou caractère bizarre.

Oui exacte pas de . donc un test.sh par exmple n’est pas accepté alors que test oui et ne pas oublier le droit d’execution (chmod +x ) et les scripts executés dans if-up.d sont appelés avec les parametres suivants :

Arg Name

$1 Interface name

$2 The tty

$3 The link speed

$4 Local IP number

$5 Peer IP number

$6 Optional ``ipparam’’ value foo

donc pas besoin de ta commande grep pour recupérer l’ip, utilise ceci :

MARKER='78’
IFACE=$1
IFACE_IP=$4

Je croit que tu a lu mon post sur le fil de discussion origianl de syam, un peu meme combat que toi sauf que moi j’utilise la selection par port ip en sortie et pas de groupe ou users, peut etre une piste pour toi ?

Un très grand merci à syam et à PascalHambourg!

Ça marche exactement comme je veux! :041 :041 :041

Bonne nuit les gars.

Librement,
TuxGasy

Il faut bien comprendre que la correspondance owner se base sur l’UID et le GID effectifs du processus émetteur, qui peuvent être différents de l’UID et du GID de l’utilisateur ayant exécuté le processus. Par exemple la commande ping a le bit SUID, et donc les paquets qu’elle émet ont l’UID root quel que soit l’utilisateur qui l’exécute.[/quote]
Certe ,mai j’ai fait un teste avec tout les utilisateur tirer du fichier /etc/passwd …certain paquet appartiennent a personne, même root!

La page de manuel d’iptables indique que les paquets émis par un processus du noyau n’ont pas de propriétaire.

c’est la le problème justement, et il semble que parfoit des paquet son émis et indispensable . du coup tu peux pas filtrer avec.
en revanche on peux: filtré (règle (port,ip))=<–>pid , mai la il faut aller lire les log d’iptables et utiliser inotify du kernel pour faire la relation
c’ est sur ce dernier point que le module owner est a améliorer.