P... de proxy, le retour

GNU/Linux Magazine n° 152 | septembre 2012 | Dominique Dumont
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
L'article « P... de proxy» a expliqué comment utiliser tinyproxy pour se simplifier la vie sur un ordinateur nomade. Cette suite (c'est la mode au cinéma) va expliquer comment étendre la solution proposée pour gérer d'autres proxys (genre proxy-cache pour serveur de paquets) et surtout faire une commutation automatique de proxy pour atteindre le Saint-Graal des hackers : la machine s'occupe de tout et moi de rien :-)

1. Résumé de l'épisode précédent

Dans GNU/Linux Mag 149, William Daniau et Julien Garcia nous ont expliqué comment configurer tinyproxy pour s'en servir de proxy « maître ». En gros, il faut :

- Installer et configurer tinyproxy avec les différents proxys utilisés.

- Configurer toutes les applications pour pointer sur ce proxy local.

- Reconfigurer et redémarrer tiniproxy en cas de changement d'environnement. Cette dernière tâche étant effectuée par un script init.d modifié.

2. Fort bien, mais ce n'est pas si simple...

En tant que développeur Debian, j'utilise la version Sid, dite « instable » qui a pour caractéristique de proposer souvent des mises à jour. Il n'est pas rare de télécharger 500MB de paquets par semaine et par machine. Pour éviter des téléchargements successifs sur ADSL (parfois poussif), l'utilisation d'un cache de paquets est recommandée : une machine télécharge à 300kB/s à partir du serveur distant et les autres machines téléchargent à 10MB/s à partir du cache local.

Ce cache de paquets (apt-cacher-ng) est utilisé par le gestionnaire de paquets (apt) et par les outils de construction de paquets en environnement minimal (pbuilder et cowbuilder utlisent un «chroot»).

En fonction de ma situation géographique, apt-cacher-ng et pbuilder doivent être configurés différemment :

- au boulot : le proxy est celui de l'entreprise ;

- à la maison : le proxy est le proxy cache de ma machine principale ;

- ailleurs : pas de proxy.

Au total, 3 fichiers de configuration doivent être modifiés en fonction de la géographie : 1 pour pbuilder, 1 pour apt-cache-ng et 1 pour tinyproxy. Soit 9 fichiers à manipuler pour gérer les alternatives les jours de proxy-boulot-dodo. Heureusement, update-alternatives sait très bien faire ça.

3. Gestion des cas de figure avec update-alternatives

update-alternatives est un petit utilitaire bien pratique : il a été conçu pour régler un problème apparemment simple : sachant qu'une fonctionnalité (java par exemple) peut être fournie par plusieurs programmes (celui d'OpenJDK, de Sun ou autres), quels sont le chemin et nom du programme qui fourniront cette fonctionnalité sur telle ou telle machine ?

Pour répondre à cette question, update-alternatives va gérer un ensemble de liens symboliques qui vont pointer du nom générique (/usr/bin/java) vers le programme réel (/usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java). update-alternatives fournit les commandes nécessaires pour installer (option --install), afficher (--display), et changer (--config) les alternatives de Java.

Comme il n'y a pas que Java dans la vie, voici un autre exemple avec les alternatives pour x-www-browser :

$ update-alternatives --display x-www-browser

x-www-browser - auto mode

link currently points to /usr/bin/konqueror

/usr/bin/epiphany-browser - priority 85

slave x-www-browser.1.gz: /usr/share/man/man1/epiphany-browser.1.gz

/usr/bin/iceweasel - priority 70

slave x-www-browser.1.gz: /usr/share/man/man1/iceweasel.1.gz

/usr/bin/konqueror - priority 100

slave x-www-browser.1.gz: /usr/share/man/man1/konqueror.1.gz

Current 'best' version is '/usr/bin/konqueror'.

Ceux qui suivent auront noté que la documentation (man pages) est gérée en mode « esclave » en même temps que les programmes : le choix d'une alternative d'un programme sera suivi d'un changement correspondant sur la documentation.

On va détourner un peu l'utilisation de update-alternatives pour gérer des fichiers de configuration (au lieu de gérer des programmes).

On va définir les fichiers de configuration pour 3 zones géographiques (boulot, maison et dehors) :

1. On copie /etc/tinyproxy.conf dans :

- /etc/tinyproxy.conf.bouloten ajoutant une ligne avec upstream web-proxy:8080 (à vous de voir quel proxy utiliser pour votre boulot) ;

