WPAD

Qu'est-ce ?

Web Proxy Auto-Discovery. Découverte automatique du proxy. Il s'agit d'un protocole imaginé par Microsoft, qui permet d'effectuer automatiquement le paramétrage d'accès à l'internet de son navigateur. Ce protocole n'est bien sûr pas exempt de failles de sécurité, soyez-en conscients si vous décidez de le mettre en application.

Bien que peu sûre, cette méthode reste tout de même tellement pratique qu'elle est souvent utilisée, et que les navigateurs modernes, aussi bien Internet Explorer que Mozilla Firefox ou Konqueror savent l'exploiter.

Puisque nous devrons configurer les clients HTTP pour passer par notre proxy, une méthode automatique simplifiera grandement nos rapports avec les utilisateurs du réseau.

L'objectif à atteindre

Voyons un peu les diverses possibilités que propose Mozilla Firefox 2.x :

Par défaut, bien sûr, le butineur est configuré pour un accès direct à l'internet, mais plusieurs autres possibilités sont offertes :

Connexion manuelle

C'est probablement le meilleur moyen et aussi le plus sûr pour qui sait faire, mais allez expliquer la manip à quelques dizaines (centaines ?) d'utilisateurs débutants…

Adresse de configuration automatique du proxy

Commençons par cette méthode. Il faut créer un fichier nommé (par convention) proxy.pac à la racine d'un site de votre intranet. Ce fichier doit contenir un script (javascript) qui définit une fonction bien particulière (et une seule), qui pourra par exemple ressembler à ceci :

function FindProxyForURL(url, host)
{
    if(isPlainHostName(host) || dnsDomainIs(host, ".domaine.mrs" ))
      {
        return "DIRECT";
      } 
    else 
      {
        return "PROXY wpad.domaine.mrs:3128";
      }
}

Ce qui, traduit en français, veut dire :

fonction TrouveLeProxyPourUrl(url, host)
    {
        si il s'agit du nom de la machine locale
          ou
           de la machine dont le nom est "tests.domaine.mrs"
          ou
           de toutes les machines du domaine ".maison.mrs"
          nous voulons une connexion directe (sans proxy)

         sinon, nous utilisons le proxy "wpad.domaine.mrs" sur le port 3128
     }

Bien entendu, il est possible de faire beaucoup plus compliqué, mais ce type de scénario devrait répondre à la plupart des besoins. Normalement, le serveur http doit disposer du type mime qui correspond à l'extension .pac. C'est le cas du serveur apache fourni dans les distributions Debian :

application/x-ns-proxy-autoconfig   pac

C'est mieux, mais ce n'est pas encore assez simple. L'étape ultime serait de se contenter de cliquer sur « Détection automatique des paramètres proxy du réseau ». Pour y arriver, nous devons nous plonger un peu dans le protocole WPAD.

