Proxy
Introduction aux proxies
Proxy signifie, de façon littérale en anglais, "on behalf of", soit "par procuration" : un serveur proxy est simplement un serveur qui effectue des requêtes pour quelqu'un d'autre. On traduit parfois le terme en français par "Serveur Mandataire". Ils servent en général d'intermédiaire entre le réseau interne et l'extérieur; il pourra être placé dans la DMZ.
Utilité
Le rôle premier d'un proxy est de partager l'accès aux réseaux internes (le plus souvent, il s'agit d'Internet). Les proxies sont des intermédiaires entre les utilisateurs du réseau interne et l'extérieur. Pour les serveurs externes, toutes les requêtes sembleront émaner d'une seule et même machine, le proxy. À première vue, cela ressemble beaucoup à un routeur ! Mais un proxy a d'autres vocations :
- Rationnaliser la bande passante : c'est la fonction de cache
- Contrôler les accès
- Compresser les données
- Anonymiser les données
- Pour les particuliers, il peut servir à contourner certains filtrages d'état (en Chine, par exemple).
Principe de fonctionnement
Le fonctionnement de base est simple, c'est un serveur qui relaie les requêtes et renvoie les réponses aux clients. Ainsi, pour une application donnée qui utilise le proxy, le client ne s'adresse qu'au proxy, celui-ci relayant les requêtes et les réponses.
La fonction Cache
Un des avantages du proxy est de fournir un cache de données : il garde en mémoire les pages visitées et les ressert aux clients. Ce mécanisme sert à limiter les besoins en bande passante. Dans ce cas, aucune connexion vers l'extérieur n'est établie.
La fonction de contrôle d'accès
Les proxies sont capables d'appliquer des règles de contrôle d'accès, généralement appellées ACL (Access Control Lists), permettant de bloquer l'accès à certaines ressources. Le filtrage peut être appliqué en fonction de la source, de la destination, ou bien du protocole; les proxies peuvent aussi identifier les utilisateurs ou les machines sources, afin de contrôler qui accède à quoi. Ils peuvent interroger des services d'annuaire afin d'appliquer des règles de filtrage basées sur des groupes d'utilisateurs / de machines. En cas d'interdiction d'accès, on peut renvoyer un message d'erreur avec une explication, ou bien même une autre ressource.
Quels protocoles utilisent des proxies?
Les proxies peuvent être utilisés par différentes applications, mais il en existe différentes sortes :
- HTTP/HTTPS
- IMAP
- SSH
- FTP
- SIP
- ARP
- etc...
Il existe également des proxies utilisant le protocole SOCKS, qui permet d'encapsuler à peu près n'importe quoi.
<pdf>Fichier:ProtocoleSocks.pdf</pdf>
Présentation des proxies web
Les proxies web sont les plus répandus. De base, ils servent à relayer les requêtes HTTP et HTTPS des applications clientes configurées pour le proxy. Mais ils peuvent cependant servir aussi à :
- Faire de la mise en cache
- Contrôler les accès
- Authentifier les clients
- Compresser les données
- Gérer l'anonymat
- Loguer les connexions
La durée de mise en cache des données est définie dans la configuration du proxy.
Authentification des clients
Si l'authentification des clients est requise, les utilisateurs devront se connecter avant de pouvoir accéder aux ressources web. Cela peut se faire selon différentes méthodes :
- NTLM/SMB : Authentification transparente pour les postes Windows du domaine (Windows NT ou Samba3). Les informations de session sont utilisées pour l'authentification auprès du proxy; les comptes sont stockés sur le contrôleur de domaine.
- Kerberos / NTLM : Autre type d'authentification transparente pour les poste Windows du domaine Active Directory ou Samba4. Les comptes sont stockés là aussi sur le contrôleur de domaine.
- Authentification LDAP : Les comptes sont stockés dans un annuaire LDAP/OpenLDAP.
- Authentification MySQL : Les comptes utilisateurs sont stockés dans une base de données MySQL.
- Authentification Locale : Les comptes utilisateur sont stockés dans un fichier local ou dans la base d'utilisateurs locaux.
Les informations de connexion seront demandées à l'utilisateur si celles-ci ne peuvent pas être récupérées; le proxy renverra une erreur HTTP 407 (Proxy Authentication Required) si l'utilisateur n'est pas authentifié.
Types de proxies pour le web
Il existe différents types de proxies pour HTTP/HTTPS :
- Les proxies classiques, avec lesquels les clients doivent être configurés pour utiliser le proxy
- Les proxies transparents : Pas de configuration côté client, mais il nécessite un peu de configuration de la part des administrateurs réseaux. La passerelle ne doit pas accepter les paquets sur les ports 80/443 mais rediriger vers le proxy.
- Les reverse-proxies : Ces proxies permettent d'accéder à des serveurs du réseau local depuis Internet : ils agissent dans le sens inverse des proxies classiques.
À partir d'ici, on parlera de proxies classiques.
Configuration des clients
En mode classique, les applications clientes doivent être configurées pour utiliser le proxy. Le port généralement utilisé pour HTTP/HTTPS est TCP 8080, bien qu'on puisse prendre n'importe quel port > 1023 (Squid utilise par défaut TCP 3128). On a plusieurs méthodes pour configurer les clients :
- Configuration manuelle : Le nom d'hôte ou l'adresse IP et le port doivent être renseignés dans l'application cliente. Les IP ou domaines à exclure sont à préciser manuellement, et on ne pas utiliser plusieurs proxies de façon native.
- Configuration automatique : l'url du fichier .PAC (Proxy Auto Config) doit être renseignée. Les clients récupèreront les paramètres de configuration automatiquement. Si le fichier est introuvable, la plupart des clients fonctionnent en mode DIRECT, c'est-à-dire sans proxy.
- Détection Automatique : il s'agit du WPAD, soit Web Proxy Auto Discovery. Pour cette méthode, il faudra :
- Un serveur http nommé wpad.<mon_domaine.tld>, en mesure de fournir un fichier proxy.pac ou wpad.dat.
- Pour que le client trouve ce fichier, plusieurs choix :
- Une option spécifique envoyée au client DHCP
- Une résolution DNS.
Lorsque les clients sont configurés pour utiliser le proxy, ils n'effectuent plus les requêtes DNS pour les sites visités (c'est le proxy qui s'en charge).
Les fichiers de configuration automatique
On peut créer un fichier de configuration du proxy pour les clients afin de centraliser la gestion des clients. Ce fichier est hébergé sur un serveur web et les logiciels client doivent être configurés pour utiliser l'url du fichier .pac pour la configuration automatique. L'url est sous la forme protocole://monsite.mondomaine/ (par exemple : http://proxy.config.mondomaine/proxy.pac).
Le fichier .PAC permet de définir plus en détails le comportement du client : on peut ainsi choisir d'utiliser tel ou tel proxy en fonction du site web, voire même indiquer un proxy de secours. Le fichier .PAC est écrit en JavaScript, mais seules quelques fonctions sont disponibles. La plupart des navigateurs ira chercherpar défaut la fonction FindProxyForUrl(). L'inconvénient majeur des fichier .PAC est l'absence de confiance en l'adresse IP source de l'expéditeur.
Exemple pour firefox v47
Pour Firefox, la configuration se fait par le menu Options > Avancé > Réseau. Il faut ensuite modifier les paramètres de connexion puis spécifier l'adresse de configuration automatique du proxy avec le port.
Exemple de fichier .PAC
/** * Exemple extrait du site http://findproxyforurl.com/example-pac-file/ **/ function FindProxyForURL(url, host) { // If the hostname matches, send direct. // Si le domaine est intranet.domain.com OU // Si le domaine est abcdomain.com // On renvoie DIRECT (= connexion directe sans proxy) if (dnsDomainIs(host, "intranet.domain.com") || shExpMatch(host, "(*.abcdomain.com|abcdomain.com)")) return "DIRECT"; // If the protocol or URL matches, send direct. // Si protocole = FTP OU url commence par http://abcdomain.com/folder/ // On renvoie DIRECT if (url.substring(0, 4)=="ftp:" || shExpMatch(url, "http://abcdomain.com/folder/*")) return "DIRECT"; // If the requested website is hosted within the internal network, send direct. // Si le site demande est heberge sur le reseau local, on renvoie DIRECT if (isPlainHostName(host) || shExpMatch(host, "*.local") || isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") || isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") || isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") || isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0")) return "DIRECT"; // If the IP address of the local machine is within a defined // subnet, send to a specific proxy. // Pour les clients du reseau 10.10.5.0/24, // On renvoie le proxy specifique a utiliser d'IP:PORT 1.2.3.4:8080 if (isInNet(myIpAddress(), "10.10.5.0", "255.255.255.0")) return "PROXY 1.2.3.4:8080"; // DEFAULT RULE: All other traffic, use below proxies, in fail-over order. // Sinon regle par defaut, on renvoie 2 proxys a utiliser // 1- Proxy avec l'IP:PORT 4.5.6.7:8080 // 2- Proxy avec l'IP:PORT 7.8.9.10:8080 return "PROXY 4.5.6.7:8080; PROXY 7.8.9.10:8080"; }
Toutes les fonctions des fichiers .PAC sont disponibles ici : http://findproxyforurl.com/pac-functions/
Plus d'informations sur les proxies et les trames qu'ils utilisent : http://www.forensicswiki.org/wiki/Proxy_server
Présentation de Squid, un proxy HTTP open-source
Squid supporte les protocoles HTTP, HTTPS, FTP et Gopher.
Il propose des fonctions de cache : si la ressource demandée par le client est déjà dans le cache et qu'elle est à jour, il la renvoie directement au client. Sinon, il effectue la requête, mets la réponse dans son cache en plus de la transférer au client, et transmet la réponse au client. Squid permet aussi d'appliquer des ACL, des règles d'authentification des utilisateurs et de filtrage (limitation horaire, limitation en bande passante...). Il fonctionne par défaut en mode classique, mais peut travailler de façon transparente si il est bien configuré.
Installation
Squid s'installe via les repos :
sudo apt install squid3
On peut ensuite le piloter avec service squid {reload|start|stop|status}.
Quelques commandes
squid3 # démarre le daemon squid3 squid3 -N # démarre Squid3 mais pas en mode daemon squid3 -k check # vérifie si le fichier de configuration est correct. Seules les erreurs sont affichées, si rien ne s'affiche c'est que tout est OK squid3 -k reconfigure # relance Squid en rechargeant la configuration (pas de coupure de service) squid3 -z # (re)construit le cache squid3 -d 99 # démarre Squid en mode debug, utile pour chercher les erreurs (squid3 -X permet aussi un mode debug complet, mais presque trop verbeux)
Configuration de Squid
La configuration se fait via /etc/squid3/squid.conf.
Un exemple de configuration générale, à adapter :
http_port 3128 # port d'ecoute, ici TCP 3128 (c'est le port standard de squid) coredump_dir /var/spool/squid3 refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880 refresh_pattern . 0 20% 4320 cache_dir ufs /var/spool/squid3 100 16 256 # chemin, type et taille du cache cache_effective_user proxy # utilisateur gestionnaire du cache cache_effective_group proxy # groupe gestionnaire du cache redirect_program /usr/bin/squidGuard # redirige la transaction a un tiers, ici squidguard
SquidGard sera vu un peu plus tard dans ce cours.
ACL
Les notions de filtrage seront vues dans un autre chapitre; je détaille ici les règles de filtrage appliquées aux sources, destinations (plages IP, domaines, ports). Le filtrage des URL se fera avec SquidGard.
Les ACL sont les règles que le serveur applique et qui permettent d'autoriser ou non certaines transactions. À noter : les groupes all, manager, localhost, et to_localhost sont prédéfinis.
La syntaxe est la suivante :
acl aclname acltype paramètre
Exemple à adapter :
acl reseau_etudiant src 192.168.20.0/255.255.255.0 # plage reseau source nommee 'resau_etudiant' acl postes_vip src 192.168.100.10-192.168.100.25/255.255.255.0 # plage source nommee 'postes_vip' acl domaine_upec dstdomain .u-pec.fr # domaine de destination .u-pec.fr acl SSL_ports port 443 # https acl Safe_ports port 70 # gopher acl Safe_ports port 80 # http acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # ports non-enregistres acl CONNECT method CONNECT # requete HTTP de type CONNECT
On peut retrouver tous les types d'ACLs ici : http://www.squid-cache.org/Doc/config/acl/
Une fois qu'on créé nos ACL, il faut définir si on les autorise ou non. Il ne faut pas tout autoriser, seulement autoriser ce que l'on souhaite et bloquer tout le reste. La syntaxe est la suivante :
http_access allow|deny [!]aclname
http_access allow reseau_etudiant # autorise le groupe 'reseau_etudiant' http_access allow postes_vip # autorise le groupe 'postes_vip' http_access deny !Safe_ports # interdit tous les ports qui ne font pas partis du groupe Safe_ports http_access deny CONNECT !SSL_ports # interdit la methode CONNECT sur les ports qui ne font pas partis du groupe SSL_ports http_access allow localhost manager # autorise localhost a gerer le cache http_access deny manager # interdit la gestion du cache pour tous les autres http_access deny all # interdit tout
Le ! signifie "différent de" (équivalent de !=).
Authentification des clients
Squid peut gérer l'authentification des clients de plusieurs façons :
- AD
- LDAP
- Samba
- Local
Les clients devront alors s'authentifier via une pop-up avant d'utiliser le proxy.
Voir cette page : https://wiki.squid-cache.org/Features/Authentication
TP1 : Mise en place
Je pars de l'architecture suivante :
Les clients sont sous Debian, les serveur sous UbuntuServer.
Je passe la mise en place des clients pour le début, très simple.
Installation et configuration de Squid
Je commence par installer Squid 3, puis je me lance dans le fichier de configuration en gardant une copie de l'original :
sudo apt install squid3 cd /etc/squid/ cp squid.conf squid.conf.bak vim squid.conf
Son contenu :
###Configuration http_port 3128 # port d'ecoute, ici TCP 3128 (c'est le port standard de squid) coredump_dir /var/spool/squid3 refresh_pattern ^ftp: 1440 20% 10080 #Ces directives correspondent aux temps de rafraîchissement du cache. refresh_pattern ^gopher: 1440 0% 1440 #Ici, je les laisse par défaut (ce sont ceux recommandés dans la doc de Squid) refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880 refresh_pattern . 0 20% 4320 cache_dir ufs /var/spool/squid 100 16 256 # chemin, type et taille du cache (que j'ai du adapter avant de lancer squid -z) cache_effective_user proxy # utilisateur gestionnaire du cache cache_effective_group proxy # groupe gestionnaire du cache #ACLs (declarations) #Je déclare ici les différents groupes sur lesquels j'appliquerais des règles acl reseau_lan src 192.168.50.0-192.168.50.253/255.255.255.0 #Correspond à mon réseau LAN acl SSL_ports port 443 #Port HTTPS acl Safe_ports port 80 #Port HTTP acl domainegouv dstdomain .gouv.fr #Domaine .gouv.fr, que l'on va interdire acl CONNECT method CONNECT #Methode de connexion au net, d'après la doc de Squid, CONNECT est "une méthode #pour tunneliser n'importe quel flux à travers un proxy". #ACLs (regles) #Je met ici en place mes règles pour contrôler le trafic. Par défaut, toute connexion est refusée à moins qu'une règle #Spécifiant le contraire n'existe dans ce fichier. #Le principe est le même que pour un Firewall : la première ligne qui matche est prise en compte. http_access deny domainegouv #Il est interdit de visiter les sites du gouvernement francais. http_access deny CONNECT !SSL_ports #Pas de HTTP ! http_access allow reseau_lan #On autorise les membres du réseau à se connecter au proxy http_access allow CONNECT SSL_Ports #On autorise la navigation en HTTPS
Il me faut relancer squid et créer les dossiers de cache :
systemctl restart squid
squid -z
Une fois cela fait, mon proxy fonctionne : je peux tester depuis un client via Firefox (en changeant les paramètres de Proxy dans Firefox, attention à cocher "utiliser ce proxy pour tous les protocoles"). Je peux me connecter en https ou http, mais pas aux site en .gouv.fr.
Utilisation du fichier PAC
Le fichier .PAC configuré est le suivant :
//Fichier 192.168.56.253/proxy.pac function FindProxyForURL(url, host) { // Connexion directe vers mondomaine.tld ou gouv.fr if (dnsDomainIs(host, "mondomaine.tld") || //Si le domaine est mondomaine.tld... shExpMatch(host, "(*.gouv.fr|gouv.fr)")) //Ou qu'il contient gouv.fr... return "DIRECT"; //Connexion Directe //Connexion directe vers les sites du réseau local if (isInNet(dnsResolve(host), "192.168.56.0", "255.255.255.0")) //dnsResolve tente une résolution DNS qui peut prendre LONGTEMPS return "DIRECT"; //et tout bloquer si pas de DNS accessible au client! //On renvoie toutes les autres connexions vers le proxy return "PROXY 192.168.56.254:3128"; }
Ce fichier prévoit que le client ait un éventuel accès au web directement, ce qui est débile, du coup... Attention au dnsResolve(host), qui tente une résolution DNS. Si le client n'as pas accès à un DNS, le navigateur va attendre, attendre... Cela fonctionne cependant bel et bien si le client a un accès au web direct (avec une seconde interface, par exemple). L'usage des résolutions DNS dans un .PAC est fortement déconseillé.
cf Wikipédia :
https://fr.wikipedia.org/wiki/Fichier_.PAC
Une fois fait, je mets ce fichier accessible sur mon serveur web (192.168.56.253/proxy.PAC) et je configure mes clients pour qu'ils aillent le chercher (dans Firefox, proxy settings > Automatic proxy configuration URL : http://192.168.56.253/proxy.PAC).
Le fichier peut bien s'appeller .pac ou .PAC, ça n'as pas l'air important.
Le filtrage en général
Filtrage en entreprise
L'usage incontrôlé d'internet en entreprise fait courir un risque pénal et civil à l'encontre de l'entreprise et de ses dirigeants. Les membres de l'équipe informatique peuvent également voir leur responsabilité engagée pour "négligence fautive", si ils n'ont pas informé la direction des menaces et des moyens à mettre en oeuvre pour limiter ces risques.
Le dispositif de filtrage des accès Internet n'est pas une option; il est OBLIGATOIRE.
On peut effectuer différents types de filtrages :
- blocage d'url
- blocage par mots-clefs
- blocage de certains types de fichiers
- analyse antivirus
- déblocage temporaire (pause déjeuner par exemple).
Filtrages des accès - Les listes ou catégories
On distingue les listes noires (sites interdits) des listes blanches (sites autorisés). Il est difficile d'avoir une liste noire complètement exhaustive et elles doivent être mises à jour régulièrement. Le filtrage s'effectue par catégorie de sites (pornographie, piratage, etc) et on peut appliquer différentes politiques selon le profil de l'utilisateur. Par exemple, on peut autoriser les VIP à avoir accès au streaming; autoriser les réseaux sociaux pendant la pause déjeuner; etc... Il est bien évidemment important de bloquer les proxies publics, que les utilisateurs pourraient utiliser.
L'analyse de fichiers à risque
On peut coupler les proxies avec des antivirus pour analyser les téléchargements (mais attention aux performances sur des gros fichiers...). On peut aussi bloquer certaines extensions de fichiers comme .cat, .bat, .vbs...
Le filtrage de flux chiffrés
Si on veux mettre en place un filtrage du HTTPS, le confidentialité sera compromise pour les clients : les données seront chiffrées entre le client et le proxy, puis entre le proxy et le serveur : le proxy fait mitm.
<pdf>Fichier:ANSSIfluxhttps.pdf</pdf>
Aspects juridiques du filtrage
La France dispose d'une legislation particulière liée au filtrage, on doit filtrer mais en respectant certaines règles.
La charte informatique
Lorsque l'on applique des règles des filtrage basée sur des informations personnelles, l'entreprise doit rédiger une charte informatique. Celle-ci doit être portée à la connaissance de l'utilisateur lors de leur prise de fonction, la CNIL la recommande dans tous les cas.
La conservation des logs
Il est recommandé de les garder 1 an, mais cela varie selon les cas :
- La LCEN (Loi pour la Confiance dans l'Économie Numérique) prévoit 1 an
- Les lois antiterrorisme du 23/01/2006 préconisent 1 an
- La CNIL recommande 6 mois à des fin de contrôle des utilisateurs
- Etc... On s'adapte en fonciton de l'activité de l'entreprise.
Obligation des dispositifs de filtrage
On doit mettre en place tous les moyens à disposition pour éviter les usages illégaux d'Internet. Il s'agit du piratage, racisme, etc... L'entreprise peut être tenue pour responsable, si les moyens suffisants ne sont pas mis en place, auprès d'HADOPI par exemple.
Déclaration auprès de la CNIL
Il est obligatoire de se déclarer auprès de la CNIL pour tout traitement de données à caractère personnel : la mise en place d'un filtrage basé sur le nom de l'utilisateur impose une déclaration auprès de la CNIL. La déclaration est simplifiée si il y'a un CIL (Correspondant Informatique et Libertés) dans l'entreprise.
Du filtrage avec Squidguard
Squidguard vient en complément de Squid. Il utilise aussi les ACL pour gérer les accès. Pour accélerer le traitement, il fonctionne avec des bases de données. Les listes blanches et noires d'url doivent être converties en bases de données pour pouvoir être utilisées par Squidguard.
Connecter squid et squidGuard
Important : Il ne faut pas oublier de dire à Squid de rediriger vers Squidguard, en rajoutant la ligne suivante EN BAS du fichier squid.conf :
redirect_program /usr/bin/squidGuard # redirige la transaction a un tiers, ici squidguard
Installation et options en lignes de commande
Le paquet est présent dans les dépôts :
sudo apt install squidguard
Les options en ligne de commande sont :
squidGuard -C all # Convertit les fichiers d'url/domaines en bases de donnees squidGuard -u # Met a jour les bases de donnees squidGuard -d # lance squidGuard en mode debug
Configuration de Squidguard
La configuration se fait via le fichier : /etc/squidguard/squidguard.conf
La configuration est décomposée en plusieurs parties :
- Les plages horaires
- Les sources
- Les destinations
- Les ACL
Les chemins des logs et des bases de données sont également définis dans ce fichier :
dbhome /var/lib/squidguard/db # Chemin vers les DB logdir /var/log/squidguard # Chemin des logs
L'utilisateur qui exécute Squidguard doit avoir les droits suffisants !
Plages horaires
On peut définir des plages de temps, que l'on pourra appliquer aux ACL (par exemple, autoriser facebook de midi à 14h...). La syntaxe est la suivante :
time <timerule_name> {args}
Un exemple de fichier :
# Abbreviation # s = sunday, m = monday, t =tuesday, w = wednesday, h = thursday, f = friday, a = saturday time workhours { weekly mtwhf 08:00 - 12:30 # Du lundi au vendredi, de 8h a 12h30 weekly mtwhf 14:00 - 18:30 # Du lundi au vendredi, de 14h a 18h30 } # date YYYY.MM.DD time fete_du_travail { date *.05.01 # 1er mai (N'importe quelle année.Mois_05.Jour_01)
Sources
On peut définir plusieurs types de sources :
- Des IPs
- Des utilisateurs
- Un domaine
La syntaxe d'une source est la suivante :
source <sourcename> {args }
Un exemple :
source admin { # source nommée 'admin' ip 10.0.1.0/24 # plage ip des admin } source workers { # source nommée 'workers' user raph # l'utilisateur raph ip 192.168.5.100-192.168.5.128 # une plage d'ip ip 192.168.2.0/24 # un reseau ip 192.168.1.17 # un hote domain iutsf.lan # un domaine }
On peut le configurer pour qu'il récupère les utilisateurs dans une base de données LDAP, mais pour cela, il faut le compiler avec l'option --with-ldap=yes
Les listes noires de l'université de Toulouse
Pour les destinations, on peut s'appuyer sur ce fichier très complet. Ici, on les télécharge en tant que fichier texte, puis on les mets dans le chemin de la BDD; il faudra par la suite les convertir en base de données avant de lancer Squidguard.
wget http://dsi.ut-capitole.fr/blacklists/download/blacklists.tar.gz #Telechargement des listes tar xvzf blacklists.tar.gz #Extraction des fichiers cp -R blacklists/* /var/lib/squidguard/db/ #Copie des fichiers vers le chemin de la DB
Les destinations
On va à présent déclarer ces listes noires dans la configuration de Squidguard (ici, on ne prendra que l'exemple des destinations social_networks et proxy). La syntaxe d'une source :
dest <destination-name> {args }
dest good { # destination good (obligatoire et cree par defaut) } dest local { # destination local (obligatoire et cree par defaut) } dest social_networks { # Liste nommee 'social_networks' domainlist social_networks/domains # liste de domaines (1 par ligne) urllist social_networks/urls # liste d'URLs (1 par ligne) } dest proxy { # liste nommee 'proxy' domainlist proxy/domains # liste de domaines (1 par ligne) urllist proxy/urls # liste d'URLs (1 par ligne) expressionlist proxy/expressions # liste d'expressions (separee par des pipes '|') }
Il est important de bloquer les proxies publics !
Les listes noires étant déclarées dans la configuration, on va désormais les convertir dans la base de données :
squidGuard -C all -b
Un message : ERROR: Going into emergency mode est très mauvais signe !
On donne ensuite l'accès à l'utilisateur de squidguard (proxy) l'accès à ces fichiers :
chown -R proxy:proxy /var/lib/squidguard
Les ACLs
On a nos plages horaires, nos sources, nos destinations; il n'y a plus qu'à définir les ACLs. Celles-ci sont construites par sources (celles définies plus tôt), on choisit ensuite les destinations autorisées ou bloquées. Il existe une règle default qui s'applique à tout le monde.
Dans l'exemple, les admins ont tous les droits, et les workers ne peuvent pas accéder aux réseaux sociaux pendant le travail, et ne pourront jamais aller sur les proxies publics. L'instruction redirect renvoie vers une page web, elle prend un certain nombre de variables (cf : http://www.squidguard.org/Doc/redirect.html)
acl { admin { pass any } workers within workhours { pass !proxy !social_networks #Tout ce qui n'est pas proxy ou social networks passe (est accessible)... redirect http://mon_serveur_web.domain/blocked.cgi?clientaddr=%a&url=%u #Mais si on tente d'accéder, rediriger vers cette page } else { pass !proxy redirect http://mon_serveur_web.domain/blocked.cgi?clientaddr=%a&url=%u } default { pass none redirect http://mon_serveur_web.domain/blocked.cgi?clientaddr=%a&url=%u } }
Remarques syntaxiques
- On utilise "any" ou "all" pour dire "Toutes les destinations", et "none" pour dire "aucune destination".
- On utilise "within" pour dire "dans la plage horaire" et "outside" pour dire "pas dans la plage horaire"
- ! signifie NOT
Fichiers d'exemples plus poussés
En repartant du TP1, j'ai mis en place Squidguard. Le fichier de configuration squidGuard est le suivant :
#/etc/squidguard/squidGuard.conf ###Fichiers de logs et base de données (emplacement) dbhome /var/lib/squidguard/db logdir /var/log/squidguard ###Plages horaires #La plage midi définit l'heure de la pause de midi #Ici, de 12h à 14h time midi { weekly mtwhf 12:00 - 14:00 } ###Sources #On définit les VIPs et les utilisateurs standard par les adresses IP source vip { ip 192.168.56.50 } source standard { ip 192.168.56.60-192.168.56.240 } ###Destinations #Ici, je définis les différentes destinations à autoriser/refuser #Les deux destinations obligatoires dest good { } dest local { } #Pornographie dest porn { domainlist porn/domains urllist porn/urls } #Jeux en ligne dest games { domainlist games/domains urllist games/urls } #Piratage dest piratage { domainlist warez/domains urllist warez/urls } #Partage de fichiers dest partage { domainlist filehosting/domains urllist filehosting/urls } #Réseaux Sociaux dest social { domainlist social_networks/domains urllist social_networks/urls } #Proxies dest proxies { domainlist proxy/domains urllist proxy/urls } ###ACLs #L'ACL par défaut refuse tout (il faut être dans un groupe pour utiliser internet) #L'ACL VIP s'assure que les VIP puissent accéder aux réseaux sociaux et partage de fichiers, mais pas aux sites interdits à tous #L'ACL standard permet aux utilisateurs standards d'accéder aux réseaux sociaux à midi, mais jamais au partage de fichiers ou #aux sites interdits à tous acl { default { pass none redirect http://192.168.56.253/blocked.cgi?clientaddr=%a&url=%u } vip { pass social partage !porn !games !proxies !piratage redirect http://192.168.56.253/blocked.cgi?clientaddr=%a&url=%u } standard outside midi { pass !social !partage !porn !games !proxies !piratage redirect http://192.168.56.253/blocked.cgi?clientaddr=%a&url=%u } else { pass social !partage !porn !games !proxies !piratage redirect http://192.168.56.253/blocked.cgi?clientaddr=%a&url=%u } }
J'ai bel et bien ajouté la ligne suivante :
redirect_program /usr/bin/squidGuard
en bas de mon fichier de configuration squid.
Retour d'expérience
Les problèmes de redirection en https de Firefox sont toujours présents avec squidguard; en effet, la redirection ne s'effectue pas quand je tente d'accéder à un site bloqué via https (mais en http, oui...).
Reverse Proxy
Présentation des reverse-proxies
Les reverse-proxies servent d'intermédiaire entre les utilisateurs externes et le réseau local. Ils ont le rôle de passerelle entre les réseaux externes et le réseau local, et permettent de contrôler les flux à destination des serveurs web internes (au contraire des proxies qui contrôlent le flux depuis l'intérieur vers l'extérieur). Implémenter des reverse-proxies présente plusieurs avantages :
- Sécuriser les serveurs web en les protégeant des attaques directes depuis l'extérieur, et en masquant l'architecture
- Mettre en cache des données statiques
- Faire du Load-balancing
- Faire du Fail-Over
- Compresser les données
Paramétrage des clients
Les clients n'ont pas besoin de configuration particulière, le reverse-proxy est transparent pour eux. On en rencontre en réalité souvent sur Internet, sans en avoir conscience.
Côté serveur
Côté serveur, il est nécessaire d'avoir un cluster de serveurs web. La répartition de charge permet de répartir les requêtes, pour éviter les ralentissements ou plantages serveur. Le Failover quant à lui, se fait parce que le reverser-proxy communique en permanence avec les serveurs internes pour connaître leur disponibilité; le reverse-proxy s'adapte et relaie les requêtes vers les serveurs qui sont fonctionnels (pas de coupure de service !). Pour ce qui est du DNS, la résolution de nom renvoie vers le proxy (et pas un des serveurs web). Le proxy redistribue alors les requêtes.
L'exemple de NginX
Nginx est à la fois un serveur web, et un reverse-proxy. Nous allons ici voir comment le configurer en tant que reverse-proxy pour le web (http et https). Il est capable de renvoyer les requêtes vers un autre serveur web local (qui écoute sur un port autre que 80) ou vers d'autres serveurs de son réseau interne.
Installation et commandes de pilotage de Nginx
L'installation est basique :
sudo apt install nginx
Les commandes de pilotage sont les suivantes :
service nginx {configtest|force-reload|reload|restart|rotate|start|status|stop|upgrade}
On peut tester sa configuration avec :
nginx -t
Configuration de Nginx
À partir d'ici, on verra comment mettre en place le reverse-proxy pour deux sites hébergés sur deux serveurs différents, ainsi que la mise en place du cache et de la compression des données entre le reverse-proxy et le client distant.
Les fichiers de configuration sont placés par défaut dans /etc/nginx.
On va commencer par la configuration globale, dans nginx.conf :
user www-data; # user qui fait tourner nginx worker_processes 4; # nb d'instance nginx (à adapter, 1 par core CPU) # fichier dans lequel est enregistre le pid de nginx (celui du master process, qui lance les workers) pid /run/nginx.pid; events { worker_connections 1024; # nb de connexion max par worker (à adapter) } http { sendfile on; # cf complement pour plus d'infos tcp_nopush on; # cf complement pour plus d'infos tcp_nodelay on; # cf complement pour plus d'infos server_tokens off; # masque la version de nginx dans les messages # delai d'attente en seconde avant la fermeture d'une connexion keepalive_timeout 65; include /etc/nginx/mime.types; # liste des types MIME (type de fichier par extension) default_type application/octet-stream; # type par defaut des fichiers non repertories dans mime.type access_log /var/log/nginx/access.log; # fichier de log des acces error_log /var/log/nginx/error.log; # fichier de log des erreurs include /etc/nginx/conf.d/*.conf; # inclusion des fichiers de configuration (on trouvera notamment le fichier de conf pour le reverse proxy) include /etc/nginx/sites-enabled/*; # configuration des sites web actifs }
Pour plus d'explications sur les directives : http://nginx.org/en/docs/http/ngx_http_core_module.html
Quelques détails supplémentaires (from : https://thoughts.t37.net/optimisations-nginx-bien-comprendre-sendfile-tcp-nodelay-et-tcp-nopush-2ab3f33432ca):
- tcp_nodelay : Par défaut, un paquet TCP peut attendre jusqu'à 0.2 secondes avant d'être envoyé, si il est trop petit, par exemple. Cette option force nginx à envoyer directement les données, sans attendre de faire des paquets tcp assez gros. En effet, ce comportement par défaut cause une latence sur le dernier paquet : il est rare qu'un fichier fasse un nombre exact de paquets, et le dernier se retrouve en général à être un peu petit (genre, un octet de données pour 40 octets de headers TCP + IP).
- tcp_nopush : Cette directive fait un peu le contraire de tcp_nodelay : au lieu d'optimiser les délais d'envoi, elle optimise la quantité d'informations envoyées en une seule fois. tcp_nopush existe dans pile TCP de FreeBSD, mais sous Linux, elle correspond à TCP_CORK. CORK oblige tcp à envoyer des paquets qui font la taille de la MSS (Maximum Segment Size), soit la MTU moins les en-têtes TCP et IP.
- sendfile : Cette directive fait la force de Nginx avec les deux autres. Elle oblige l'utilisation de l'appel système sendfile pour tous les envois de fichiers. Je passe les détails incompréhensibles, mais en gros, c'est plus efficace.
Compression des données
Pour le moment, le cache et la compression des données ne sont pas configurés. On va donc configurer la compression des données (la configuration du cache se fera dans le fichier de configuration proxy.conf).
Pour gérer la compression des données, on rajoute les lignes suivantes dans la partie http du fichier de configuration :
gzip on; # active la compression gzip_comp_level 5; # niveau de compression (de 1 a 9, 9 pour la compression max) gzip_http_version 1.0; # version HTTP minimum pour que la compression soit active gzip_proxied any; # active la compression pour les requetes faites par les clients qui passent par un proxy gzip_types text/plain text/html text/css image/x-icon application/x-javascript; # types MIME pour lesquels la compression est active gzip_disable "MSIE [1-6]\.(?!.*SV1)"; # désactive la compression pour les navigateurs qui ne supportent pas
Plus de détails sur la compression : http://nginx.org/en/docs/http/ngx_http_gzip_module.html
Reverse-proxy
Pour les directives relatives au reverse-proxy, on va, pour plus de clarté, créer un fichier à part. On y définira aussi les options de cache. On va créer le fichier /etc/nginx/conf.d/proxy.conf et y mettre les lignes suivantes :
proxy_redirect off; # desactive la reecriture d'url (inutile ici, les sites sont heberges sur d'autres serveurs) proxy_set_header Host $host; # permet de modifier l'entete HTTP proxy_set_header X-Real-IP $remote_addr; # permet de modifier l'entete HTTP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # permet de modifier l'entete HTTP proxy_hide_header X-Powered-By; # cache le champ X-Powered-By de l'entête HTTP proxy_intercept_errors on; # permet d'intercepter les réponses avec un code de retour supérieur ou égal à 300 proxy_cache_path /var/cache/nginx/site1 levels=1:2 keys_zone=site1:10m inactive=7d max_size=700m; # definit le chemin et les parametres du cache pour le site 1 proxy_cache_path /var/cache/nginx/site2 levels=1:2 keys_zone=site2:10m inactive=7d max_size=700m; # definit le chemin et les parametres du cache pour le site 2 proxy_cache_path /var/cache/nginx/site3 levels=1:2 keys_zone=site3:10m inactive=7d max_size=700m; # definit le chemin et les parametres du cache pour le site 3
Ici, les directives proxy_set_header permettent de réécrire le header pour que les serveurs web voient les requêtes arriver du client, plutôt que du proxy.
Déclaration des serveurs arrières (backend)
On ne prendra ici pour exemple qu'un seul serveur arrière.
Deux dossiers importants :
- /etc/nginx/sites-available : Contient les configurations des sites (tous les sites, même inactifs)
- /etc/nginx/sites-enabled : contient des liens symboliques vers les fichiers de configuration des sites actifs (même principe qu'Apache).
On va ici voir l'exemple du fichier de site reverse-site1. C'est un fichier de configuration standard de Nginx. Il est à placer dans available avec un lien dans enable, comme pour Apache. Attention, ce fichier est bien sur le proxy, par sur les serveurs webs en eux-même !
server { listen 80; # port d'ecoute server_name www.site1.domain site1.domain; # nom du serveur arriere (ici repondra sites www.site1.domain et site1.domain if ($request_method !~ ^(GET|HEAD|POST)$ ) { # Si la requete n'est pas de type GET ou HEAD ou POST return 444; # on renvoie le code 444 (no data), permet de fermer la connexion } location / { proxy_cache site1; # nom de la zone de cache proxy_cache_valid 200 302 2d; # duree du cache pour les codes de retour 200 et 302 (ici 2 jours) proxy_cache_valid 404 1m; # duree du cache pour les code de retour 404 (ici 1 minute) proxy_pass http://www.site1.domain/; # url du serveur arriere } access_log /var/log/nginx/site1-access.log; # fichier de log des acces error_log /var/log/nginx/site1-error.log; # fichier de log des erreurs }
Load Balancing
Le load balancing se fait avec la directive upstream. Par défaut, Nginx fonctionne en mode round-robin (chaque serveur est interrogé à tour de rôle). Un exemple ici de la doc (http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream)
upstream '''backend''' { server backend1.example.com weight=5; server backend2.example.com:8080; server unix:/tmp/backend3; server backup1.example.com:8080 backup; server backup2.example.com:8080 backup; } server { location / { proxy_pass http://'''backend'''; } }
Quelques explications :
- server suivi d'une IP:un nom de domaine et d'un port (éventuel) permet d'indiquer un serveur backend;
- weight correspond au poids du serveur (par défaut, 1). Avec l'exemple du dessus, pour 7 requêtes, 5 vont au premier serveur, une au deuxième, et une au troisième.
- backup marque le serveur en question comme serveur de backup, utilisé seulement si els serveurs primaires sont indisponibles.
- Bien d'autres options sont disponibles.
Mise en place d'un reverse-proxy
Nous allons mettre en place un reverse-proxy, en nous basant sur cette architecture :
Le serveur proxy sera la même machine que j'ai utilisé pour Squid plus tôt; l'utilisateur externe sera en fait ma machine hôte, avec l'IP donnée par le DHCP de la box.
Je commence par mettre en place mes 4 serveurs web, des Debian avec Apache. Rien de compliqué, mais je m'assure que le site01 et le site02 aient une page d'acceuil différente (je ne crée pas d'hôte virtuel : les sites doivent répondre directement depuis leur IP). Une fois que c'est fait et que je les ai testés (avec un client...), je passe à la configuration du reverse-proxy.
C'est parti pour les différents fichiers !
/etc/nginx.conf
#/etc/nginx/nginx.conf user www-data; # user qui fait tourner nginx worker_processes 2; # nb d'instances nginx (ici, ma VM a deux coeurs CPU) # fichier dans lequel est enregistre le pid de nginx (celui du master process, qui lance les workers) pid /run/nginx.pid; events { worker_connections 2000; # nb de connexion max par instance (j'en beaucoup parce que ça consomme vite) } http { sendfile on; # Optimisation des performances tcp_nopush on; # Optimisation des performances tcp_nodelay on; # Optimisation des performances server_tokens off; # masque la version de nginx dans les messages keepalive_timeout 65; # delai d'attente en seconde avant la fermeture d'une connexion include /etc/nginx/mime.types; # liste des types MIME (type de fichier par extension) default_type application/octet-stream; # type par defaut des fichiers non repertories dans mime.type access_log /var/log/nginx/access.log; # fichier de log des acces error_log /var/log/nginx/error.log; # fichier de log des erreurs include /etc/nginx/conf.d/*.conf; # inclusion des fichiers de configuration (on trouvera notamment proxy.conf) include /etc/nginx/sites-enabled/*; # configuration des sites web actifs ###Compression gzip on; # active la compression gzip_comp_level 5; # niveau de compression (de 1 a 9, 9 pour la compression max) gzip_http_version 1.0; # version HTTP minimum pour que la compression soit active gzip_proxied any; # active la compression pour les requetes faites par les clients qui passent par un proxy gzip_types text/plain text/html text/css image/x-icon application/x-javascript; # types MIME pour lesquels la compression est active gzip_disable "MSIE [1-6]\.(?!.*SV1)"; # désactive la compression pour les navigateurs qui ne supportent pas }
/etc/nginx/conf.d/proxy.conf
#/etc/nginx/conf.d/proxy.conf #Ici se trouve la configuration générale du reverse-proxy ###Options générales proxy_redirect off; # desactive la reecriture d'url (inutile ici, les sites sont heberges sur d'autres serveurs) proxy_set_header Host $host; # permet de modifier l'entete HTTP proxy_set_header X-Real-IP $remote_addr; # permet de modifier l'entete HTTP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # permet de modifier l'entete HTTP proxy_hide_header X-Powered-By; # cache le champ X-Powered-By de l'entête HTTP proxy_intercept_errors on; # permet d'intercepter les réponses avec un code de retour supérieur ou égal à 300 ###Options de cache proxy_cache_path /var/cache/nginx/site01 levels=1:2 keys_zone=site1:10m inactive=7d max_size=700m; # definit le chemin et les parametres du cache pour le site 1 proxy_cache_path /var/cache/nginx/site02 levels=1:2 keys_zone=site2:10m inactive=7d max_size=700m; # definit le chemin et les parametres du cache pour le site 2
/etc/nginx/sites-available/site01.conf
#/etc/nginx/sites-available/site01.conf upstream site01 { #Ici, je configure mes deux serveurs backend server 192.168.56.101:80 weight=2; #Répartition de charge : ce serveur (srv1-backend) recoit 2/3 des requêtes server 192.168.56.102:80 weight=1; #Répartition de charge : ce serveur (srv2-backend) recoit 1/3 des requêtes } server { #Ici, je configure le site en lui même listen 80; #Le port sur lequel Nginx écoute server_name www.site01.mondomaine site01.mondomaine; #L'adresse de ce site pour le client location / { #Ce bloc contient les directives de fichiers... proxy_cache site1; #Le cache est "site1" défini dans proxy.conf proxy_cache_valid 200 302 2d; #Cache valide 1 jour pour les pages qui fonctionnent proxy_cache_valid 404 1m; #Cache valide 1 minute pour les erreurs 404 proxy_pass http://site01; #On renvoie vers le bloc "upstream site01", soit vers nos serveurs backend } }
/etc/nginx/sites-available/site02.conf
#/etc/nginx/sites-available/site02.conf upstream site02 { #Ici, je configure mes deux serveurs backend, à poids égal (par défaut, weight=1) server 192.168.56.103:80; #Répartition de charge : ce serveur (srv3-backend) reçoit la moitié des requêtes server 192.168.56.104:80; #Répartition de charge : ce serveur (srv3-backend) reçoit la moitié des requêtes } server { #Ici, je configure le site en lui même listen 80; #Le port sur lequel Nginx écoute server_name www.site02.mondomaine site02.mondomaine; #L'adresse de ce site pour le client location / { #Ce bloc contient les directives de fichiers... proxy_cache site2; #Le cache est "site1" défini dans proxy.conf proxy_cache_valid 200 302 2h; #Cache valide 1 jour pour les pages qui fonctionnent proxy_cache_valid 404 1m; #Cache valide 1 minute pour les erreurs 404 proxy_pass http://site02; #On renvoie nos deux serveurs backend } }
Création du dossier de cache
Il faut créer le dossier de cache et lui filer les droits :
mkdir /var/cache/nginx cd /var/cache/nginx mkdir site01 site 02 cd .. chown -R www-data:www-data nginx
Tests et activation
Notre site est enfin en place ! Il n'y a plus qu'à tester. D'abord les fichiers de configurations :
nginx -t #Doit dire que c'est bon
Ensuite, on redémarre nginx :
systemctl restart nginx systemctl status nginx #Très important : nginx -t ne renvoie pas toutes les erreurs !
Plus qu'à se rendre sur un navigateur client (côté WAN) pour tester.
Si le cache pose problème, il est possible de vider ses dossiers !
Un reverse très simple : mitmproxy
https://mitmproxy.org/ Il s'agit d'un reverse rapide à utiliser pour le debugging, écrit en Python !
<source> apt install mitmproxy
- OU
python3 -m pip install mitmproxy mitmproxy -p 8080 --mode reverse:http://127.0.0.1:1313 </source>