47. Application sur le proxy HTTP Squid

47.1. Travaux pratiques : installation de SQUID

47.1.1. Application

Pour cette partie, il est impératif de maîtriser les technique de routage avec netfilter.

Le but est d'installer un service proxy minimal, configurer les clients et de tester le fonctionnement de l'accès à internet à partir de ces derniers.

La première étape consistera à configurer les ACLs permettant un contrôle d'accès aux données externes, ensuite l'on fera évoluer la configuration vers un serveur proxy transparent.

Le service proxy sera installé sur le routeur.

47.1.2. Préparation de la maquette

On dispose d'un routeur en interface entre l’accès internet et un client qui représente un segment de réseau privé. L’ensemble doit fonctionner (accès à internet, résolution de nom, masquage d’adresse).

Pour ce TP, nous utiliserons à nouveau Netkit en employant deux hôtes : le client et le routeur-proxy. Voici une schématisation de la mise en pratique :

Figure 28. Schématisation d'une architecture Proxy

L'internet sera accessible à travers l'interface eth1 du routeur. On utilisera pour cela la fonctionnalité tap de Netkit. On renseignera le fichier /etc/resolv.conf pour y mettre l'adresse IP des serveurs DNS.


adminbdd lab_proxy # cat lab.conf 
LAB_DESCRIPTION="Utilisation d'un proxy HTTP Squid"
LAB_VERSION=1.0
LAB_AUTHOR="Vanvincq Clément"
LAB_EMAIL=vanvincq.clement@gmail.com
LAB_WEB=http://www.eof.eu.org/

client[eth0]=interne

proxy[eth0]=interne
proxy[eth1]=tap,10.0.0.1,10.0.0.2

adminbdd lab_proxy # cat client.startup 
ifconfig eth0 192.168.0.10 netmask 255.255.255.0 broadcast 192.168.0.255 up
route add default gw 192.168.0.254
echo "nameserver 192.168.10.21" > /etc/resolv.conf
echo "nameserver 192.168.10.22" >> /etc/resolv.conf

Juste en guise de rappel, l'IP FORWARDING est déjà activé par défaut sous netkit.


adminbdd lab_proxy # cat proxy.startup 
ifconfig eth0 192.168.0.254 netmask 255.255.255.0 broadcast 192.168.0.255 up
echo "nameserver 192.168.10.21" > /etc/resolv.conf
echo "nameserver 192.168.10.22" >> /etc/resolv.conf
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE

adminbdd lab_proxy # linfo

====================== Lab information ==========================
Lab directory: /home/lab_proxy
Version:       1.0
Author:        Vanvincq Clément
Email:         vanvincq.clement@gmail.com
Web:           http://www.eof.eu.org/
Description:
Utilisation d'un proxy HTTP Squid

The lab is made up of 2 virtual machines (client proxy).
=================================================================

Bien, on peut maintenant démarrer le laboratoire et procéder à quelques vérifications.


client:~# ifconfig; route
eth0      Link encap:Ethernet  HWaddr ee:ba:7b:99:bc:a5  
		  inet addr:192.168.0.10  Bcast:192.168.0.255  Mask:255.255.255.0
		  inet6 addr: fe80::ecba:7bff:fe99:bca5/64 Scope:Link
		  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
		  RX packets:26 errors:0 dropped:0 overruns:0 frame:0
		  TX packets:26 errors:0 dropped:0 overruns:0 carrier:0
		  collisions:0 txqueuelen:1000 
		  RX bytes:2206 (2.1 KiB)  TX bytes:2162 (2.1 KiB)
		  Interrupt:5 

lo        Link encap:Local Loopback  
		  inet addr:127.0.0.1  Mask:255.0.0.0
		  inet6 addr: ::1/128 Scope:Host
		  UP LOOPBACK RUNNING  MTU:16436  Metric:1
		  RX packets:2 errors:0 dropped:0 overruns:0 frame:0
		  TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
		  collisions:0 txqueuelen:0 
		  RX bytes:100 (100.0 B)  TX bytes:100 (100.0 B)

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     *               255.255.255.0   U     0      0        0 eth0
default         192.168.0.254   0.0.0.0         UG    0      0        0 eth0