- /etc/tinyproxy.conf.maison et /etc/tinyproxy.conf.dehors sans modification.

2. Pareil pour /etc/pbuilderrc :

- /etc/pbuilderrc.boulot avec export http_proxy=http://web-proxy:8080/ ;

- /etc/pbuilderrc.maison avec export http_proxy=http://192.168.0.2:3142 (3142 étant le port d'écoute de apt-cacher-ng) ;

- /etc/pbuilderrc.dehors sans modification.

3. Et pour /etc/ apt/apt.conf :

- /etc/apt/apt.conf.boulot avec Acquire::http::Proxy "http://web-proxy:8080"; ;

- /etc/apt/apt.conf.maison avec Acquire::http::Proxy "http://192.168.0.2:3142"; ;

- /etc/apt/apt.conf.dehors sans rien.

Une fois ces fichiers créés, il faut supprimer les fichiers cibles (tinyproxy.conf, pbuilderrc et apt.conf) pour que update-alternatives puisse créer ses liens symboliques.

On va maintenant définir la première alternative en utilisant tinyproxy.conf comme maître (avec l'option --install) et les autres fichiers en esclave (avec l'option --slave) :

$ sudo update-alternatives --install /etc/tinyproxy.conf tinyproxy.conf /etc/tinyproxy.conf.maison 10 --slave /etc/apt/apt.conf apt.conf /etc/apt/apt.conf.maison --slave /etc/pbuilderrc pbuilderrc /etc/pbuilderrc.maison

Ensuite, on définit les autres alternatives d'une manière similaire, (attention, les 2 paramètres après l'option --install sont les mêmes qu'avec la première commande) :

$ sudo update-alternatives --install /etc/tinyproxy.conf tinyproxy.conf /etc/tinyproxy.conf.boulot 10 --slave /etc/apt/apt.conf apt.conf /etc/apt/apt.conf.boulot --slave /etc/pbuilderrc pbuilderrc /etc/pbuilderrc.boulot

$ sudo update-alternatives --install /etc/tinyproxy.conf tinyproxy.conf /etc/tinyproxy.conf.dehors 10 --slave /etc/apt/apt.conf apt.conf /etc/apt/apt.conf.dehors --slave /etc/pbuilderrc pbuilderrc /etc/pbuilderrc.dehors

La priorité est la même pour toutes et fixée à 10 (cela aurait pu être 42).

Une fois que tout est en place, une seule commande suffit pour changer les 3 fichiers :

$ sudo update-alternatives --config tinyproxy.conf

[sudo] password for domi:

There are 3 choices for the alternative tinyproxy.conf (providing /etc/tinyproxy.conf).

Selection Path Priority Status

------------------------------------------------------------

0 /etc/tinyproxy.conf.boulot 10 auto mode

* 1            /etc/tinyproxy.conf.boulot   10        manual mode

2 /etc/tinyproxy.conf.dehors 10 manual mode

3 /etc/tinyproxy.conf.maison 10 manual mode

Press enter to keep the current choice[*], or type selection number:

Et si on oublie de relancer tinyproxy après ces manipulations, on restera perplexe devant les messages d'erreur de Firefox. Étant distrait, la solution basée sur update-alternatives suivie du redémarrage de tinyproxy ne me suffisait pas.

4. Réglage automatique du proxy avec NetworkManager

Sachant que votre distribution préférée est capable de lancer des scripts dès qu'une interface réseau est activée (ou désactivée), pourquoi ne pas en profiter pour automatiser les changements de proxy ?

Il faut juste trouver :

1. Quel programme gère les interfaces réseau (NetworkManager dans mon cas).

2. Où on peut ajouter un script qui sera lancé par le gestionnaire des interfaces. Sous Debian, c'est dans /etc/network/if-up.d/ (qui est aussi utilisé par NetworkManager et par la solution canonique de Debian pour gérer les réseaux : ifup, du paquet ifupdown).

3. Quel critère utiliser pour que le script sache quelle alternative utiliser.

4. Comment récupérer cette information.

Pour décider quel proxy utiliser, le plus simple est d'utiliser l’adresse IP donnée par le serveur DHCP quand la machine se connecte :

- 192.168.0.0/24 : on est à la maison ;

- 11.12.13.0/24 : c'est le boulot ;

- autre : on est dehors.

Reste à récupérer cette adresse IP. La page de manuel « interface(5) » précise dans quel contexte est appelé un script installé dans le répertoire /etc/network/if-up.d/ : la variable d'environnement IFACE contient le nom de l'interface réseau configurée. Une fois qu'on a l'interface eth0, on peut lancer ifconfig pour récupérer son adresse IP et ensuite configurer le proxy.

