28Mar

Forcer une application à utiliser une interface réseau donnée sur GNU/Linux (ou comment utiliser deux connexions Internet en même temps)

Par , 28 mars 2013 | GNU/Linux, Informatique | 0 Commentaire

J'habite dans un endroit recu­lé que n'a pas encore atteint la civi­li­sa­tion des Lol­cats. Com­pre­nez par là que dans mon coin, les connexions Inter­net culminent à un fara­mi­neux 2Mbps quand tout fonc­tionne bien et qu'on n'est pas trop loin de son DSLAM. Pour ceux qui ne visua­lisent pas bien, cela donne en moyenne et selon les opé­ra­teurs dans les 250 kio/s en down­load et de 10 à 25 kio/s en upload. Oui, je sais, c'est ridi­cule dans la France du XXIe siècle.

En atten­dant l'hypothétique jour où cela chan­ge­ra, cette situa­tion peut se révé­ler fran­che­ment gênante dès lors que vous faites autre chose que mettre à jour votre sta­tut sur un réseau social ou lire vos emails. À pro­pos d'emails, je vous laisse ima­gi­ner les dif­fi­cul­tés pour envoyer le moindre mes­sage pour­vu d'une pièce jointe de 100 kio, ça peut être assez folk­lo­rique. Si en plus vous êtes en train de télé­char­ger le film de vacances de votre grand-mère qu'elle a gra­cieu­se­ment mis à votre dis­po­si­tion sur le FTP fami­lial, c'est la cata ! Vous n'avez plus comme solu­tion que de mettre le télé­char­ge­ment en pause le temps de vaquer à votre occu­pa­tion, qu'elle soit d'envoyer un email ou sim­ple­ment affi­cher un site en moins de 20s, parce que voir votre navi­ga­teur mou­li­ner aus­si long­temps pour sim­ple­ment affi­cher duckduckgo.com, c'est über-frustrant.

Fort heu­reu­se­ment, j'ai la chance d'avoir pour voi­sine une dame ado­rable en plus d'être pour­vue d'une connexion Inter­net et de faire de déli­cieuses pâtis­se­ries. Cette gente dame m'a fort cour­toi­se­ment auto­ri­sé à uti­li­ser son Wifi à dis­cré­tion, elle même n'utilisant que très peu sa connexion Inter­net. Je me retrouve donc avec deux connexions à Inter­net : la mienne chez OVH que j'utilise en ether­net depuis mon PC prin­ci­pal et la sienne chez Orange, que je vais uti­li­ser en Wifi tou­jours depuis mon PC prin­ci­pal. C'est pra­tique en cas de besoin, c'est à dire si ma connexion venait à fail lamen­ta­ble­ment, mais pas que : et si j'utilisais sa connexion pour télé­char­ger ledit film de vacances de mon aïeule afin de pou­voir uti­li­ser la mienne tran­quille­ment pen­dant ce temps là ? En voi­là une idée qu'elle est bonne ! Voyons donc par quel miracle du dieu Rou­tage ceci peut être réalisé :

Pré-requis

— par défaut en France, les box des opé­ra­teurs uti­lisent pour leur adres­sage pri­vé des adresses de la RFC 1918, à savoir 192.168.x.x. Or, si l'on veut pou­voir réa­li­ser les opé­ra­tions qui suivent, il faut que les deux box ne soient pas sur le même réseau. Je n'aborderai pas ici com­ment confi­gu­rer sa box ou son rou­teur, sachez sim­ple­ment que pour évi­ter des désa­gré­ments à ma chère voi­sine je n'ai pas tou­ché à la confi­gu­ra­tion de sa Live­box, qui uti­lise donc la plage d'adresses 192.168.1.x. J'ai fait les modi­fi­ca­tions néces­saires sur mon rou­teur afin d'utiliser, de mon côté, une plage d'adresses en 172.16.x.x.
— afin d'utiliser cer­taines des com­mandes qui suivent, vous devez dis­po­ser du paquet net-tools, que je vous laisse ins­tal­ler selon votre dis­tri­bu­tion (il l'est sûre­ment déjà, ceci dit)
— ma solu­tion uti­lise iptables. Vous devez donc dis­po­ser d'iptables dans votre dis­tri­bu­tion. À ma connais­sance, c'est le cas.

Mise en œuvre

Il y a plu­sieurs solu­tions pour arri­ver au résul­tat vou­lu, mais j'ai rete­nu celle qui consiste à créer un uti­li­sa­teur qui ser­vi­ra à lan­cer les appli­ca­tions à rou­ter vers le Wifi de ma voi­sine. J'aurais pu aus­si me baser sur le PID du pro­ces­sus de l'application, mais les PID sont chan­geants. J'aurais pu, sinon, uti­li­ser un fil­trage basé sur le port de connexion mais je pré­fère avoir la liber­té de lan­cer deux fois l'application simul­ta­né­ment mais qu'une seule des deux ins­tances soit routée.

Pour com­men­cer, on crée donc cet uti­li­sa­teur spé­cial, sans shell ni réper­toire personnel :

# adduser --shell /bin/false --no-create-home rtuser

Ensuite, il faut créer une table de rou­tage qui ser­vi­ra à rece­voir la règle de rou­tage des paquets géné­rés par notre rtu­ser nou­vel­le­ment créé :

# echo 200 wlan-route >> /etc/iproute2/rt_tables

Ceci fait, on crée la règle qui rou­te­ra les paquets. L'IP pas­se­relle de la Live­box est 192.168.1.1 et l'interface qui me sert à m'y connec­ter est wlan0 :