client:~# ping -c 3 eof.eu.org
PING eof.eu.org (86.64.63.108) 56(84) bytes of data.
64 bytes from ns1.beaupeyrat.com (86.64.63.108): icmp_seq=1 ttl=52 time=80.4 ms
64 bytes from ns1.beaupeyrat.com (86.64.63.108): icmp_seq=2 ttl=52 time=35.3 ms
64 bytes from ns1.beaupeyrat.com (86.64.63.108): icmp_seq=3 ttl=52 time=148 ms

--- eof.eu.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2014ms
rtt min/avg/max/mdev = 35.352/88.096/148.511/46.515 ms

proxy:~# ifconfig; route
eth0      Link encap:Ethernet  HWaddr e6:2b:9c:bd:e5:25  
		  inet addr:192.168.0.254  Bcast:192.168.0.255  Mask:255.255.255.0
		  inet6 addr: fe80::e42b:9cff:febd:e525/64 Scope:Link
		  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
		  RX packets:33 errors:0 dropped:0 overruns:0 frame:0
		  TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
		  collisions:0 txqueuelen:1000 
		  RX bytes:2231 (2.1 KiB)  TX bytes:3699 (3.6 KiB)
		  Interrupt:5 

eth1      Link encap:Ethernet  HWaddr 82:ee:9e:c5:3f:ee  
		  inet addr:10.0.0.2  Bcast:10.255.255.255  Mask:255.0.0.0
		  inet6 addr: fe80::80ee:9eff:fec5:3fee/64 Scope:Link
		  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
		  RX packets:54 errors:0 dropped:0 overruns:0 frame:0
		  TX packets:56 errors:0 dropped:0 overruns:0 carrier:0
		  collisions:0 txqueuelen:1000 
		  RX bytes:5142 (5.0 KiB)  TX bytes:4687 (4.5 KiB)
		  Interrupt:5 

lo        Link encap:Local Loopback  
		  inet addr:127.0.0.1  Mask:255.0.0.0
		  inet6 addr: ::1/128 Scope:Host
		  UP LOOPBACK RUNNING  MTU:16436  Metric:1
		  RX packets:2 errors:0 dropped:0 overruns:0 frame:0
		  TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
		  collisions:0 txqueuelen:0 
		  RX bytes:100 (100.0 B)  TX bytes:100 (100.0 B)

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     *               255.255.255.0   U     0      0        0 eth0
10.0.0.0        *               255.0.0.0       U     0      0        0 eth1
default         10.0.0.1        0.0.0.0         UG    0      0        0 eth1

proxy:~# ping -c 3 eof.eu.org
PING eof.eu.org (86.64.63.108) 56(84) bytes of data.
64 bytes from ns1.beaupeyrat.com (86.64.63.108): icmp_seq=1 ttl=53 time=38.1 ms
64 bytes from ns1.beaupeyrat.com (86.64.63.108): icmp_seq=2 ttl=53 time=35.0 ms
64 bytes from ns1.beaupeyrat.com (86.64.63.108): icmp_seq=3 ttl=53 time=32.6 ms

--- eof.eu.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2034ms
rtt min/avg/max/mdev = 32.654/35.263/38.106/2.231 ms

En un mot, formidable. Nous allons procéder de façon très brutale en interdisant le forwarding du routeur afin d'empêcher le client de sortir. Il n'aura alors d'autre choix que de passer par le proxy interne :)

Sans cela, si le client voulait aller sur internet en utilisant son navigateur favori, lynx, pour aller sur google il obtenait ceci :

Figure 29. Requête HTTP via un client web


proxy:~# iptables -A FORWARD -j DROP
proxy:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Maintenant que la règle a été ajoutée, le client n'a plus accès à l'extérieur.


