Mise en place d'une passerelle « sécurisée » pour le partage d'une connexion Internet

Nicolas Vallée

Le but de cet article est de permettre à tout débutant « éclairé » de mettre en place une passerelle, ne nécessitant pas des performances monstrueuses, afin de partager de manière sécurisée, et sécurisante, sa connexion Internet.

Ici, nous avons choisi de montrer l'exemple sur une machine Debian… vous pourrez facilement vous adapter à votre distribution, en changeant juste les procédures d'installation. Par ailleurs, je considère que le monde extérieur est branché sur eth0, et que les machines utilisateurs sont reliées via eth1. ♪

- Titre : Mise en place d'une passerelle « sécurisée » pour le partage d'une connexion Internet

- Auteur : Nicolas Vallée

- Parution : 9 août 2006

- Licence : Copyright (c) 2006 Nicolas Vallée. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. Read the full license here : http://www.gnu.org/licenses/fdl.txt

Sommaire

- I. Serveurs

- I-A. Squid

- I-A-1. Réinitialiser le cache

- I-A-2. Authentification

- I-A-3. Cascader des proxys

- I-B. DansGuardian

- II. Quelques petits plus…

- II-A. Proxy Transparent

- II-B. Interdire ping depuis l'extérieur

- II-C. Fermer certains ports

- II-D. Se doter d'un nom de domaine

- II-E. Autres services

- II-F. Quelques notions sur iptables

- II-G. Compléments

- III. Divers

- III-A. Références

- III-B. Conclusion

I - Serveurs

I-A - Squid

Commençons d'abord par installer le plus important des serveurs : un proxy http. Ici, nous avons choisi Squid, qui est très populaire, stable et dispose de nombreux modules…

installation de squid

apt-get install squid

Ensuite vous devez éditer le fichier /etc/squid/squid.conf

configuration de squid - /etc/squid/squid.conf

# ne doit ecouter que les appels locaux
# pour infos, 3128 est le port standard de Squid
http_port 127.0.0.1:3128

# nom visible lors des messages aux clients
visible_hostname gw.domain.com

# remplacer zone_ip_interne par votre zone personnelle
# par exemple 192.168.1.0
acl LocalNet src zone_ip_interne/255.255.255.0

# autoriser les acces venant de cette zone
http_access allow LocalNet

# Taille optimale de mémoire vive utilisée pour stocker du cache
cache_mem 16 MB
# voir aussi cache_mem_low et cache_mem_high

# Taille maximale des objets stockés dans le cache
maximum_object_size 8 MB
# Taille minimale des objets stockés dans le cache
minimum_object_size 0 KB

# Paramétrage d'un cache sur un disque
# 1 - Type de stockage
# 2 - Emplacement du cache
# 3 - Taille totale du cache en MB
# 4 - Nombre de répertoires de niveau 1 et de niveau 2
cache_dir ufs /var/spool/squid 200 16 256

Vous devez ensuite redémarrer squid de manière à ce que les nouveaux paramètres soient pris en compte.

/etc/init.d/squid restart

I-A-1 - Réinitialiser le cache

Il arrive parfois que le cache local n'ait pas la bonne forme, car squid n'a pas été arrêté correctement… vous devez alors le reconstruire.