# ip route add default via 192.168.1.1 dev wlan0 table wlan-route

Main­te­nant, on crée une règle per­met­tant de rou­ter les paquets mar­qués d'un 1 vers notre nou­velle table de routage :

# ip rule add fwmark 0x1 table wlan-route

Enfin, il faut créer les règles de rou­tage dans iptables :

# iptables -t mangle -A OUTPUT -o eth0 -p TCP -m owner --uid-owner rtuser -j MARK --set-mark 0x1
# iptables -t nat -A POSTROUTING -o wlan0 -p TCP -j SNAT --to 192.168.1.13
— La pre­mière règle marque les paquets TCP issus de mon inter­face eth0 (celle qui est connec­tée à mon rou­teur, sur ma connexion) et appar­te­nant à l'utilisateur rtu­ser d'un 1
— La deuxième règle per­met de rou­ter cor­rec­te­ment les paquets qui reviennent vers la machine, sinon les réponses aux paquets envoyés via la connexion de ma voi­sine (wlan0) arri­ve­raient sur l'autre inter­face (eth0) qui ne sau­rait donc pas quoi en faire… 192.168.1.13 est l'adresse IP locale avec laquelle je suis connec­té à la Live­box. Concrè­te­ment, donc, tous les paquets pro­ve­nant d'applications lan­cées par rtu­ser se ver­ront mar­qués d'un 1. Ensuite, les règles feront que tous les paquets mar­qués d'un 1 seront envoyés via wlan0 (la Live­box de ma voi­sine) au lieu d'eth0 (mon rou­teur OVH). On peut véri­fier que tout est bien en place :
# ip route show table wlan-route
default via 192.168.1.1 dev wlan0

# ip rule show
0:    from all lookup local
32765:    from all fwmark 0x1 lookup wlan-route
32766:    from all lookup main
32767:    from all lookup default

# iptables -L -t mangle
[…]
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
MARK       tcp  --  anywhere             anywhere             owner UID match fzuser MARK set 0x1
[…]

# iptables -L -t nat
[…]
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       tcp  --  anywhere             anywhere             to:192.168.1.13

Main­te­nant, il va fal­loir désac­ti­ver la pro­tec­tion du ker­nel contre l'IP spoo­fing, sinon ça ne fonc­tion­ne­ra pas, malheureusement :

# for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
# echo 1 > /proc/sys/net/ipv4/route/flush

Véri­fions que rtu­ser passe effec­ti­ve­ment par la connexion inter­net de ma voisine :

$ curl ip.appspot.com
109.190.x.x
$ sudo -u rtuser curl ip.appspot.com
86.219.x.x

L'IP publique de rtu­ser est donc bien celle de ma voi­sine. Je peux main­te­nant lan­cer File­Zilla en tant que rtu­ser afin d'utiliser cette seconde connexion pour télé­char­ger le film de mamie en lais­sant la mienne libre pour le reste :

$ sudo -u rtuser filezilla

Il est fort pos­sible que rtu­ser ne soit pas auto­ri­sé à lan­cer d'applications gra­phiques. Pour y remé­dier, il suf­fit de lan­cer un petit

$ xhost +local:rtuser

et voi­là !

Pour aller plus loin

Cette solu­tion est bien évi­dem­ment très imparfaite :
— elle ne résiste pas à une perte de connexion Wifi : dans ce cas, la règle dans la route wlan-route dis­pa­raît et la connexion bas­cule sur eth0, la connexion par défaut. Il faut donc recréer la règle après s'être reconnecté.
— elle ne per­siste pas après un reboot : la route dis­pa­raît et les règles iptables sont effacées.
Il y a des solu­tions faciles à mettre en œuvre pour évi­ter ces désa­gré­ments mais dans la mesure où je ne compte uti­li­ser cette astuce que ponc­tuel­le­ment, je ne les abor­de­rai pas ici. Juste, pour finir, un petit script qui fait tout ce qui pré­cède d'un seul coup, à rendre exé­cu­table et à lan­cer en tant que root :
#!/bin/bash
#~ Configuration ~#
# Table de routage vers laquelle le traffic sera redirigé
RT_TABLE="wlan-route"
# L'utilisateur qui va lancer les applications redirigées
RT_USER="rtuser"
# Nom de l'interface sur laquelle le trafic sera redirigé
IFACE_D="wlan0"
# Nom de l'interface depuis laquelle le trafic sera redirigé
IFACE_O="eth0"
# Adresse IP LAN sur l'interface visée
IP_LOCAL=`ifconfig $IFACE_D | grep 'inet adr:' | cut -d: -f2 | cut -d" " -f1`
# Adresse IP de la passerelle sur l'interface visée
IP_GW="192.168.1.1"

#~ Rien à modifier ci-dessous ~#
echo 200 $RT_TABLE >> /etc/iproute2/rt_tables
ip rule add fwmark 0x1 table $RT_TABLE
ip route add default via $IP_GW dev $IFACE_D table $RT_TABLE
iptables -t mangle -A OUTPUT -o $IFACE_O -p TCP -m owner --uid-owner $RT_USER -j MARK --set-mark 0x1
iptables -t nat -A POSTROUTING -o $IFACE_D -p TCP -j SNAT --to $IP_LOCAL
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
echo 1 > /proc/sys/net/ipv4/route/flush

Pho­to zigazou76

Back to top

Pas peur d'Hadopi

Ce site Web est accessible en




ipv6 ready