client:~# lynx google.fr
Looking up  'google.fr' first
^C
client:~# ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2011ms

47.1.3. Installation et configuration du service proxy

Avant de modifier le fichier de configuration de squid, il est conseillé d'en faire une sauvegarde.


proxy:~# cp /etc/squid/squid.conf /etc/squid/squid.conf.bak

À la place, je vais mettre le fichier de configuration précisé dans l'énoncé :


proxy:/etc/squid# cat squid.conf
http_port 3128
#We recommend you to use the following two lines.
acl QUERY urlpath_regex cgi-bin \?
no_cache deny QUERY
cache_mem 8 MBM

maximum_object_size_in_memory 8 KB

cache_dir ufs /var/spool/squid 100 16 256

cache_access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log
cache_store_log /var/log/squid/store.log

# Put your FQDN here
visible_hostname freeduc-sup.foo.org
pid_filename /var/run/squid.pid

#Recommended minimum configuration:
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255

#Recommended minimum configuration:
http_access allow manager localhost
http_access allow all

Reste à initialiser le cache :


proxy:/etc/squid# squid -z
2012/04/27 09:35:27| Creating Swap Directories
proxy:/etc/squid# /etc/init.d/squid start
Starting Squid HTTP proxy: squid.

On vérifie que le service est bien en cours d'exécution et que le port 3128 est en écoute :


proxy:/etc/squid# ps aux | grep [s]quid
root       635  0.0  1.9   4816   616 ?        Ss   09:35   0:00 /usr/sbin/squid -D -YC
proxy      637  0.3 14.1   7104  4504 ?        S    09:35   0:00 (squid) -D -YC
proxy:/etc/squid# netstat -atup | grep LISTEN
tcp        0      0 *:sunrpc                *:*                     LISTEN      354/portmap     
tcp        0      0 *:3128                  *:*                     LISTEN      637/(squid)

47.1.4. Configuration du client

Afin que le client puisse à nouveau naviguer sur l'Internet, il est nécessaire de configurer le client web du client pour qu'il prenne en compte notre proxy. Pour cela nous allons simplement modifier le fichier de configuration /etc/lynx-cur/lynx.cfg de Lynx pour y ajouter notre proxy.


client:~# grep http_proxy /etc/lynx-cur/lynx.cfg 
# wget) in a subsidiary role, it can be useful to add http_proxy and other
#http_proxy:http://some.server.dom:port/
http_proxy:http://192.168.0.254:3128/

Vérifions maintenant le fonctionnement :


client:~# lynx eof.eu.org
Looking up  'eof.eu.org' first
^C

Cela ne fonctionne pas mais c'est normal car les requêtes DNS (comme tout d'ailleurs) sont bloquées à cause de la règle brutale d'iptables. Réessayons en indiquant directement l'adresse IP du serveur cible :


client:~# lynx 86.64.63.108

Figure 30. Le site de l'EOF accessible via le proxy

Vérification des logs d'accès :


proxy:~# tail -f /var/log/squid/access.log 
1335520007.903   1734 192.168.0.10 TCP_MISS/200 6891 GET http://86.64.63.108/ - DIRECT/86.64.63.108 text/html
1335527993.324   1664 192.168.0.10 TCP_MISS/200 6891 GET http://86.64.63.108/ - DIRECT/86.64.63.108 text/html
1335528688.463     23 192.168.0.10 TCP_MISS/200 6901 GET http://86.64.63.108/ - DIRECT/86.64.63.108 text/html
1335528712.147      2 192.168.0.10 TCP_MISS/200 6901 GET http://86.64.63.108/ - DIRECT/86.64.63.108 text/html

Interdisons maintenant tous les accès avec la règle http_access deny all (sans oublier de redémarrer squid) :


proxy:~# /etc/init.d/squid restart
Restarting Squid HTTP proxy: squid.

client:~# lynx 86.64.63.108

Figure 31. Accès HTTP refusé

47.1.5. Mise en place d’une ACL simple