rm -rf /var/spool/squid/*
squid -z

I-A-2 - Authentification

Vous ne devez pas avoir activé le mode proxy transparent, si vous souhaitez mettre en place une authentification.

Vous avez sûrement remarqué que le seul contrôle effectué dans /etc/squid/squid.conf porte sur les adresses IP des machines clientes. Mais vous pouvez avoir envie de faire plus…

Pour cela, il existe différentes méthodes :

- ldap_auth, pour authentifier les utilisateurs depuis un annuaire LDAP ;

- smb_auth, pour utiliser l'authentification d'un contrôleur de domaine Windows NT (lien) ;

- ncsa_auth, utilisant un fichier d'utilisateurs local.

Dans un premier temps, nous nous contenterons de ncsa_auth. Pour d'autres utilisations, vous trouverez facilement, car c'est similaire aux méthodes utilisées par d'autres serveurs ;)

Créez un fichier pour gérer les utilisateurs, et remplissez-le via l'utilitaire htpasswd (celui des .htaccess/.htpasswd d'Apache)

/etc./squid/users

touch /etc./squid/users
htpasswd -b /etc./squid/users <nom de l'utilisateur>  <mot de passe>

Il vous est alors conseillé de tester à la main… en lançant le module d'authentification, et en lui donnant les entrées par la console. Sortez en tapant Ctrl+d

/usr/lib/squid/ncsa_auth /etc./squid/users
username password
OK
bas_user bad_passwd
ERR

Si ça marche, on peut alors passer au mode automatique. Pour cela, allez modifier votre fichier /etc/squid/squid.conf, pour y ajouter ceci :

# preciser qu'on oblige a passer par l'authentification
acl Users proxy_auth REQUIRED
http_access deny !Users

# pour indiquer le mode d'authentification
authenticate_program /usr/lib/squid/ncsa_auth /etc./squid/users

# duree de validite de l'authentification
authenticate_ttl 30 minutes
# lier un utilisateur a une adresse ip pendant un laps de temps
authenticate_ip_ttl 30 minutes

Pour éviter qu'un utilisateur ne donne son accès à tous ses amis (ou se le fasse squatter), on peut aussi limiter le nombre de connexions différentes qu'il peut effectuer. Pour cela, rajouter ceci dans /etc/squid.conf

# duree du couplage adresse ip <-> utilisateur
authenticate_ip_ttl 2 hours

# declaration du mode authentification
acl users proxy_auth required

# nombre de sessions simultanees maximal pour un utilisateur
acl maxauth max_user_ip -s 1

# regles d'acces
http_access deny maxauth
http_access allow users

I-A-3 - Cascader des proxys

Il arrive parfois que votre passerelle se trouve dans un sous-réseau, et donc doive passer par une autre passerelle pour se connecter à Internet. Ce n'est pas très grave, tout est prévu dans Squid… :D
Il vous suffit d'ajouter dans votre /etc/squid/squid.conf

# la commande indispensable
cache_peer ip_proxy_general parent port_de_autre_proxy 3130 no-query default

# une optimisation pour naviguer directement entre les deux passerelles
cache_peer_domain ip_proxy_general !.domain.com

# avoir quand meme des logs...
debug_options ALL, 9

I-B - DansGuardian

Maintenant, nous allons installer un filtre, DansGuardian, étant un module de squid, afin de :

- interdire l'accès à des contenus peu recommandables (avec possibilité de régler le seuil, d'interdire certains mots-clés, etc.) ;

- gérer les téléchargements de fichiers potentiellement dangereux (exécutables, scripts, etc.) ;

- contrôler les virus (à partir de la version 2.9 en standard ; sinon à partir de la 2.8 si recompilation avec le plugin DGAV).

Commençons par l'installer…

apt-get install dansguardian

Maintenant, il faut le configurer. Commençons par le strict minimum pour le faire fonctionner, avec le fichier /etc/dansguardian/dansguardian.conf

configuration de DansGuardian - /etc/dansguardian/dansguardian.conf

# Commentez cette ligne, sinon DansGuardian ne voudra pas démarrer...
# UNCONFIGURED

# Changez la langue des messages envoyes aux utilisateurs
#language = 'ukenglish'
language = 'french'

# N'autorisez que les connexions depuis votre reseau local...
filterip = IP_interne
# Choisissez le port que va ecouter DansGuardian
filterport = 8080

# Mettez ici l'adresse pour joindre Squid
proxyip = 127.0.0.1
# Mettez ici le port qu'écoute Squid
proxyport = 3128

Commençons à raffiner… et configurons le fichier /etc/dansguardian/dansguardianf1.conf

configuration de DansGuardian - /etc/dansguardian/dansguardianf1.conf

# autorise un contenu jusqu'à une certaine limite
# on peut abaisser le seuil
#   - 50 pour jeunes enfants
#   - 100 pour adolescents
#   - 160 pour jeunes adultes
naughtynesslimit = 160

# autorisez toutes les extensions au téléchargement
# utile pour les mises à jour ou autre...
# mais à vos risques et périls, vous devrez gérer une partie de la sécurité au niveau des machines clientes
# vous pouvez aussi seulement autoriser certaines extensions,
# en le commentant dans le fichier /etc./dansguardian/bannedextensionlist
# par exemple, il suffit de commenter les extensions .gz pour pouvoir installer et mettre à jour une machine debian
bannedextensionlist = '/dev/null'
#bannedextensionlist = '/etc./dansguardian/bannedextensionlist'

Ici, nous sommes assez permissifs avec les utilisateurs, que nous considérons comme suffisamment autonomes, et responsables… ce n'est pas forcément votre cas, et sachez qu'il y a de nombreux réglages possibles dans ce fichier.

II - Quelques petits plus…

II-A - Proxy Transparent

On peut vouloir configurer un proxy transparent. Ainsi, les machines clientes ne devront pas être configurées spécialement pour aller sur Internet.

/etc/squid/squid.conf

httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on

# activer le routage d'adresses
echo 1 > /proc/sys/net/ipv4/ip_forward

# vous devez adapter zone_ip_interne et IP_interne

# exemple zone_ip_interne = 192.168.0.0
iptables -t nat -A PREROUTING -s zone_ip_interne/255.255.255.0 \
-p tcp -m tcp --dport 80 -j REDIRECT --to-port 8080
# exemple IP_interne = 192.168.0.1
iptables -t nat -A PREROUTING -s zone_ip_interne/255.255.255.0 \
-p tcp -m tcp --dport 80 -j DNAT --to-destination IP_interne:8080

II-B - Interdire ping depuis l'extérieur

Il peut être utile d'interdire le ping depuis l'extérieur, surtout si votre machine est directement reliée à un modem, et non un routeur… car dans une telle situation, vous êtes en première ligne. D'ailleurs, il vaut mieux toujours penser qu'on est dans la pire des situations, car des petits malins finiront par nous prouver qu'on était bien en dessous de la vérité.

Pour cela, nous allons créer un fichier /etc/init.d/no_ping_from_eth0

/etc/init.d/no_ping_from_eth0

#! /bin/sh
echo "Setting 'No Ping From Red Zone'"
iptables -i eth0 -A INPUT -p icmp -j DROP

Il faut ensuite le placer au niveau 2 du démarrage… enfin, je conseille le niveau 2 ;)

update-rc.d no_ping_from_eth0 start 99 2 5 .

II-C - Fermer certains ports

Pour des raisons de sécurité, il est parfois utile de fermer certains ports… pour les services inutilisés.

On commence par regarder les ports ouverts à n'importe quelle machine…

netstat -lp | grep "*"

Toutefois, c'est un peu lourd à décrypter… et pas forcément parlant. On peut aussi utiliser cette commande.

lsof -P | grep TCP | grep '*:'
# la sortie est formatee ainsi
# service    ...    TCP    *:port (LISTEN)

Ainsi, vous voyez quel processus utilise quel port. Ensuite, quand on voit un process inutile, on commence par chercher sur Google à quoi il peut bien servir. Si l'on veut toujours le supprimer, on commence par l'arrêter « temporairement »…

/etc/init.d/service stop

On vérifie que tout fonctionne normalement… si oui, on veut qu'il ne démarre pas tout simplement.

update-rc.d -n service remove
# on verifie d'abord ce que cela va realiser... puis, on fait :
update-rc.d -f service remove

Par exemple, avec l'installation minimale par défaut de la debian sarge, on pourrait désactiver les services suivants :

- portmap (port 111) ;

- inetd (port 113) ;

- nfs-common (statd port 742).

On peut aussi fermer le ssh (port 22) sur la zone rouge (eth0), mais cela dépend de votre utilisation…

Si vous n'avez pas besoin de cet accès extérieur, ajoutez cette ligne dans /etc/ssh/sshd_config

/etc/ssh/sshd_config

# Vous devez adapter IP_interne à vos besoins
ListenAddress IP_interne

II-D - Se doter d'un nom de domaine

Si vous souhaitez bénéficier d'un accès extérieur pour un service quelconque (http, ssh, ftp, etc.), vous pouvez souhaiter disposer d'un nom de domaine… ce qui évite d'avoir à apprendre son IP publique par cœur, ou permet de faciliter l'usage des IP dynamiques. Prenez un compte gratuit sur DynDNS par exemple.

Une fois que cela est fait, si vous êtes dans le cas d'une IP publique dynamique, il vous faut installer un client dyndns.

apt-get install ipcheck

Ensuite, il faut créer un script /usr/local/sbin/update_ip_dyndns.sh

#! /bin/sh
/usr/sbin/ipcheck -l -r checkip.dyndns.org:8245 login password hostname

Maintenant, il faut exécuter ce script régulièrement, afin qu'il mette à jour votre IP publique auprès de DynDNS. Il faut donc ajouter à votre crontab.

crontab -e
# cela va vous ouvrir un fichier avec votre editeur prefere...
# et il faudra ajouter cette ligne
*/10     *       *       *       *      /usr/local/sbin/update_ip_dyndns.sh