Les différentes documentations que l'on peut trouver sur le sujet évoquent la nécessité de disposer des structures suivantes :

  • un serveur http nommé wpad.<votre domaine.tld> (wpad.domaine.mrs dans l'exemple), qui soit en mesure de fournir un fichier proxy.pac ou wpad.dat ;
  • l'information pour que le client trouve ce fichier doit quant à elle être donnée par l'une de ces voies :
    • une option spécifique envoyée au client DHCP, ce qui nécessite l'emploi d'un serveur dhcp ;
    • une résolution DNS, ce qui nécessite de disposer d'un serveur DNS  ou, à défaut, de renseigner manuellement le fichier hosts de chaque client.

Expérience instructive

Souvent, dans la vie, rien ne vaut l'expérience. Voyons donc avec notre « sniffeur » favori, ce qu'il se passe lorsque nous demandons à notre navigateur de rechercher une configuration de proxy de façon automatique.

Nous disposons d'un réseau local, avec un serveur DNS et un domaine en bois : domaine.mrs. Tous nos clients sont configurés pour effectuer leurs résolutions de noms avec ce serveur DNS (192.168.0.250).

Le principe de la manip est simple : le sniffeur va capturer ce qu'il se passe lorsque nous configurons notre navigateur pour qu'il fasse une recherche automatique du proxy.

Mozilla Firefox 2.x (Windows comme GNU/Linux)

No. Time      Source          Destination     Protocol Info
 1  0.000000  192.168.0.10    192.168.0.250   DNS      Standard query A wpad.domaine.mrs
 2  0.001591  192.168.0.250   192.168.0.10    DNS      Standard query response, No such name

Firefox cherche à trouver l'adresse IP d'un hôte qui s'appellerait wpad.domaine.mrs. La solution DNS devrait donc pouvoir fonctionner, si ce serveur existait sur le réseau.

Internet Explorer 6 et 7 (Windows)

No. Time      Source          Destination     Protocol Info
 1  0.000000  192.168.0.10    192.168.0.250   DNS      Standard query A wpad.domaine.mrs
 2  0.001591  192.168.0.250   192.168.0.10    DNS      Standard query response, No such name

Même chose. Pour une fois, les deux navigateurs auraient ils le même comportement ? C'est plutôt une bonne nouvelle.

Konqueror (GNU/Linux)

No. Time      Source          Destination     Protocol Info
 1  0.000000  192.168.0.10    192.168.0.250   DNS      Standard query A wpad.localdomain
 2  0.001591  192.168.0.250   192.168.0.10    DNS      Standard query response, No such name

Quand même, tout n'est pas si simple, ce qui a quelque chose de réconfortant dans le dur monde de l'informatique. Konqueror recherche wpad.localdomain, alors que Firefox, sur la même machine (GNU/Linux Ubuntu 7.04), recherchait bien wpad.maison.mrs. Pourquoi donc ?

Analyse du fichier /etc/resolv.conf :

# cat /etc/resolv.conf
# generated by NetworkManager, do not edit!

search maison.mrs

nameserver 192.168.0.250

Analyse du fichier /etc/hosts :

# cat /etc/hosts
127.0.0.1       localhost.localdomain localhost  ubuntu

Si nous modifions ce fichier comme suit :

# cat /etc/hosts
127.0.0.1 localhost.domaine.mrs localhost ubuntu

Konqueror va adopter un fonctionnement normal :

No. Time      Source          Destination     Protocol Info
 1  0.000000  192.168.0.10    192.168.0.250   DNS      Standard query A wpad.domaine.mrs
 2  0.001591  192.168.0.250   192.168.0.10    DNS      Standard query response, No such name

Il n'est pas interdit de se demander pourquoi Konqueror adopte une méthode aussi tordue pour déduire le nom de domaine de la machine hôte, alors que le paramètre search du fichier resolv.conf est justement là pour donner cette information.

Bref, moyennant un minimum de précautions, les trois navigateurs adoptent le même comportement, à savoir chercher via DNS un serveur nommé wpad.maison.mrs. Donnons leur ce qu'ils demandent, en agissant sur notre DNS (ou sur nos fichiers hosts). Comme il est dit dans les docs que l'on risque d'avoir besoin d'un fichier wpad.dat sur le serveur http, autant le créer tout de suite :

ln -s /var/www/proxy.pac /var/www/wpad.dat

Nous mettons en route notre sniffeur, nous ouvrons par exemple IE7, et le configurons pour qu'il récupère sa configuration proxy de façon automatique, puis nous allons visiter, toujours par exemple, www.grenouille.com :

No. Time      Source          Destination     Protocol Info
 1  0.000000  192.168.0.10    192.168.0.250   DNS      Standard query A wpad.domaine.mrs
 2  0.001852  192.168.0.250   192.168.0.10    DNS      Standard query response CNAME tests.domaine.mrs A 192.168.0.128
 3  0.003192  192.168.0.10    192.168.0.250   DNS      Standard query A tests.domaine.mrs
 4  0.004410  192.168.0.250   192.168.0.10    DNS      Standard query response A 192.168.0.128
...
 8  0.008375  192.168.0.10    192.168.0.128   HTTP     GET /wpad.dat HTTP/1.1
...
10  0.009706  192.168.0.128   192.168.0.10    HTTP     HTTP/1.1 200 OK (chemical/x-mopac-input)
...
16  0.021575  192.168.0.10    192.168.0.128   HTTP     GET http://www.grenouille.com/ HTTP/1.1
...
19  0.025318  192.168.0.128   192.168.0.10    HTTP     HTTP/1.0 407 Proxy Authentication Required (text/html)
...
29  8.091195  192.168.0.10    192.168.0.128   HTTP     GET http://www.grenouille.com/ HTTP/1.1

IE7 commence par chercher l'adresse IP de wpad.domaine.mrs (1, 2, 3 et 4), puis il cherche à récupérer dessus le fichier wpad.dat, comme annoncé (8). Le serveur lui répond (10) :

Frame 10 (519 bytes on wire, 519 bytes captured)
...
Hypertext Transfer Protocol
    HTTP/1.1 200 OK\r\n
        Request Version: HTTP/1.1
        Response Code: 200
    Date: Sat, 02 Jun 2007 13:24:49 GMT\r\n
    Server: Apache/2.2.3 (Debian) PHP/5.2.0-10+lenny1\r\n
    Last-Modified: Sat, 02 Jun 2007 13:05:52 GMT\r\n
    ETag: "a00a61-cb-fdcd2c00"\r\n
    Accept-Ranges: bytes\r\n
    Content-Length: 203
    Content-Type: chemical/x-mopac-input\r\n
    \r\n
Media Type
    Media Type: chemical/x-mopac-input (203 bytes)

0000  00 05 5d 47 f5 c5 00 30 84 3a 8c cd 08 00 45 00   ..]G...0.:....E.
0010  01 f9 34 78 40 00 40 06 82 ac c0 a8 00 80 c0 a8   ..4x@.@.........
0020  00 0a 00 50 06 6f 50 84 34 63 29 a2 04 4d 50 18   ...P.oP.4c)..MP.
0030  16 d0 7f dc 00 00 48 54 54 50 2f 31 2e 31 20 32   ......HTTP/1.1 2
0040  30 30 20 4f 4b 0d 0a 44 61 74 65 3a 20 53 61 74   00 OK..Date: Sat
0050  2c 20 30 32 20 4a 75 6e 20 32 30 30 37 20 31 33   , 02 Jun 2007 13
0060  3a 32 34 3a 34 39 20 47 4d 54 0d 0a 53 65 72 76   :24:49 GMT..Serv
0070  65 72 3a 20 41 70 61 63 68 65 2f 32 2e 32 2e 33   er: Apache/2.2.3
0080  20 28 44 65 62 69 61 6e 29 20 50 48 50 2f 35 2e    (Debian) PHP/5.
0090  32 2e 30 2d 31 30 2b 6c 65 6e 6e 79 31 0d 0a 4c   2.0-10+lenny1..L
00a0  61 73 74 2d 4d 6f 64 69 66 69 65 64 3a 20 53 61   ast-Modified: Sa
00b0  74 2c 20 30 32 20 4a 75 6e 20 32 30 30 37 20 31   t, 02 Jun 2007 1
00c0  33 3a 30 35 3a 35 32 20 47 4d 54 0d 0a 45 54 61   3:05:52 GMT..ETa
00d0  67 3a 20 22 61 30 30 61 36 31 2d 63 62 2d 66 64   g: "a00a61-cb-fd
00e0  63 64 32 63 30 30 22 0d 0a 41 63 63 65 70 74 2d   cd2c00"..Accept-
00f0  52 61 6e 67 65 73 3a 20 62 79 74 65 73 0d 0a 43   Ranges: bytes..C
0100  6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a 20 32   ontent-Length: 2
0110  30 33 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65   03..Content-Type
0120  3a 20 63 68 65 6d 69 63 61 6c 2f 78 2d 6d 6f 70   : chemical/x-mop
0130  61 63 2d 69 6e 70 75 74 0d 0a 0d 0a 66 75 6e 63   ac-input....func
0140  74 69 6f 6e 20 46 69 6e 64 50 72 6f 78 79 46 6f   tion FindProxyFo
0150  72 55 52 4c 28 75 72 6c 2c 20 68 6f 73 74 29 0a   rURL(url, host).
0160  7b 0a 20 20 20 20 69 66 28 69 73 50 6c 61 69 6e   {.    if(isPlain
0170  48 6f 73 74 4e 61 6d 65 28 68 6f 73 74 29 20 7c   HostName(host) |
0180  7c 20 64 6e 73 44 6f 6d 61 69 6e 49 73 28 68 6f   | dnsDomainIs(ho
0190  73 74 2c 20 22 2e 6d 61 69 73 6f 6e 2e 6d 72 73   st, ".maison.mrs
01a0  22 20 29 29 0a 20 20 20 20 7b 0a 20 20 20 20 20   " )).    {.     
01b0  20 20 20 72 65 74 75 72 6e 20 22 44 49 52 45 43      return "DIREC
01c0  54 22 3b 0a 20 20 20 20 7d 20 65 6c 73 65 20 7b   T";.    } else {
01d0  0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20   .        return 
01e0  22 50 52 4f 58 59 20 77 70 61 64 2e 6d 61 69 73   "PROXY wpad.mais
01f0  6f 6e 2e 6d 72 73 3a 33 31 32 38 22 3b 0a 20 20   on.mrs:3128";.  
0200  20 20 7d 0a 7d 0a 0a                                }.}..

Nous retrouvons bien notre javascript dans la réponse. Notez le vilain Media Type: chemical/x-mopac-input qui est dû aux mime.types par défaut du système :

# cat /etc/mime.types | grep -e ' dat '
chemical/x-mopac-input                          mop mopcrt mpc dat zmt

Ce défaut ne semble pas affecter la configuration automatique qui fonctionne bien, puisque IE7 va maintenant transmettre notre requête au serveur proxy (16) :

Frame 16 (457 bytes on wire, 457 bytes captured)
...
  Hypertext Transfer Protocol
     GET http://www.grenouille.com/ HTTP/1.1\r\n
  ...

Frame 19 (1128 bytes on wire, 1128 bytes captured)
...
Hypertext Transfer Protocol
    HTTP/1.0 407 Proxy Authentication Required\r\n
...
Line-based text data: text/html
...
    <H1>ERROR</H1>
    >H2>Cache Access Denied</H2>
...
    While trying to retrieve the URL:
    <A HREF="http://www.grenouille.com/">http://www.grenouille.com/</A>
    <P>
    The following error was encountered:
    <UL>
    <LI>
    <STRONG>
    Cache Access Denied.
...
    <P>Sorry, you are not currently allowed to request:
    <PRE>    http://www.grenouille.com/</PRE>
    from this cache until you have authenticated yourself.
...
    You need to use Netscape version 2.0 or greater, or Microsoft Internet
    Explorer 3.0, or an HTTP/1.1 compliant browser for this to work.  
...

Comme nous avons requis une identification, c'est le moment de s'exécuter. Notez au passage, dans la trame 29, que le « login/password » est très facilement lisible :

Frame 29 (506 bytes on wire, 506 bytes captured)
...
Hypertext Transfer Protocol
    GET http://www.grenouille.com/ HTTP/1.1\r\n
        Request Method: GET
        Request URI: http://www.grenouille.com/
        Request Version: HTTP/1.1
    Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, 
            application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*\r\n
    Accept-Language: fr\r\n
    UA-CPU: x86\r\n
    Accept-Encoding: gzip, deflate\r\n
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n
    Proxy-Authorization: Basic dXNlcjE6cGFzc3dvcmQx\r\n
        Credentials: machin:epikoi
    Proxy-Connection: Keep-Alive\r\n
    Host: www.grenouille.com\r\n
    \r\n

La suite du dialogue se fait toujours avec le proxy, ce qui démontre bien que la configuration automatique a réussi.

Il est facile de vérifier que Firefox comme Konqueror fonctionneront également suivant ce principe. Les logs de Squid montrent clairement les requêtes des clients, avec le nom de l'utilisateur concerné, puisque nous avons ici une identification obligatoire.

Cette « configuration automatique » peut rester activée en permanence. En effet, si le serveur wpad n'est pas trouvé, ou s'il ne fournit pas de script, le navigateur enverra les requêtes directement au serveur ciblé par l'URL. A première vue, cette solution semble bien souple et bien agréable pour l'utilisateur.

Comment forcer nos utilisateurs à utiliser une telle configuration ?

Nous pouvons agir d'une part sur le routeur pour qu'il redirige tout flux sortant sur le port 80 (sauf bien sûr celui du proxy) vers notre serveur http local, et configurer celui-ci pour que la page d'accueil ainsi que l'erreur 404 affichent une explication sur la façon de configurer son navigateur.

Sécurité

Que l'euphorie de la réussite ne fasse toutefois pas oublier les questions de sécurité (pour le client surtout)…

Le système revient clairement à charger dans le navigateur un script qui va analyser les URL demandées par le client, et les transmettre, suivant le cas, à un serveur mandataire, et ce, de façon invisible pour l'utilisateur. En d'autres termes, le trafic http (et https) peut être dérouté sur un serveur intermédiaire, sans que l'utilisateur en ait connaissance. Les questions que l'on devrait se poser seront les suivantes :

  • Si nous sommes sur un réseau « de confiance » et que l'administrateur a clairement annoncé ses intentions, tout va encore à peu près pour le mieux, si l'on admet que le réseau ne peut être compromis ;
  • si nous sommes sur un réseau dont nous ne savons rien, nous ne savons pas par où nous passons (ce peut être le cas aussi avec un proxy transparent, mais ce dernier est facilement repérable, par exemple avec un tcptraceroute). Dans ce cas un indélicat pourrait facilement nous espionner ;
  • sommes nous certains que nos navigateurs sont assez sécurisés pour ne pas accepter n'importe quoi comme fonction FindProxyForURL ?

Le cas le plus intéressant serait sans doute sur un réseau wi-fi non sécurisé, ouvert à tous :-)