Interdisez l’accès à un serveur (google.fr) par exemple. Vérifiez le fonctionnement.

On va réactiver tout d'abord le http_access pour tout pour ensuite y ajouter la règle d'interdiction aux serveurs google. De plus, on va changer la règle brutale en quelque chose de plus doux (notamment pour faciliter les requêtes DNS) :

Suppression des anciennes règles :


proxy:~# iptables -F
proxy:~# iptables -X
proxy:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Interdiction de forwarder les requêtes HTTP :


proxy:~# iptables -A FORWARD -p TCP --dport 80 -j DROP
proxy:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere            tcp dpt:www 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Ajoutons maintenant la nouvelle entrée dans le fichier /etc/squid/squid.conf (attention à bien rajouter la règle AVANT le http_access allow all) :


proxy:~# tail -n 7 /etc/squid/squid.conf
#Définition d'un nouveau ACL
acl GOOGLE dstdomain .google.fr
http_access deny GOOGLE

#Recommended minimum configuration:
http_access allow manager localhost
http_access allow all
proxy:~# /etc/init.d/squid restart
Restarting Squid HTTP proxy: squid.

Tout est fin prêt pour de nouveaux tests !


client:~# lynx google.fr

Figure 32. Impossible d'accéder à google.fr ..


client:~# lynx google.de

Figure 33. .. mais rien n'interdit l'accès à google.de !

47.1.6. Utilisation de fichiers pour stocker les règles des ACLs

Exercice : Construisez deux fichiers, l’un qui permettra de stocker des adresses IP, l’autre des mots clés. Construisez une ACL qui interdit l’accès en sortie aux machines qui ont les adresses IP déterminées dans le premier fichier, et une ACL qui empêche l’accès aux URL qui contiennent les mots clés stockés dans le second fichier.


# Exemple de ce que le fichier "adresse_ip" contient :
# Mettez dans la liste des adresses celle de votre client pour tester
192.168.0.2
192.168.0.10

# Exemple de ce que le fichier "mot_cle" contient :
jeu
game

# Exemple d’ACL
acl porn url_regex "/etc/squid/mot_cle"
acl salleTP_PAS_OK src "/etc/squid/adresse_ip"
http_access deny porn
http_access deny salleTP_PAS_OK

Tester le fonctionnement de ces deux ACLs. (Utiliser comme url de destination par exemple http://games.yahoo.com/)

Comme précisé dans l'exemple ci-dessus, nous allons commencer par renseigner les deux fichiers.


proxy:/etc/squid# cat mot_clef 
windows
microsoft
apple
mac
tf1
iphone
imac
macbook

proxy:/etc/squid# cat squid.conf
[...]
acl CENSURE url_regex "/etc/squid/mot_clef"
http_access deny CENSURE

#Recommended minimum configuration:
http_access allow manager localhost
http_access allow all

Le client ne pourra pas accéder à une url contenant la chaîne "microsoft". Cependant, la casse est prise en compte alors pour une solide configuration, il faudra la prendre en compte tous les cas possibles.

Figure 34. Exemple de faille simple si l'on ne fait pas attention

47.1.7. Configuration des messages d’erreurs

Exercice : Configurez Squid pour qu’il affiche des pages (messages d’erreur) en Français. Vérifiez le fonctionnement.


error_directory /usr/share/squid/errors/French

Identifiez la page qui est retournée lors d’un refus d’accès. Modifiez la page et le message retourné, puis vérifiez le fonctionnement.

Après avoir ajouté la ligne indiquée, vérifions déjà ce que contient le fichier qui nous intéresse :


proxy:/etc/squid# cat /usr/share/squid/errors/French/ERR_ACCESS_DENIED 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERREUR&nbsp;: L'URL demand&eacute;e n'a pu &ecirc;tre charg&eacute;e</TITLE>
<STYLE type="text/css"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}PRE{font-family:sans-serif}--></STYLE>
</HEAD><BODY>
<H1>ERREUR</H1>
<H2>L'URL demand&eacute;e n'a pu &ecirc;tre charg&eacute;e</H2>
<HR noshade size="1px">
<P>
En essayant de charger l'URL&nbsp;:
<A HREF="%U">%U</A>
<P>
L'erreur suivante a &eacute;t&eacute; rencontr&eacute;e&nbsp;:
<UL>
<LI>
<STRONG>
Acc&egrave;s interdit.
</STRONG>
<P>
La configuration du contr&ocirc;le d'acc&egrave;s interdit &agrave; votre requ&ecirc;te d'&ecirc;tre
accept&eacute;e &agrave; cette heure-ci. Veuillez contacter votre
prestataire de service si vous pensez que ceci n'a pas lieu d'&ecirc;tre.
</UL>
</P>

