Création d'un serveur proxy filtrant Squid

Sources de la documentation : https://elatov.github.io/2019/01/using-squid-to-proxy-ssl-sites/ et https://grumpytechie.net/2020/02/25/adding-custom-root-ca-certificates-to-debian/

Procédure validée sur Debian 11.

Présentation du projet

Nous allons réaliser un proxy interceptant les communications entre un réseau local et Internet. Dans cette documentation, il filtrera certains domaines et certaines URL, notamment les sites pour adultes et les régies publicitaires.

La machine utilisée possédera deux cartes réseau :

enp0s3
Connectée sur Internet et dont l'adresse IP est obtenue via DHCP
enp0s8
Connectée sur le réseau local et dont l'adresse IP est 10.50.0.1

Notre machine agira comme routeur pour les appareils situés sur le réseau local.

Installation des paquets

Nous allons installer Squid avec support HTTPS, iptables et les serveurs DHCP et DNS :

apt -y install squid-openssl isc-dhcp-server bind9 iptables

Configuration du système

Nous allons configurer l'interface réseau enp0s8. Pour cela, nous modifions le fichier /etc/network/interfaces :

auto lo
iface lo inet loopback

auto enp0s3
iface enp0s3 inet dhcp

auto enp0s8
iface enp0s8 inet static
        address 10.50.0.1
        netmask 255.255.0.0
        post-up bash /etc/iptables-rules

Appliquer ce changement :

service networking restart

Il faut permettre au serveur de transmettre les paquets reçus et d'agir comme un routeur. Pour cela, modifier la ligne suivante dans /etc/sysctl.conf :

net.ipv4.ip_forward=1

Appliquer ce changement :

sysctl -p

Nous allons créer les règles de pare-feu permettant de forcer le trafic entrant depuis l'interface enp0s8 vers le proxy. On crée le fichier /etc/iptables-rules :

Pensez à créer une règle pour SSH si vous utilisez ce service pour configurer votre serveur. Ne vous enfermez pas dehors !
#!/bin/bash
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t filter -F
iptables -t filter -X
iptables -P INPUT DROP
iptables -A INPUT -i enp0s8 -p udp --dport 67 -j ACCEPT           # DHCP
iptables -A INPUT -i enp0s8 -p udp --dport 53 -j ACCEPT           # DNS
iptables -A INPUT -i enp0s8 -p tcp --dport 3129 -j ACCEPT          # Squid HTTP
iptables -A INPUT -i enp0s8 -p tcp --dport 3130 -j ACCEPT         # Squid HTTPS
iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
iptables -t nat -A PREROUTING -i enp0s8 -p tcp --dport 80 -j REDIRECT --to-port 3129
iptables -t nat -A PREROUTING -i enp0s8 -p tcp --dport 443 -j REDIRECT --to-port 3130
iptables -t filter -i enp0s8 -A FORWARD -p tcp --dport 3128 -j ACCEPT
iptables -t filter -i enp0s8 -A FORWARD -p tcp --dport 3129 -j ACCEPT
iptables -t filter -i enp0s8 -A FORWARD -p tcp --dport 3130 -j ACCEPT
iptables -t filter -i enp0s8 -A FORWARD -p tcp --dport 389 -j ACCEPT
iptables -t filter -i enp0s8 -A FORWARD -p udp --dport 53 -j ACCEPT
iptables -t filter -i enp0s8 -A FORWARD -p udp --dport 67 -j ACCEPT
iptables -t filter -i enp0s8 -A FORWARD -j DROP
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Charger les règles iptables :

bash /etc/iptables-rules

Configuration du serveur DHCP

Le serveur DHCP ne doit écouter que sur l'interface LAN. Pour cela, modifier le fichier /etc/default/isc-dhcp-server :

INTERFACESv4="enp0s8"
INTERFACESv6=""

Configurer la zone réseau pour le serveur DHCP dans le fichier /etc/dhcp/dhcpd.conf :

subnet 10.50.0.0 netmask 255.255.0.0 {
        range 10.50.0.10 10.50.255.254;
        option routers 10.50.0.1;
        option domain-name-servers 10.50.0.1;
        option subnet-mask 255.255.0.0;
        option broadcast-address 10.50.255.255;
}