Je vous propose un petit script Perl pour faire cette tâche (cela pourrait très bien être du shell, mais l'auteur est nul en shell). Ce script sera nommé tiny-proxy-switch (peu importe le nom, il faut juste ne pas oublier de le rendre exécutable).

On commence par du standard, les déclarations habituelles et l'importation de quelques modules :

#!/usr/bin/perl

use IO::Pipe ;

use 5.10.1 ; # nécessaire pour utiliser given et say

use Sys::Syslog qw(:standard :macros);

Ensuite, on récupère le nom de l'interface contenue dans la variable d'environnement IFACE. En Perl, celle-ci est contenue dans le dictionnaire (« hash ») spécial %ENV :

my $iface = $ENV{IFACE};

Il est de bon ton de sortir discrètement du script si l'interface n'est pas eth0 :

exit 0 unless $iface =~ /eth0/;

Dans son contexte d’exécution normal (c'est-à-dire lancé par NetworkManager en arrière-plan, « background » en VO), ce script n'a pas de terminal pour afficher ce qui se passe, l'utilisation de syslog est fortement recommandée pour que le petit script puisse s'exprimer.

Pour ce faire, il faut d'abord ouvrir le canal de communication vers syslog avec un appel à openlog. Cet appel est paramétré pour assurer que tous les logs générés dans ce script indiqueront tiny-proxy-switch en début de ligne. (On aurait aussi pu mettre $0, mais c'est moins lisible) :

openlog('tiny-proxy-switch', "", "user");

IO::Pipe est un module bien pratique pour lancer des programmes en arrière-plan et récupérer leur sortie standard. Pour récupérer l'adresse IP de l'interface eth0, la commande ifconfig et ses paramètres sont passés à la méthode readerfournie par IO::Pipe :

my $pipe = IO::Pipe->new();

$pipe->reader('/sbin/ifconfig' , $iface);

Ensuite, la méthode getline va récupérer une par une les lignes produites par ifconfig :

while (my $line = $pipe->getline) {

La ligne suivante est un peu plus compliquée. Le contenu de la variable $line est testé (opérateur « =~ ») avec une expression régulière contenue entre les « / ». Si cette ligne ne contient pas inet addr, l'adresse IP ne s'y trouve pas et on passe à la ligne suivante en sautant la fin de la boucle (avec next unless) :

next unless $line =~ /inet addr:([\d\.]+)/ ;

Si la ligne passe le test, l'adresse IP est capturée par le sous-motif ([\d\.]+) et est disponible dans la variable spéciale $1 (voir la page de manuel perlre pour plus de détails) :

my $ip = $1 ;

En fonction de la valeur de cette adresse IP, on construit le chemin alternatif pour tinyproxy (configuré en maître pour update-alternatives) :

my $target = '/etc/tinyproxy.conf.' ;

given ($ip) {

when (/^16\./) { $target .= 'boulot' }

when (/^192\.168\.0\./) { $target .= 'maison' }

default { $target .= 'dehors' }

}

Par pur instinct de conservation, on n'oublie pas d'informer l'administrateur du système :

syslog(info => "tiny-proxy-switch: switch $iface -> $target") ; # ayé BOFH est prévenu

Et enfin, on lance le programme update-alternatives à travers la fonction system de Perl, et on ferme la boucle while :

system('update-alternatives', '--set', 'tinyproxy.conf', $target) ;

} # while getline

Et on n'oublie pas de redémarrer tinyproxy

syslog(info => "tiny-proxy-switch: restarting tiny-proxy") ;

system ('/etc/init.d/tinyproxy', 'restart');

Et voilà, c'est fini. Il ne reste plus qu'à faire le ménage avant de partir :

$pipe->close ;

closelog ;

Conclusion et limitations

Une fois que tout est en place, vous n'aurez plus à vous soucier des proxys. NetworkManager va relancer le script dans tous les cas de figure, que ce soit redémarrage, réveil après hibernation, ou tout simplement connexion du câble LAN ou du Wi-Fi.

Le seul point délicat est le critère basé sur les adresses IP : les adresses en 192.168.0.* sont très souvent utilisées. Toutefois, si le script se trompe, vous pourrez toujours basculer sur le bon proxy avec update-alternatives... Ah oui, et sans oublier de redémarrer tiny-proxy...

Tags : Perl, proxy