J'avoue que sur lynx est un peu limitée mais on fera avec. Pour le fun, voici la nouvelle mise en page :

Figure 35.

On remarquera au passage un problème avec les caractères accentués mais cela doit fort probablement être réglable.

47.1.8. Automatisation de la configuration des clients

Exercice : Créez un fichier ".pac" pour la configuration des clients Mozilla. Vous en avez un complet dans la FAQ de squid. Celui-ci fait le minimum.

47.2. Liens

  1. Le site officiel de Squid

  2. SquidGuard expliqué par l'université de Toulouse

  3. Moteur de recherche des HOWTOs (par contre, je n'arrive pas à accéder aux pages freenix).

47.3. Annexes

47.3.1. Fichier squid.conf - testé avec Squid 2.5

Fichier minimal pour Squid :


http_port 3128

#Ne pas "cacher" les données des formulaires
acl QUERY urlpath_regex cgi-bin \?
no_cache deny QUERY
cache_mem 8 MBM

maximum_object_size_in_memory 8 KB

cache_dir ufs /var/spool/squid 100 16 256
cache_access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log
cache_store_log /var/log/squid/store.log

# Ici mettez le nom de votre machine
visible_hostname uranus.freeduc-sup.org

pid_filename /var/run/squid.pid

#Recommended minimum configuration:
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255

# Test des fichiers @ip et mots clés
acl porn url_regex "/etc/squid/mot_cle"
acl salleTP_PAS_OK src "/etc/squid/adresse_ip"
http_access deny porn
http_access deny salleTP_PAS_OK

# Authentification
auth_param basic program /usr/lib/squid/ncsa_auth /etc/squid/users
auth_param basic realm Squid proxy-caching web serve
auth_param basic children 5
acl foo proxy_auth REQUIRED
http_access allow foo

#Default:
#http_access deny all

#Messages d’erreurs en FR
error_directory /usr/share/squid/errors/French

# Pour le proxy cache transparent
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on

47.3.2. Exemples d’ACLs Squid 2.2


acl salleTP_OK src "/etc/squid/salleTP_OK.txt"
acl porn url_regex "/etc/squid/porn.txt"
acl salleTP_PAS_OK src "/etc/squid/salleTP_PAS_OK.txt"
http access salleTP_OK
http access porn
http deny salleTP_PAS_OK

47.3.3. ACL par authentification Squid 2.2

Utilisation d’une authentification simple similaire à celle mise en oeuvre dans les .htaccess. Créer le fichier par script ou manuellement avec htpasswd.


authenticate_program /usr/bin/ncsa_auth /etc/squid/users
authenticate_children 5
acl_authenticate_users REQUIRED
http_access authenticate_users

47.3.4. ACL sur des plages horaires Squid 2.2

Combinaison par "ET" logique des plages horaire et des salles. Mettre la machine à l’heure avec ntpdate par exemple.


# Interdire les accès en dehors des plages horaires 8h-12h et 14h-18h
S Sunday M Monday T Tuesday W Wednesday H Thrusday F Friday A Saturday
acl am time MTWHF 08:00-12:00
acl PM time MTWHF 14:00-18:00
http_access allow am salleTP_PAS_OK
http_access allow pm salleTP_PAS_OK