Redémarrer le serveur DHCP :

service isc-dhcp-server restart

Création du script de renouvellement des listes noires

Créer le répertoire qui contiendra les listes noires :

mkdir /etc/squid/blacklist
chown -R proxy:proxy /etc/squid/blacklist

La liste noire des sites pour adultes provient de l'Université de Toulouse 1 Capitole et la liste des régies publicitaires est hébergée sur https://pgl.yoyo.org/adservers/.

Créer le script en charge de la mise à jour des listes noires /opt/refresh-blacklist :

#!/bin/bash
wget -O /etc/blacklist/ads https://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=0&mimetype=plaintext
wget -O /tmp/adult.tar.gz ftp://ftp.ut-capitole.fr/pub/reseau/cache/squidguard_contrib/adult.tar.gz
cd /tmp
tar zxvf /tmp/adult.tar.gz
cp -R /tmp/adult /etc/blacklist/
rm /tmp/adult.tar.gz
service squid reload

Configurer cron pour mettre à jour les listes noires toutes les nuits à 2 heures du matin. Pour cela, exécuter la commande suivante :

crontab -e

Ajouter la configuration suivante :

0 2 * * * bash /opt/refresh-blacklist

Exécuter le script de renouvellement des listes noires :

bash /opt/refresh-blacklist

Configuration de Squid

Squid intervenant comme intermédiaire entre le client et le serveur, l'interception des communications HTTPS impose à Squid de générer les certificats SSL pour les domaines contactés.

Nous allons créer la base de données des certificats SSL de Squid :

/usr/lib/squid/security_file_certgen -c -s /var/spool/squid/ssl_db -M 4MB
chown -R proxy:proxy /var/spool/squid

Sauvegarder la configuration par défaut de Squid et effacer la configuration :

cp /etc/squid/squid.conf /etc/squid/squid.conf.bak
echo '' > /etc/squid/squid.conf

Créer la configuration de Squid pour analyser le trafic de manière transparente en bloquant les URL et les domaines renseignés dans des fichiers de listes noires. Pour cela, on édite le fichier de configuration /etc/squid/squid.conf :

http_port 3128
http_port 3129 transparent
https_port 3130 intercept ssl-bump cert=/etc/squid/cert/squid_proxyCA.pem generate-host-certificates=on
sslcrtd_program /usr/lib/squid/security_file_certgen -s /var/spool/squid/ssl_db -M 4MB
ssl_bump bump all
ssl_bump peek all
acl purge method PURGE
http_access allow purge localhost
http_access deny purge
coredump_dir /var/spool/squid
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
acl Safe_ports port 80       # http
acl Safe_ports port 443       # https
acl CONNECT method CONNECT
acl adult dstdomain "/etc/blacklist/adult/domains"
acl adult url_regex "/etc/blacklist/adult/urls"
acl ads dstdomain "/etc/blacklist/ads"
http_access deny !Safe_ports
http_access allow CONNECT
http_access deny manager
http_access allow localhost
http_access deny adult
http_access deny ads
http_access allow all

Créer le certificat de l'autorité de certification de Squid :

mkdir -p /etc/squid/cert/
openssl req -new -newkey rsa:4096 -sha256 -nodes -x509 -keyout /etc/squid/cert/squid_proxyCA.pem -out /etc/squid/cert/squid_proxyCA.pem
chown -R proxy:proxy /etc/squid/cert/
chmod 0400 /etc/squid/cert/squid_proxyCA.pem

Ajouter le certificat de l'autorité de certification de Squid dans le magasin des autorités de certifications reconnues :

mkdir -p /usr/local/share/ca-certificates
openssl x509 -inform PEM -in /etc/squid/cert/squid_proxyCA.pem -out /usr/local/share/ca-certificates/squid_proxyCA.crt
update-ca-certificates

Redémarrer le service Squid :

service squid restart

Installation du certificat de l'autorité de certification sur les clients

Sur le client, copier le fichier /usr/local/share/ca-certificates/squid_proxyCA.crt situé sur le serveur dans le répertoire /usr/local/share/ca-certificates/ du client.

Mettre à jour le magasin des certificats :

update-ca-certificates