II-E - Autres services

Si vous avez besoin d'ouvrir des ports pour des services ne passant pas par une passerelle http, il vous faudra soit installer un « proxy » spécifique (ftp, smtp) ; soit quelques notions d'iptables… un article est en cours de rédaction avec Spoutnik.

Nous allons maintenant montrer comment ouvrir l'accès vers un port spécifique à l'extérieur, depuis les machines situées derrière la passerelle, et ce, de manière transparente. L'exemple sera avec le protocole SSH, associé au port tcp 22.

IF_LOCAL="eth1"
IF_NET="eth0"
iptables -A FORWARD -d zone_ip_interne/255.255.255.0 -i ${IF_LOCAL} -o ${IF_NET} \
--dport 22 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s zone_ip_interne/255.255.255.0 -i ${IF_LOCAL} -o ${IF_NET} \
--dport 22 -m state --state ! INVALID -j ACCEPT

On peut aussi, si l'on ne veut pas s'embêter, laisser la zone verte sortir librement…

IF_LOCAL="eth1"
IF_NET="eth0"

## On active la translation d adresse pour l'ensemble du reseau local pour l ensemble des ports
iptables -t nat -A POSTROUTING -o ${IF_NET} -i ${IF_LOCAL} -s zone_ip_interne/255.255.255.0 -d 0.0.0.0/0 -j MASQUERADE

