Et c’est parti pour la mise en place d’une protection parentale pour la famille afin de filtrer les accès Web (et leurs contenus) de manière transparente pour tous les périphériques de la famille. Les loutors finiront un jour par avoir accès à Internet et je préfère prendre les devants pour éviter toute surprise.
Pour cela, j’utilise mon Raspberry PI 3, installé avec Raspbian Jessie en tant que passerelle, pour séparer mon réseau interne d’Internet.
Vu que le RP fait office de passerelle avec 2 interfaces réseaux, eth0 en interne et eth1 en externe, la configuration routeur est déjà faite et je ne détaillerai pas ces opérations dans ce post.
Pour mettre en place cette protection parentale, les paquets suivants seront installés
- Squid3 qui assure la partie “proxy” et intercepte les protocoles HTTP et HTTPS
- SquidGuard qui autorise ou non les domaines à visiter, les IP du réseaux locales, les heures de navigation, …
- IpTables pour rerouter le trafic HTTP et HTTPS sur squid pour rendre le proxy “transparent”
- Nginx avec le support PHP pour afficher une belle page Web en cas de site non-autorisé
Quelle version de Squid ?
Par défaut, la version de Squid est la 3.4. Cette version ne permet pas de gérer le protocole HTTPS de manière simple (SSL bumping très rudimentaire).
Avec la version 3.4, on est obligé de déployer un certificat SSL sur les PC/tabelettes/smartphone pour pouvoir décrypter le contenu des paquets. En effet, les navigateurs récents stoppent toute connexion HTTPS dès qu’une activité suspecte sur le certificat est détecté. Vu que Squid 3.4 remplace le certificat du site distant par un certificat dynamique, le navigateur pense à une attaque de type “Man In The Middle”.
Mais outre les questions d’éthique (je ne peux plus proposer à mes invités ma connexion Wifi) que cela peut poser en plus des problèmes de sécurité, le déploiement du certificat SSL me parait trop lourd.
La version 3.5 introduit une nouvelle option, “Peek and Splice” dans la fonctionnalité ssl_bump qui permet de choisir quelle partie de la connexion SSL on souhaite vérifier. Dans notre cas, on souhaite vérifier le nom de domaine lors du TCP CONNECT en HTTPS et non le contenu des données ou l’URL.
Il va donc falloir récupérer les sources de Squid 3.5 et les recompiler à la sauce Debian.
Mise à jour de sa distrib’
- On commence tout d’abord par une petite mise à jour de sa distribution favorite
123sudo apt-get updatesudo apt-get upgradesudo reboot
Compilation de Squid 3.5
- On installe les paquets nécessaires, on télécharge les sources de squid 3.5, on édite quelques fichiers et on compile le tout
123456789101112131415#Installation des paquetssudo apt-get install devscripts build-essential fakeroot debhelper dh-autoreconf cdbssudo apt-get build-dep squid3sudo apt-get install libssl-dev#Création du répertoire pour la compilationmkdir -p ~/build/squid3cd ~/build/squid3#Récupération et décompilation des sourceswget http://http.debian.net/debian/pool/main/s/squid3/squid3_3.5.23-3.dscwget http://http.debian.net/debian/pool/main/s/squid3/squid3_3.5.23.orig.tar.gzwget http://http.debian.net/debian/pool/main/s/squid3/squid3_3.5.23-3.debian.tar.xzdpkg-source -x squid3_3.5.23-3.dsccd squid3-3.5.23 - A ce stade, il faut modifier 2 fichiers pour que la compilation se déroule correctement :
- ~/build/squid3/squid3-3.5.23/debian/rules : les flags de compilation sont ajustés pour rajouter le support SSL (non activé par défaut) + suppression d’option d’authentification inutile
12345678910111213141516171819202122232425262728293031323334DEB_CONFIGURE_EXTRA_FLAGS := BUILDCXXFLAGS="$(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)" \--datadir=/usr/share/squid \--sysconfdir=/etc/squid3 \--libexecdir=/usr/lib/squid \--mandir=/usr/share/man \--enable-inline \--disable-arch-native \--enable-async-io=8 \--enable-storeio="ufs,aufs,diskd,rock" \--enable-removal-policies="lru,heap" \--enable-delay-pools \--enable-cache-digests \--enable-icap-client \--enable-follow-x-forwarded-for \--enable-auth-basic="DB,fake,getpwnam,LDAP,NCSA,NIS,PAM,POP3,RADIUS,SASL,SMB" \--enable-auth-digest="file,LDAP" \--enable-auth-negotiate="kerberos,wrapper" \--enable-auth-ntlm="fake,smb_lm" \--enable-external-acl-helpers="file_userip,kerberos_ldap_group,LDAP_group,session,SQL_session,time_quota,unix_group,wbinfo_group" \--enable-url-rewrite-helpers="fake" \--enable-eui \--enable-esi \--enable-icmp \--enable-zph-qos \--disable-translation \--with-swapdir=/var/spool/squid \--with-logdir=/var/log/squid \--with-pidfile=/var/run/squid.pid \--with-filedescriptors=65536 \--with-large-files \--with-default-user=proxy \--with-openssl \--enable-ssl \--enable-ssl-crtd - ~/build/squid3/squid3-3.5.23/debian/control : la ligne de contrôle des dépendances est mise à jour pour supprimer des dépendances inutiles
1Build-Depends: libldap2-dev, libpam0g-dev, libdb-dev, cdbs, libsasl2-dev, debhelper, libcppunit-dev, libkrb5-dev, comerr-dev, libcap2-dev [linux-any], libexpat1-dev, libxml2-dev, autotools-dev, libltdl-dev, dpkg-dev (>= 1.16.1~), pkg-config, libnetfilter-conntrack-dev [linux-any], nettle-dev, libgnutls28-dev, lsb-release
- ~/build/squid3/squid3-3.5.23/debian/rules : les flags de compilation sont ajustés pour rajouter le support SSL (non activé par défaut) + suppression d’option d’authentification inutile
- Puis on lance la compilation
123#Compilation./configuredebuild -us -uc -b
Installation de Squid 3.5
- Une fois la compilation terminée, on peut installer les paquets fraîchement compilés
1234567cd ~/build/squid3#Installation des paquetssudo dpkg -i squid-common_3.5.23-3_all.deb squidclient_3.5.23-3_armhf.deb squid_3.5.23-3_armhf.deb#On marque le paquet pour éviter une mise à joursudo apt-mark hold squid squid-common - On crée maintenant le fichier /etc/squid3/squid.conf, on rajoute son réseau et on l’autorise avec 2-3 autres modifications. Comme beaucoup de réseaux locaux, le mien est en 192.168.1.X.
Pour la génération du certificat SSL, j’ai réutilisé celui déjà mis en place au niveau du serveur Nginx en tant que reverse proxy. La procédure de création du certificat n’est donc pas décrite.
Le fichier doit ressembler à ça :
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960#Définition des ACLacl SSL_ports port 443acl Safe_ports port 80 # httpacl Safe_ports port 21 # ftpacl Safe_ports port 443 # httpsacl Safe_ports port 70 # gopheracl Safe_ports port 210 # waisacl Safe_ports port 1025-65535 # unregistered portsacl Safe_ports port 280 # http-mgmtacl Safe_ports port 488 # gss-httpacl Safe_ports port 591 # filemakeracl Safe_ports port 777 # multiling httpacl CONNECT method CONNECT#Le réseau localacl LocalNet src 192.168.1.0/24#ACL : Liste des domaines non-vérifiésacl broken_sites ssl::server_name .google.comacl broken_sites ssl::server_name .google.fracl broken_sites ssl::server_name .google.chacl bump_step1 at_step SslBump1#Définition des autorisationshttp_access deny !Safe_portshttp_access deny CONNECT !SSL_portshttp_access allow localhost managerhttp_access deny managerhttp_access allow localhosthttp_access allow LocalNethttp_access deny all#Configuration du SSL proxysslproxy_cert_error allow allsslproxy_flags DONT_VERIFY_PEERsslproxy_options NO_SSLv2,NO_SSLv3,SINGLE_DH_USE#Localhost et les sites sur liste blanche ne sont pas vérifiésssl_bump splice localhostssl_bump splice broken_sites#On ne vérifie que CONNECTssl_bump peek bump_step1 allssl_bump splice all#Définition des ports d'écoutehttp_port 3128 transparenthttps_port 3129 transparent ssl-bump generate-host-certificates=on version=4 \cafile=/etc/certs/example.pem \cert=/etc/certs/example.crt \key=/etc/erts/example.keycoredump_dir /var/spool/squid3refresh_pattern ^ftp: 1440 20% 10080refresh_pattern ^gopher: 1440 0% 1440refresh_pattern -i (/cgi-bin/|\?) 0 0% 0refresh_pattern . 0 20% 4320cache_dir ufs /cache 400 16 256cache_access_log /var/log/squid3/access.logcache_effective_user proxy - Une fois la configuration de Squid3 faite, on s’occupe du répertoire /cache visant à améliorer la navigation. Le DD étant une SD, je monte ce répertoire en RAM plutôt que sur la SD pour économiser la flash.
1sudo mkdir /cache - Vient l’édition du fichier /etc/fstab afin de monter 500Mo de RAM dans le répertoire /cache. La taille de 500Mo est à ajuster en fonction de la taille de cache déclarée dans le fichier /etc/squid3/squid.conf. Il est recommandé de ne pas utiliser 100% du /cache mais 80% (500 x 80% = 400). D’où les 400Mo déclaré dans /etc/squid3/squid.conf et les 500Mo dans /etc/fstab.
1tmpfs /cache tmpfs defaults,noatime,nosuid,size=500m 0 0 - Un redémarrage des services et on peut désormais tester notre serveur proxy depuis un poste. L’IP de mon raspberry est 192.168.1.5. La navigation Internet doit pouvoir s’effectuer sans souci depuis le poste client.
123sudo service squid3 stopsudo squid3 -zsudo service squid3 start
SquidGuard
- Comme précédemment, on installe les paquets nécessaires.
1sudo apt-get install squidguard - Maintenant, il s’agit d’utiliser des listes contenant les sites et contenus interdits ou à surveiller. L’université de Toulouse met à disposition gracieusement de telles listes et on va donc récupérer ces listes pour les utiliser.
1234sudo cd /var/lib/squidguard/db/sudo wget http://dsi.ut-capitole.fr/blacklists/download/blacklists.tar.gzsudo tar -zxvf blacklists.tar.gzsudo chown -R proxy:proxy /var/lib/squidguard/db/ - On édite le fichier /etc/squidguard/squidGuard.conf avec la liste des IP des appareils autorisés à tous les contenus (déclaration du group parents). Pour chaque contenu non-autorisé, un fichier *contenu*.access est crée dans le répertoire /var/log/squidguard afin de logguer les tentatives d’accès.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105dbhome /var/lib/squidguard/dblogdir /var/log/squidguardsrc parents {ip 192.168.1.90}dest ads {domainlist blacklists/ads/domainsurllist blacklists/ads/urlslog ads.access}dest adult {domainlist blacklists/adult/domainsurllist blacklists/adult/urlslog adult.access}dest aggressive {domainlist blacklists/aggressive/domainsurllist blacklists/aggressive/urlslog aggressive.access}dest agressif {domainlist blacklists/agressif/domainsurllist blacklists/agressif/urlslog agressif.access}dest arjel {domainlist blacklists/arjel/domainslog arjel.access}dest drogue {domainlist blacklists/drogue/domainsurllist blacklists/drogue/urlslog drogue.access}dest drugs {domainlist blacklists/drugs/domainsurllist blacklists/drugs/urlslog drugs.access}dest malware {domainlist blacklists/malware/domainsurllist blacklists/malware/urlslog malware.access}dest mixed_adult {domainlist blacklists/mixed_adult/domainsurllist blacklists/mixed_adult/urlslog mixed_adult.access}dest phishing {domainlist blacklists/phishing/domainsurllist blacklists/phishing/urlslog phishing.access}dest porn {domainlist blacklists/porn/domainsurllist blacklists/porn/urlslog porn.access}dest proxy {domainlist blacklists/proxy/domainsurllist blacklists/proxy/urlslog proxy.access}dest sexual_education {domainlist blacklists/sexual_education/domainsurllist blacklists/sexual_education/urlslog sexual_education.access}dest violence {domainlist blacklists/violence/domainsurllist blacklists/violence/urlslog violence.access}dest warez {domainlist blacklists/warez/domainsurllist blacklists/warez/urlslog warez.access}acl {parents {pass all}default {pass !ads !adult !aggressive !agressif !arjel !drogue !drugs !malware !mixed_adult !phishing !porn !proxy !sexual_education !violence !warez allredirect http://192.168.1.5/block.php?caddr=%a&cname=%n&user=%i&group=%s&target=%t&url=%u}} - On charge les listes téléchargées dans squidGuard. A noter que ces 2 commandes doivent être relancées à chaque modification du fichier /etc/squidguard/squidGuard.conf
12sudo squidGuard -C allsudo chown -R proxy:proxy /var/lib/squidguard/db/ - Nouvelle édition du fichier /etc/squid3/squid.conf pour rajouter la ligne suivante
1url_rewrite_program /usr/bin/squidGuard -c /etc/squidguard/squidGuard.conf - Re redémarrage des services et nouveau test sur un site interdit
123sudo service squid3 stopsudo squid3 -zsudo service squid3 start - La page suivante doit apparaître, ce qui est normal vu que nginx n’a pas encore été installé et configuré
- Côté log, on peut voir que les connexions HTTP et HTTPS sont bien interceptées
121496669801.800 50 192.168.1.30 TAG_NONE/503 0 CONNECT www.y*****n.com:443 - HIER_NONE/- -1496670016.301 6 192.168.1.30 TCP_MISS/200 1614 GET http://www.y*****n.com/ - HIER_DIRECT/192.168.1.5 text/html
Nginx
- Comme vu, on installe les paquets nécessaires
1sudo apt-get install nginx php5-fpm - On édite le fichier /etc/php5/fpm/pool.d/www.conf pour décommenter/vérifier la ligne suivante
1listen = /var/run/php5-fpm.sock
Vu que squidGuard et Nginx tournent sur la même machine, on utilise donc une socket Unix pour la communication. - On redémarre PHP5
1sudo service php5-fpm restart - On crée un nouveau fichier /etc/nginx/conf.d/php5-fpm.conf pour indiquer la location de la socket
123upstream php5-fpm-sock {server unix:/var/run/php5-fpm.sock;} - Puis, édition du fichier /etc/nginx/sites-available/default pour prendre en charger les fichiers *.php et fixer les accès. On autorise seulement l’accès au réseau local
12345678910111213141516171819202122server {listen 80;root /var/www/squidguard;index block.php;server_name localhost;location / {try_files $uri $uri/ /block.php;allow 192.168.1.0/8;allow 127.0.0.1;deny all;}location ~ \.php$ {try_files $uri $uri/ =404;fastcgi_index block.php;fastcgi_pass php5-fpm-sock;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;include /etc/nginx/fastcgi_params;}} - Un petit fichier de test pour vérifier que Nginx avec le support PHP5 fonctionne bien
1echo '<?php phpinfo(); ?>' > /var/www/squidguard/info.php - On redémarre Nginx et on affiche la page PHP Info
1sudo service nginx restart
SquidGuard, le retour
- On va customiser notre page indiquant les sites bloqués. Pour cela, on crée le fichier /var/www/squidguard/block.php
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647<?phpif (@$_GET['cname']) $details[] = "Client Name: {$_GET['cname']}";if (@$_GET['caddr']) $details[] = "Client IP: {$_GET['caddr']}";if (@$_GET['user']) $details[] = "Client User: {$_GET['user']}";if (@$_GET['group']) $details[] = "Group: {$_GET['group']}";if (@$_GET['target']) $details[] = "Category: {$_GET['target']}";if (isset($details) && $details) $details = implode(" | ", $details);?><!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=utf8" /><title>Site Web bloqué</title><link rel="stylesheet" type="text/css" href='http://192.168.1.5/filter.css'></head><body><div id="message"><center><img height=300px src='http://192.168.1.5/block.png' /></center></div><div class="outer"><div class="header">Contrôle parentale activé pour ce poste</div><div class="inner"><div class="error"><p>Accès refusé !</p></div><div class="msg"><p>Site Web bloqué</p><p><strong>URL: <?php printf("<a href=\"%s\">%s</a>", @$_GET['url'], @$_GET['url']);?></strong></p><p><?php if (isset($details) && $details) print $details; ?></p></div></div><div class="footer">Web Filtering by Squid3 and SquidGuard on Pumpkin</div></div></body></html> - Puis le fichier /var/www/squidguard/filter.css
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950@CHARSET "UTF-8";body {background-color: #ffffff;font-family: verdana, arial, sans serif;}div.outer {width: 70%;margin: 20px auto;}div.header {padding: 10px;background-color: #c0c0c0;text-align: right;font-size: 60%;}div.footer {padding: 5px;background-color: #c0c0c0;text-align: right;font-size: 60%;}div.inner {text-align: center;background-color: #f4f4f4;text-align: center;padding: 20px;}div.msg {padding: 20px;margin-top: 20px;background-color: #e2e2e2;color: black;font-size: 80%;}div.error {letter-spacing: 0.5em;word-spacing: 1em;padding: 20px;background-color: #ff0000;color: white;font-size: 200%;font-weight: bold;} - Un nouveau test sur un contenu interdit en HTTP devrait nous afficher la jolie page suivante
- Pour le même site mais en HTTPS, pas de jolie page Web mais un message du navigateur avertissant d’un souci de confidentialité dans la chaîne SSL entre le site et lui. Cette erreur apparaîtra sur tous les navigateurs récents (Opera Neon, Chrome, Firefox, Safari, …).
- Côté log, on a bien l’entrée correspondante
123/var/log/squidguard % tail -f adult.access2017-06-05 17:09:00 [12763] Request(default/adult/-) http://www.youporn.com/favicon.ico 192.168.1.30/pollux.loutor - GET REDIRECT2017-06-05 17:09:06 [12763] Request(default/adult/-) www.youporn.com:443 192.168.1.30/pollux.loutor - CONNECT REDIRECT
Configuration du proxy transparent
- Si le paquet IPtable n’est pas déjà installé
1sudo apt-get install iptables - Puis, mise à jour des règles IPTables pour intercepter le trafic HTTP et HTTPS et le re-router sur le port 3128 et 3129 du proxy squid3
1234567*nat-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.5:3128-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 3128-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 192.168.1.5:3129-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 3129-A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADECOMMIT - On fait un nouveau test en pensant bien à désactiver la configuration proxy. Le résultat doit être le même que précédemment, la page de restriction doit s’afficher.
Mise à jour des listes
- Histoire d’automatiser le téléchargement des listes et de toujours avoir les dernières nouveautés, un p’tit script /etc/cron.daily/blacklist.sh est mis en place
123456789#!/bin/shcd /var/lib/squidguard/dbrm -rf blacklistswget http://dsi.ut-capitole.fr/blacklists/download/blacklists.tar.gztar -zxvf blacklists.tar.gzrm blacklists.tar.gzsquidGuard -C allchown -R proxy:proxy /var/lib/squidguard/db/service squid3 restart
Ressources utilisées
- http://www.pihomeserver.fr/2015/09/01/un-controle-parental-grace-au-raspberry-pi-squid-et-squidguard
- https://adilmehmoodbutt.wordpress.com/2014/02/19/how-to-install-squid3-transparent-proxy-server/
- https://www.guillaume-leduc.fr/projet-installation-configuration-nginx-php-fpm.html
- https://redmine.pfsense.org/issues/6777
- https://docs.diladele.com/administrator_guide_5_0/install/rpi/index.html
- http://david.mercereau.info/serveur-proxy-squid3-avec-ssl-rebuild-debian-squeeze-package/