En dépit de nombreux progrès techniques, l'infrastructure Internet absorbe difficilement un trafic de plus en plus dense. Les proxies cache offrent une alternative séduisante à l'augmentation du débit des liaisons. Nous vous présentons Squid, une solution Open Source de qualité.
Principe
Protocole http
Détaillons les mécanismes mis en jeu lors d'une navigation sur la toile. Le protocole HTTP fixe des conventions d'échange d'objets entre serveurs et clients. Ces objets possèdent un type. Nous retrouvons les pages HTML et leurs éléments : images GIF, TIF, JPG... Une URL (Universal Ressource Locator) identifie le nom et l'emplacement d'une ressource ainsi que le protocole à respecter pour la consulter. Une URL s'écrit :
<proto>://<objet>
Squid gère les protocoles suivants (plus une ou deux antiquités) :
HTTP Hyper Text Transfer Protocol FTP File Transfer Protocol SSL Secure Socket Layer WAIS Wide Area Information Service
Squid ne gère pas les protocoles en mode non connecté, très répandus dans le domaine du multimédia (flux audio et vidéo). Dans le cas du protocole HTTP, une URL s'écrit :
http://<serveur>{:<port>}/<objet>
Ainsi, pour récupérer le contenu d'une page HTML, un client appliquera l'algorithme suivant :
Recherche de l'adresse IP de <serveur> Connexion TCP sur le port 80 ou <port> si indiqué Requêté de <objet> Itérer sur les éléments décrits dans <objet>
Prenons l'exemple de la page d'accueil du site officiel Squid. Son URL est http://www.squid-cache.org. Une simple session telnet donne accès au code HTML de cette page. Voici la requête :
telnet www.squid-cache.org 80 GET /index.html HTTP/1.0 Accept: text/html <CRLF>
Et la réponse du serveur :
HTTP/1.0 200 OK Date: Thu, 13 Jul 2000 22:12:15 GMT Server: Apache/1.3.3 (Unix) Expires: Fri, 14 Jul 2000 22:12:15 GMT Last-Modified: Wed, 05 Jul 2000 03:47:58 GMT Content-Length: 4128 Content-Type: text/html <CRLF> <HTML> <HEAD><TITLE>Squid Web Proxy Cache</TITLE></HEAD> ...
Performances
L'efficacité est moyenne. Chaque serveur est soumis à de multiples requêtes d'objets de petite taille. Dans le pire des cas, deux requêtes portant sur un même objet aboutissent à deux transferts de données. Une situation pénalisante si vous disposez d'une liaison à faible débit.
Caches locaux
Les navigateurs maintiennent une copie des objets récemment consultés dans un cache propriétaire. Cette solution n'est pas optimale. Un cache générique conçu sur un modèle client / serveur doit permettre le partage des données collectées indépendamment des applications ou des utilisateurs.
Proxies
Un proxy cache relaie les requêtes des clients. Les objets sont cachés au passage, ce qui limite le trafic.
L'exemple
Voici les caractéristiques d'Altair, le petit réseau privé de classe C ayant servi aux tests. Altair est composé de PC sous Linux équipés de cartes Ethernet à 10 Mb/s. Nous lui affectons la plage d'adresses 192.168.0.*. La passerelle se nomme Vortex. Elle possède l'adresse 192.168.0.1 et dispose d'un lien point à point intermittent vers l'Internet partagé grâce à une technique de translation d'adresses. Elle héberge également notre proxy. Nous avons opté pour une distribution Caldera Open Linux 2.3.
Compilation
Récupérez l'archive de la dernière version stable de Squid (notée x). Décompressez-la : tar -xvzf squid-x.tar.gz. Déplacez-vous dans le répertoire des sources : cd squid-x. Compilez Squid :
./configure --enable-err-language=French make all
Installation
Procédez à l'installation :
make install
L'arborescence par défaut est la suivante :
/---usr---local---squid-+-bin |-cache |-etc |-logs
Configuration
Les fichiers de configuration sont rassemblés dans le répertoire /usr/local/squid/etc. Les options par défaut assurent généralement un fonctionnement correct.
Utilisateur et groupe effectifs
Les sockets liés à des ports de numéros inférieurs à 1024 doivent être initialisés par des processus de propriétaire root. Pour des raisons de sécurité, Squid modifie ensuite utilisateur et groupe effectifs. Ajoutez les entrées suivantes au fichier squid.conf :
cache_effective_user squid cache_effective_group squid
Créez un utilisateur et un groupe squid :
groupadd -g 999 squid useradd -g squid -d /usr/local/squid squid
Port
Par défaut, Squid écoute les requêtes HTTP sur le port 3128. De nombreux FAI placent leurs proxies en écoute sur le port 8080, plus facile à mémoriser. Ajoutez éventuellement une entrée :
http_port 8080
Répertoire du cache
Les documents cachés seront stockés dans une arborescence de racine cache_dir
cache_dir ufs /usr/local/squid/cache 1024 16 256
La première constante indique la taille maximale du cache en Mo. Nous allouons 1 Go, un espace suffisant pour cacher de l'ordre de 100000 objets. Ces derniers seront stockés dans 4096 répertoires répartis sur deux niveaux. Une fonction de hachage garantit une répartition équitable des objets. Créez la racine de l'arborescence.
mkdir -m 700 /usr/local/squid/cache chown squid /usr/local/squid/cache chgrp squid /usr/local/squid/cache
Créez finalement l'arborescence :
/usr/local/squid/bin/squid -z
Les répertoires sont nommés de 00 à 0F et de 00 à FF.
Adresse de l'administrateur Squid
L'option cache_mgr précise l'adresse électronique de l'administrateur Squid. Cette personne recevra une notification en cas d'arrêt du démon. L'adresse figurera également sur les pages d'erreurs retournées aux clients.
cache_mgr squidadmin@altair.net
Adresse pour le ftp anonyme
Nous communiquerons également une adresse valide lors du téléchargement FTP sous compte anonymous.
ftp_user squidadmin@altair.net
Audit
Squid rend compte de son état dans divers fichiers placés sous /usr/local/squid/logs. Rectifiez les droits de ce répertoire.
chmod 700 /usr/local/squid/logs chown squid /usr/local/squid/logs chgrp squid /usr/local/squid/logs
L'option -k de Squid combinée au mot clé rotate force l'archivage des fichiers. Squid doit être actif au moment de l'appel :
/usr/local/squid/bin/squid -k rotate
L'option logfile_rotate définit le nombre maximum de versions archivées. Pour une sauvegarde sur un mois, à raison d'une rotation par jour :
logfile_rotate 30
Le plus simple est d'automatiser la rotation grâce au démon Cron. Voici un exemple de fichier /etc/crontab correspondant à une invocation de la commande de rotation tous les jours à deux heures du matin :
SHELL=/bin/sh MAILTO=root 0 2 * * * squid /usr/local/squid/bin/squid -k rotate
Tests
Tout est prêt pour un premier test :
/usr/local/squid/bin/squid -N -D -d 2
Le démon s'exécute normalement en tâche de fond. L'option -N interdit le passage en arrière-plan. Les sorties seront visibles de la console. L'option -D évite un test du service DNS. L'option -d fixe le niveau de détail des comptes-rendus. Voici la sortie obtenue :
2000/10/18 05:14:25| Starting Squid Cache... 2000/10/18 05:14:25| Swap maxSize 1048576 KB, estimated 7876 objects 2000/10/18 05:14:25| Target number of buckets: 157 2000/10/18 05:14:25| Using 8192 Store buckets 2000/10/18 05:14:25| Max Mem size: 8192 KB 2000/10/18 05:14:25| Max Swap size: 102400 KB 2000/10/18 05:14:25| Rebuilding storage in Cache Dir #0 (DIRTY) 2000/10/18 05:14:25| Set Current Directory to /var/spool/squid 2000/10/18 05:14:25| Loaded Icons. 2000/10/18 05:14:27| Accepting HTTP connections on port 3128, FD 35. 2000/10/18 05:14:27| Accepting ICP messages on port 3130, FD 36. 2000/10/18 05:14:27| Accepting SNMP messages on port 3401, FD 37. 2000/10/18 05:14:27| Ready to serve requests. 2000/10/18 05:14:28| storeRebuildFromDirectory: DIR #0 done! 2000/10/18 05:14:28| Finished rebuilding storage from disk. 2000/10/18 05:14:28| 0 Entries read from previous logfile. 2000/10/18 05:14:28| 0 Entries scanned from swap files. 2000/10/18 05:14:28| 0 Invalid entries. 2000/10/18 05:14:28| 0 With invalid flags. 2000/10/18 05:14:28| 0 Objects loaded. 2000/10/18 05:14:28| 0 Objects expired. 2000/10/18 05:14:28| 0 Objects cancelled. 2000/10/18 05:14:28| 0 Duplicate URLs purged. 2000/10/18 05:14:28| 0 Swapfile clashes avoided. 2000/10/18 05:14:28| Took 36 seconds ( 0.0 objects/sec). 2000/10/18 05:14:28| Beginning Validation Procedure 2000/10/18 05:14:29| storeLateRelease: released 0 objects 2000/10/18 05:14:28| Completed Validation Procedure 2000/10/18 05:14:28| Validated 0 Entries 2000/10/18 05:14:28| store_swap_size = 21k
Le démon est actif. Squid est fourni avec un client en mode texte. Connectez-vous à Internet et lancez depuis la passerelle :
/usr/local/squid/bin/client http://www.squid-cache.org
Testez ensuite une requête identique depuis une machine quelconque du réseau :
/usr/local/squid/bin/client -h 192.168.0.1 http://www.squid-cache.org
Ajoutez éventuellement l'option -p 8080.
Configuration détaillée
A partir d'ici les choses se compliquent légèrement ;-)
Taille maximale des objets en cache
Squid ne stocke les objets sur disque que si leur taille entre dans un intervalle fixé par l'administrateur :
minimum_object_size 0 KB maximum_object_size 1024 KB
Délais
Squid se connecte aux serveurs selon l'algorithme présenté dans la section précédente. Il est nécessaire d'établir des délais au delà desquels Squid considérera qu'une transaction a échoué. Ceci vaut pour l'établissement des connexions, l'envoi des requêtes et la réception des résultats.
connect_timeout 30 seconds request_timeout 30 seconds read_timeout 2 minutes
Complétez éventuellement les requêtes interrompues par les utilisateurs. Fixez les seuils en fonction du débit de votre réseau :
quick_abort_min 10 KB quick_abort_max 10 KB quick_abort_pct 90
Résolution DNS
Des processus spécifiques assurent la traduction noms de serveurs <-> adresse IP. Leur nombre est à choisir en fonction de la charge en pointe de votre réseau :
dns_children 10
Ces processus ne traitent pas directement les délais d'expiration (TTL) fournis par les serveurs de noms. Les correspondances sont stockées dans deux caches. Des constantes précisent quand ces données deviennent obsolètes :
positive_dns_ttl 24 hours negative_dns_ttl 5 minutes
Sécurité
Il est recommandé de limiter l'accès du proxy aux machines de votre réseau. A cet effet, Squid propose les ACL (Access Classes Lists) et les ACO (Access Classes Operators). Une liste regroupe un ensemble de propriétés des requêtes :
acl manager proto cache_object acl src_localhost src 127.0.0.1/255.255.255.255 acl src_reseau_altair src 192.168.0.0/255.255.255.0 acl all src 0.0.0.0/0.0.0.0
Nous décrivons ici les machines du réseau Altair et le gestionnaire du cache. Lors du test d'une règle A/M, on opère un ET logique entre l'adresse candidate C et le masque M puis on compare le résultat et A. Le résultat est positif si A = C . M. Reste à définir les droits d'accès à appliquer aux listes précédentes :
http_acces allow manager localhost http_acces deny manager http_acces allow src_localhost http_acces allow src_reseau_altair icp_access deny all
Attention : Les éléments d'une liste sont combinés avec des OU logiques, les prémisses d'une règle avec des ET logiques. Les règles sont lues en séquence. L'accès est autorisé par défaut. Une règle *au plus* est appliquée pour chaque type de contrôle (http_access, ftp_access ...). Si aucune règle ne s'applique à un candidat, l'action *opposée* à celle de la *dernière* règle lue s'impose. Par exemple :
A allow X A deny Y A deny X A allow Y Z -> allow Z -> deny
En étudiant le fichier de configuration, vous constaterez la présence des règles supplémentaires :
acl SSL_ports port 443 563 acl Safe_ports port 21 70 80 210 280 443 488 563 591 777 1025-65535 acl CONNECT method CONNECT http_access deny !Safe_ports http_access deny CONNECT !SSL_ports
Ces règles évitent qu'un utilisateur mal intentionné n'exploite votre proxy à la manière d'un tunnel pour requérir des services interdits. Limitez la taille des requêtes pour restreindre les risques d'attaques de type "refus de service".
request_header_max_size 10 KB request_body_max_size 64 KB
Anonymat
Préservez l'anonymat des utilisateurs en masquant une partie des adresses source des requêtes :
client_netmask 255.255.255.0
Ici, nous masquons la section machine des adresses IP de notre réseau de classe C. De plus, vous pouvez filtrer certains champs des en-têtes de requêtes générés par les clients :
anomyze_headers deny Referer Server From User-Agent
Ici, nous masquons l'adresse électronique et la description du client. Nous masquons également la ressource URL à partir de laquelle l'utilisateur a sélectionné la ressource interrogée. Certains serveurs réclamant l'identification du programme client, nous ajoutons l'option :
fake_user_agent Nutscrape/1.0 (CP/M; 8-bit)
L'option strip_query_terms activée par défaut évite que les paramètres des requêtes adressées par exemple à un moteur de recherche ne soient archivés.
Filtrage
Un filtrage judicieux garantit une bonne répartition du trafic, ce en accord avec la politique d'administration de votre serveur. Les ACO permettent un filtrage sur la base d'expressions rationnelles appliquées aux URL. Par exemple, pour interdire le chargement de fichiers MP3 :
acl url_mp3 url_regex -i \.mp3$ http_access deny url_mp3
Pour limiter la taille des objets importés à 1 Mo :
reply_body_max_size 1024 KB
Plus radicalement, vous pouvez filtrer un protocole ou un domaine entier :
acl proto_ftp proto ftp acl dom_tucows dstdom_regex -i tucows http_access deny proto_ftp http_access deny dom_tucows
Hiérarchie des fichiers
Plusieurs caches peuvent collaborer. Ainsi, Renater, organisme fédérant les réseaux des universités dispose d'un cache national hébergé sur le campus de Jussieu et de caches régionaux. Cette hiérarchie augmente le nombre de documents cachés. Squid intègre des mécanismes autorisant une telle collaboration. Le protocole ICP (Inter-Cache Protocol) permet d'interroger un cache sur la présence d'un objet particulier (HIT / MISS). Ces requêtes se font généralement sur le port 3130. Les résumés de caches (cache digests) permettent l'échange d'index entiers. Deux caches voisins (sibling caches) n'échangent que les objets qu'ils possèdent. Un cache père (parent cache) accepte de récupérer un objet qu'il ne possède pas pour un de ses caches fils. Nous allons envisager deux cas d'école.
Raccordement au cache d'un FAI
Dans ce cas, toute requête aboutissant à un échec au niveau du cache local est adressée à un cache père.
cache_peer proxy.fai.fr parent 8080 0 default no-query prefer_direct off
Nous correspondons avec un proxy.fai.fr sur le port 8080 (default). Nous n'utilisons pas ICP (no-query) et souhaitons contacter prioritairement le proxy père (prefer_direct off). Pour obtenir "proxy.fai.fr" vous pouvez faire un nslookup fai.fr puis ensuite utiliser la commande dig @ip_du_ns_du_fai fai.fr AXFR | less. Restera plus qu'a choisir un proxy ou cache proche de chez vous.
Collaboration des deux caches
Si votre réseau est de taille importante, vous pouvez répartir la charge entre plusieurs proxies. Cette technique nécessite la configuration d'un serveur de noms. Supposons que notre second cache soit hébergé par la machine Krell d'adresse 192.168.0.2. Nous ajoutons deux enregistrements à la zone altair.net.
proxy A 192.168.0.1 proxy A 192.168.0.2
Les navigateurs pointent vers proxy.altair.net. Lors d'une résolution de noms, la librairie Resolver retournera alternativement l'une des deux adresses. Nous installons Squid sur Krell et créons les entrées :
cache_peer vortex.altair.net sibling 3128 3130 proxy-only acl src_vortex src 192.168.0.1/255.255.255.255 icp_access allow src_vortex
Et sur Vortex :
cache_peer krell.altair.net sibling 3128 3130 proxy-only acl src_krell src 192.168.0.2/255.255.255.255 icp_access allow src_krell
L'option proxy-only bloque le stockage en cache local d'un résultat récupéré depuis un cache frère. Nous augmentons ainsi le nombre total d'objets stockés.
Serveur http local
Supposons que notre réseau dispose d'un serveur Web hébergé localement. Il serait inefficace de relayer des requêtes HTTP ou CGI destinées à ce serveur vers un proxy extérieur.
acl dst_localhost dst 127.0.0.1/255.255.255.255 acl dst_reseau_altair dst 192.168.0.0/255.255.255.0 always_direct allow dst_localhost always_direct allow dst_reseau_altair hierarchy_stoplist cgi-bin ?
De plus nous ne souhaitons pas cacher ces documents :
acl cgi urlpath_regex cgi-bin \? no_cache deny cgi no_cache deny dst_localhost no_cache deny dst_reseau_altair
Matériel
Se pose la question des caractéristiques de la machine hébergeant le cache :
- Puissance processeur
- Capacité, temps d'accès et débit disque
Supposons par exemple que vous disposiez d'une liaison ISDN à 64 kb/s. Cette ligne est utilisée une dizaine d'heures par jour, soit un transfert théorique d'environ 200 Mo/j. Un disque de 1 Go stockera les données sur 5 jours. Ceci est une estimation au pire, le cache ayant pour fonction de limiter le recours à la liaison Internet. Un objet pèse en moyenne 10 ko. Le cache stockera donc environ 100 000 objets. Chaque objet occupe 75 octets de RAM dans l'index de Squid, soit 6 Mo. Multiplions cette valeur par 3 pour tenir compte des caches dédiés aux objets en transit et aux correspondances nom <-> adresse IP de serveurs. Un total de 16 Mo devrait éviter le recours au swap.
cache_mem 16 MB
Estimons à 10 requêtes par seconde la charge de Squid en pic. Un Pentium à 133 MHz devrait suffire à satisfaire cette demande. Concernant le disque, le débit est moins primordial que le temps d'accès. Avec un temps d'accès de 12 ms, vous pouvez servir de l'ordre de 100 requêtes par seconde.
Statistiques
Un script CGI nommé cachemgr.cgi retourne des statistiques sur l'activité de Squid. Vous pouvez l'activer en installant un serveur Web de type Apache. Typiquement, le script sera copié ici :
cp /usr/local/squid/bin/cachemgr.cgi /home/httpd/cgi-bin
Et accessible à l'adresse http://localhost/cgi-bin/cachemgr.cgi. Définissez un mot de passe pour en protéger l'accès :
cachemgr_passwd ****** all
Lancement automatique
Une simple ligne dans le fichier /etc/rc.d/rc.local suffit.
/usr/local/squid/bin/squid -D
Squid crée deux processus. Le processus fils gère le cache. Le processus père surveille l'activité du processus fils et le relance si nécessaire.
pstree init-+-booter . . -squid---squid---unlinkd
L'interruption du démon pour maintenance se fera proprement par un appel /usr/local/squid/bin/squid -k shutdown
Configuration des navigateurs
La configuration des navigateurs est triviale.
Netscape navigator & Communicator
Ouvrez le menu "Edit / Preferences", Développez le menu "Advanced". Sélectionnez l'entrée "Proxies". Activez le bouton radio "Manual proxy configuration" puis "View". Renseignez les champs "FTP Proxy" et "HTTP Proxy". Le nom est du type proxy.mon.fail. A défaut, indiquez son adresse IP. Le numéro de port est probablement le 8080. Sélectionnez l'entrée Cache. Passez la capacité "Disk Cache" à 0. Cliquez le bouton "Clear Disk Cache".
Lynx
Sous Bourne Again Shell, exportez les variables
export ftp_proxy="http://proxy.mon.fai:8080/" export http_proxy="http://proxy.mon.fai:8080/"
Conclusion
Squid est un logiciel proposant des fonctionnalités nombreuses et configurables dans leurs moindres détails. Consultez la documentation en ligne pour une étude approfondie. Vous apprendrez à moduler la charge supportée par vos proxies, fixer des priorités par type de trafic, modifier l'algorithme de stockage des objets en cache, etc.