Chaque proxy a sa propre configuration, et nous ne pouvons pas tous les présenter ici…

II-F - Quelques notions sur iptables

Il faut faudra certainement quelques notions d'iptables pour mieux comprendre ces règles…

#! /bin/sh

IPTABLES="iptables"

IF_LOCAL="eth1"
IF_NET="eth0"

IP_NET=XXX.XXX.XXX.XXX
ZONE_INTERNE=192.168.0.0/255.255.255.0
IP_LOCAL=192.168.0.1
DNS_FAI=YYY.YYY.YYY.YYY
GW_FAI=ZZZ.ZZZ.ZZZ.ZZZ

#### Initialisation

# modes pour le ftp
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp

# purger iptables
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X

# Politique par defaut : les paquets sont refuses
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

# On accepte les paquets reconnus par le moteur d'etat
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

#### Autoriser les connexions sortantes sur un port particulier

# exemple: on autorise les connexions ssh sortantes
$IPTABLES -A OUTPUT -m state --state ! INVALID -p tcp --sport 1024: --dport 22 -j ACCEPT

#### Autoriser les connexions entrantes vers un port particulier, et une interface particulière

# exemple: on ouvre le port tcp/22 depuis l'interieur, donc sur l'interface eth1
$IPTABLES -A INPUT -m state --state NEW -p tcp -s ${ZONE_INTERNE} --sport 1024: --dport 22 -i ${IF_LOCAL} -j ACCEPT

#### Router les paquets arrivant sur un port vers un autre port de la meme machine

# exemple: on route le port web (tcp/80) sur le port de squid
$IPTABLES -t nat -A PREROUTING  -s ${ZONE_INTERNE} -p tcp -m tcp --dport 80 -j REDIRECT --to-port 3128
$IPTABLES -t nat -A PREROUTING  -s ${ZONE_INTERNE} -p tcp -m tcp --dport 80 -j DNAT --to-destination ${IP_LOCAL}:3128

##### Router les paquets arrivant sur un port vers le port d'une autre machine

# exemple: on autorise le routage des connexions ssh depuis l'interieur vers l'exterieur
$IPTABLES -A FORWARD -m state --state NEW -p tcp -s ${ZONE_INTERNE} --sport 1024: --dport 22 -i ${IF_LOCAL} -o ${IF_NET} -j ACCEPT

#### Diriger les requetes en sortie
# pour qu'elles fassent ZONE_INTERNE -> eth1:Passerelle -> eth0:Passerelle -> ZONE_EXTERNE

$IPTABLES -t nat -A POSTROUTING -s ${ZONE_INTERNE} -o ${IF_NET} -j SNAT --to ${IP_NET}

#### Activer le routage
echo 1 > /proc/sys/net/ipv4/ip_forward

II-G - Compléments

Il faut se protéger d'une attaque Denial of Service, dont le but est de saturer la passerelle par de nombreuses connexions non abouties, et ainsi de la faire tomber sous la charge. Pour cela, une ligne suffit…

echo 1 > /pros/sys/net/ipv4/tcp_syncookies

Je signale l'existence du module AdZapper pour Squid, afin de supprimer tout ce qui pourrait ressembler à un bandeau publicitaire…

Il manque encore quelques détails à rajouter sur la QoS, mais vous trouverez plus complet dans un article à venir sur iptables. Si vous avez d'autres suggestions… n'hésitez pas ;)

III - Divers

III-A - Références

- Documentation de « référence » (en anglais)

- Exposé complet sur Squid

- Squid et SquiGuard avec Webmin

- Avantages et inconvénients de DansGuardian

- Vieil article sur les passerelles

III-B - Conclusion

Ceci n'est pas assez complet pour espérer appréhender correctement la sécurité sous Linux… il vous faudra maintenant approfondir les notions survolées ici.