Mise en place d'une passerelle d'authentification à l'aide de authpf
Date de publication : 15/01/07
Par
julp (Autres articles)
Une étude du shell authpf : applications, mise en place, interaction avec
Packet Filter au moyen d'une ancre. Le tout agrémenté de quelques exemples
simples.
1. Présentation
2. Attribution du shell authpf
2.1. Attribution individuelle : changement de shell
2.2. Attribution groupée : utilisation des classes de session
3. Configuration de Packet Filter
3.1. Pré-requis
3.2. Configuration
3.3. Règles propres à chaque utilisateur
3.4. Règles principales
4. Administration et gestion des utilisateurs
4.1. Gestion des utilisateurs
4.2. Lister les utilisateurs actuellement connectés
4.3. Affichage de messages de bienvenue et d'erreur
4.4. Journalisation des évènements
4.5. La sécurité autour de SSH
4.5.1. Paramétrage de SSH
4.5.2. Se prémunir contre les attaques par dictionnaire
5. Après la théorie : la pratique par l'exemple
5.1. Permettre aux utilisateurs de travailler depuis chez eux
5.2. Autoriser l'accès au réseau sans fil
6. Conclusion
6.1. Epilogue
6.2. Remerciements
1. Présentation
Une passerelle d'authentification par rapport à une passerelle normale
demande à ce que l'utilisateur s'identifie afin que le trafic généré par
ce dernier puisse la traverser.
Pour cela chaque utilisateur se voit attribuer un shell différent de ceux
que nous connaissons déjà : authpf, et lors d'une connexion SSH réussie
à la passerelle, ce shell chargera dynamiquement les règles correspondant
à cet usager.
Ces règles peuvent être globales ou bien spécifiques, c'est-à-dire propres
à chacun. Il est ensuite possible d'appliquer sans restriction tout type
de règles proposé par Packet Filter : passer au travers du filtre,
redirection, traduction d'adresse (NAT), etc.
Les connexions et déconnections sont enregistrées par authpf via syslog,
fournissant ainsi à l'administrateur l'adresse IP de la machine utilisée,
le login de l'utilisateur, l'heure de l'établissement de la session,
l'heure à laquelle la session s'est terminée et sa durée. Vous trouverez
ici
un exemple de parser écrit en Perl.
Quelques utilisations courantes :
-
Exiger une authentification de la part des utilisateurs avant de
leur permettre d'utiliser ou d'avoir accès aux ressources réseaux
(Intranet comme Internet) :
- Rendre possible le travail à domicile
- Accès à un réseau sans fil
-
Adapter le dispositif de filtrage à l'utilisateur connecté :
- Donner des accès supplémentaires à des administrateurs
- Etre plus permissif envers les utilisateurs connus
- Rediriger vers la machine attribuée à un utilisateur
2. Attribution du shell authpf
Tout d'abord il est nécessaire que authpf soit reconnu comme étant un
shell par le système, ce qui n'est pas le cas par défaut.
Pour cela exécutez la commande :
grep '^/usr/sbin/authpf$' /etc/shells || echo '/usr/sbin/authpf' >> /etc/shells
|
2.1. Attribution individuelle : changement de shell
Dans le cas d'utilisateurs déjà présents sur le système, il faut
modifier manuellement le shell de chacun d'eux. Voici une liste
(non exhaustive) des commandes permettant d'effectuer cette
opération :
Plusieurs méthodes sont possibles :
-
A l'aide de chsh. Exemple d'utilisation :
chsh -s /usr/sbin/authpf login_utilisateur
|
-
Un équivalent très proche, basé sur la commande pw :
pw usermod login_utilisateur -s /usr/sbin/authpf
|
-
Editez tous les comptes présents sur la machine à l'aide de
vipw pour modifier les shells des utilisateurs
concernés en /usr/sbin/authpf (le shell étant le
dernier champ).
A la création d'utilisateurs avec la commande adduser vous
pourrez spécifier authpf comme shell.
2.2. Attribution groupée : utilisation des classes de session
Méthode particulièrement adaptée si les utilisateurs devant utiliser
ce mécanisme d'authentification ne sont pas encore créés.
Nous allons créer une nouvelle classe pour les utilisateurs concernés
dans notre fichier /etc/login.conf telle que :
authpf:\
:shell=/usr/sbin/authpf:\
:tc=default:
|
 |
Il vous est possible d'ajouter de nombreuses limitations aux utilisateurs
associés à une classe. Pour vous en rendre compte consultez la page man de
/etc/login.conf.
|
Après avoir effectuer des changements dans ce fichier il est impératif
d'en regénérer la base afin de les prendre en considération. Utiliser la
commande cap_mkdb à cette fin :
Vous pourrez alors utiliser cette nouvelle classe lors de la création
de nouveaux utilisateurs avec adduser.
En revanche, si vos utilisateurs existent déjà, vous pouvez utiliser
la commande pw pour les changer de classe. Voici un exemple où
l'utilisateur julp se voit attribuer cette classe :
3. Configuration de Packet Filter
3.1. Pré-requis
Le répertoire accueillant les fichiers de configuration de authpf
n'existant pas par défaut, il nous faut donc le créer :
Authpf requiert également un autre répertoire, qui lui héberge des
fichiers temporaires dont les noms sont les adresses IP des machines
distantes où une connexion SSH est ouverte pour l'exécuter. Sa
particularité c'est que le groupe du même nom doit avoir tous les
droits sur celui-ci :
Dernière spécificité, et non des moindres, ce shell utilise le
système de fichier nommé fdescfs, qui permet d'accéder à
un fichier (déjà ouvert) à partir de son descripteur. Afin de le
prendre en charge, nous ajoutons dans /etc/fstab, la ligne
suivante :
fdescfs /dev/fd fdescfs rw 0 0
|
3.2. Configuration
Authpf refusera systématiquement toute connexion en l'absence du
fichier /etc/authpf/authpf.conf, c'est pourquoi il faut
absolument le créer même vide. Il permet de spécifier deux options
de configuration :
- anchor : définit le nom de l'ancre. Sa valeur par défaut est authpf.
- table : permet de spécifier le nom de la table contenant l'ensemble des adresses IP d'où les utilisateurs sont actuellement connectés. Sa valeur par défaut est authpf_users.
Voilà comment il sera défini pour la suite de cet article :
| /etc/authpf/authpf.conf : |
anchor=authpf
table=utilisateurs_authpf
|
3.3. Règles propres à chaque utilisateur
Authpf présente également l'intérêt de pouvoir charger des règles de
filtrage spécifiques à chaque utilisateur. Pour cela, il suffit de les
écrire dans un fichier de la forme /etc/authpf/users/$USER/authpf.rules
où $USER correspond au login de l'utilisateur en question. Pas
d'inquiétude, vous n'aurez pas réécrire les règles pour chaque
utilisateur puisque authpf propose d'utiliser des règles par défaut
définies dans /etc/authpf/authpf.rules si ce dernier n'existait
pas.
Il paraît dès lors évident qu'au moins un de ces deux fichiers doit
toujours être disponible quelque soit l'utilisateur qui se connectera.
En effet, le shell mettra immédiatement fin à la connexion de
l'utilisateur si aucune règle (par défaut ou non) ne peut lui être
appliquée. Par conséquent, il est préférable de définir dans /etc/authpf/authpf.rules
les règles s'appliquant aux utilisateurs lambda ou de le laisser vide
si celles-ci sont directement définies parmi vos règles principales.
Nous y venons justement dans la prochaine partie.
Deux macros sont automatiquement disponibles pour la création de vos
règles dans les fichiers cités ci-dessus, à savoir :
- $user_ip : l'adresse IP de la machine depuis laquelle l'utilisateur a établi la connexion vers la passerelle
- $user_id : l'identifiant (login) de l'utilisateur en question
3.4. Règles principales
Voyons comment sont gérées les règles dans le fichier principal de
configuration de Packet Filter. Ci-dessous une ébauche générique
complète qui vous servira de base. Vous trouverez les explications
correspondantes après celui-ci :
interface = "de0"
table <utilisateurs_authpf> persist
nat-anchor "authpf/*"
rdr-anchor "authpf/*"
binat-anchor "authpf/*"
block drop all
pass in quick on $interface inet proto tcp from any \
to $interface port ssh flags S/SA keep state
anchor "authpf/*"
|
La déclaration de la table dont vous avez donné le nom par la
directive table dans /etc/authpf/authpf.conf n'est
nécessaire que si vous envisagez de l'utiliser. Celle-ci contiendra
la liste des adresses IP des machines depuis lesquelles une personne
s'est authentifiée à la passerelle. La présence du mot-clé
persist est obligatoire pour maintenir son existence en
mémoire même si celle-ci venait à être vide.
Il existe quatre types d'ancres, comme montré ci-dessus, dont chacune
dépend de la nature des règles qui seront dynamiquement chargées.
Cette dernière est indiquée par son préfixe. Toutes ne sont pas
requises, vous ne pouvez faire figurer que celles dont vous avez
besoin ainsi dans le cas où vous ne faites aucune traduction d'adresse
vous pouvez omettre les lignes commençant par nat-anchor et
binat-anchor.
Enfin, on notera la présence impérative d'une règle qui autorise le
trafic SSH en vue de permettre l'authentification de nos différents
utilisateurs.
4. Administration et gestion des utilisateurs
4.1. Gestion des utilisateurs
L'administrateur peut décider de bannir (bloquer) un utilisateur, pour
cela il lui suffit de créer le fichier /etc/authpf/banned/$USER,
où $USER désigne le login de cet utilisateur. Ce fichier peut
avoir pour contenu la raison de cette interdiction et ce message sera
affiché lors de la connexion de celui-ci par SSH. En guise d'exemple,
nous souhaitons interdire l'utilisateur julp :
echo "Interdit de réseau pour utilisation de réseaux pear to pear." > /etc/authpf/banned/julp
|
A l'inverse le fichier /etc/authpf/autpf.allow indique les
utilisateurs autorisés à avoir recours à authpf en y spécifiant leurs
logins. Toutefois, si ce dernier n'est pas présent sur votre système
ou bien s'il a pour contenu * alors tout le monde est autorisé
à s'y connecter.
Le fichier d'interdiction est toujours cherché avant celui d'autorisation.
En clair, l'interdiction prévaut sur l'autorisation. De plus, si authpf
n'est pas capable de déterminer l'un ou l'autre alors il met fin à la
connexion SSH.
Il est dès lors possible de déterminer deux approches :
- politique permissive : placer * dans /etc/authpf/authpf.allow et bloquer les utilisateurs au cas par cas
- politique restrictive : ne lister que les personnes autorisées dans /etc/authpf/authpf.allow
4.2. Lister les utilisateurs actuellement connectés
Le moyen le plus commode pour savoir qui est en train d'utiliser la
passerelle et depuis où reste ps. En effet, lorsque la
connexion est établie avec succès, authpf modifie le nom de son
processus pour y intégrer le login de l'utilisation ainsi que
l'adresse IP de la machine cliente. En voici une démonstration :
# ps ax | grep authpf
1123 p0 Ss+ 0:00,05 -authpf: stéphane@192.168.100.1 (authpf)
|
Il est possible de mettre fin à la connexion de stéphane établie
depuis la machine d'adresse 192.168.100.1 en envoyant un signal TERM
(15) au processus associé à celle-ci. Dans de tel cas, Authpf se
chargera de la suppression des connexions dont l'état a été mémorisé
(option keep state et similaires) et des règles spécifiques à cet
utilisateur s'il y a lieu, de nettoyer la table.
 |
Toutefois, pour des questions de praticité, j'ai mis au point un
petit programme qui vous permettra de lister et de mettre fin à
une session. Celui-ci ne possède aucune dépendance particulière.
Les sources sont à votre disposition ici.
|
4.3. Affichage de messages de bienvenue et d'erreur
Il existe plusieurs méthodes pour afficher un message particulier à
l'ensemble des utilisateurs recourant à authpf. Voici la liste des
fichiers de message reconnus par authpf :
Voyons un exemple :
echo -n > /etc/authpf/authpf.message
cat > /etc/authpf/authpf.problem
Il semblerait que le système rencontre quelques difficultés techniques.
Reportez ce problème en téléphonant au 0X-XX-XX-XX-XX ou en envoyant un
email à administrateur@domaine.fr afin que nous puissions le résoudre
au plus vite.
^D
cat > /etc/authpf/authpf.motd
Vous pouvez maintenant accéder au réseau. Cette connexion est établie à votre
nom et vous devenez à cet instant responsable du trafic généré à partir de
votre machine.
^D
|
Ici
/etc/authpf/authpf.motd est un fichier qui servira à
cultiver l'obscurantisme, c'est-à-dire à ne pas dévoiler une
quelconque information au sujet du système d'exploitation
(typiquement ses nom et version). Par contre, son recours requiert
l'appel à une classe de session et nous complèterons celle que
nous avons défini plus haut, dans la partie
Attribution groupée : utilisation des classes de session,
dans
/etc/login.conf tel que :
authpf:\
:shell=/usr/sbin/authpf:\
:welcome=/etc/authpf/authpf.motd:\
:tc=default:
|
Regénérons la base de données :
/etc/authpf/authpf.motd sera affiché lorsque tout va bien,
c'est pourquoi nous créons /etc/authpf/authpf.message vide.
4.4. Journalisation des évènements
La question de journalisation a été abordée précédemment lors de la
présentation de authpf et celle-ci est inactive par défaut. Nous
allons modifier /etc/syslog.conf pour la prendre en charge :
!authpf
*.* /var/log/authpf.log
|
Puis nous procédons ensuite à la création du fichier de log qui sera
dédié à authpf :
touch /var/log/authpf.log
chmod 0600 /var/log/authpf.log
|
Nous terminons par le redémarrage du démon syslog afin que les
modifications apportées soient prises en compte dès maintenant :
4.5. La sécurité autour de SSH
4.5.1. Paramétrage de SSH
Il peut s'avérer nécessaire de reconfigurer le service SSH au
niveau de la sécurité puisque SSH est la clé d'accès au réseau
pour vos utilisateurs. Voici la liste des options qui nous
intéressent :
-
Protocol 2 : seule la version 2 du protocole est
acceptée et gérée par sshd. Préférable pour des raisons
de sécurité.
-
AllowTcpForwarding no : il est recommandé de
refuser les redirections TCP car celles-ci peuvent
entraîner le blocage des paquets par PF.
-
ClientAliveInterval 15 : fréquence, en secondes,
de vérification de la validité de la connexion du client.
Option ne s'appliquant qu'à la version 2 du protocole -
valeur par défaut 0, inactive.
Combinée à la directive ClientAliveCountMax (présentée
ci-dessous), elle permet de terminer les connexions
inactivent ou qui font l'objet d'une tentative de vol par
usurpation (spoofing).
-
ClientAliveCountMax 3 : nombre maximum de
vérifications infructueuses acceptées par sshd avant de
mettre fin à la session.
4.5.2. Se prémunir contre les attaques par dictionnaire
Les systèmes équipés de la version 3.7 de Packet Filter ou
supérieure (ce qui correspond pour FreeBSD à une version
supérieure ou égale à 6.0) peuvent bloquer les tentatives
d'attaque par dictionnaire à l'aide des règles suivantes :
ext_if = "votre interface sur l'extérieur"
table <ssh-bruteforce> persist [file "/etc/ssh-bruteforce"]
block in quick from <ssh-bruteforce>
pass in quick on $ext_if inet proto tcp from any \
to $ext_if port ssh flags S/SA keep state (max-src-conn-rate 4/30, overload <ssh-bruteforce> flush global)
|
Ainsi, lorsque quelqu'un tentera 4 connexions en moins de 30
secondes (option max-src-conn-rate 4/30) vers ssh, son adresse
IP sera ajoutée à la table ssh-bruteforce (option overload) et
mettra fin à toutes ses connexions (option flush global).
5. Après la théorie : la pratique par l'exemple
Les exemples suivants sont volontairement simplifiés pour mettre en
lumière des applications courantes de authpf ainsi que pour montrer
l'intégration des règles relatives à authpf par rapport à celles qui
sont statiques.
Les pare-feu dont les configurations sont données en exemple sont marqués
sur les schémas ci-dessous sous les traits d'un mur en brique.
5.1. Permettre aux utilisateurs de travailler depuis chez eux
Le directeur d'une petite entreprise spécialisée dans la création
de site web souhaite, suite aux demandes répétées de ses salariés,
leur permettre de travailler depuis chez eux.
Cet accès se limitera au bastion faisant office de serveur Web et
de serveur de gestion de configuration (subversion), leur offrant
ainsi la possibilité de récupérer, mettre à jour les sources et
visualiser directement le résultat de ces changements (aucune
installation locale particulière n'est ainsi requise).
La représentation du réseau est la suivante :
Le fichier /etc/authpf/authpf.rules sera créé vide pour que
l'ensemble des règles figure dans un seul et unique fichier. Voici
comment il sera écrit :
ext_if = "de0"
int_if = "xl0"
tcpflags = "flags S/SFRA"
http_server = "192.168.100.101"
nat_ports = "port 50000:60000"
set skip on lo0
set block-policy drop
table <utilisateurs_authpf> persist
scrub in
nat on $ext_if from !($ext_if) \
to any -> ($ext_if) $nat_ports
rdr on $ext_if inet proto tcp from <utilisateurs_authpf> \
to ($ext_if) port http -> $http_server port http
block all
pass in quick on $ext_if inet proto tcp from any \
to ($ext_if) port ssh $tcpflags keep state
pass in quick on $ext_if inet proto tcp from <utilisateurs_authpf> \
to $http_server port http $tcpflags keep state
pass out quick on $int_if inet proto tcp from <utilisateurs_authpf> \
to $http_server port http $tcpflags keep state
pass in quick on $ext_if inet proto tcp from $int_if:network \
to any $tcpflags keep state
pass out quick on $ext_if inet proto tcp from $ext_if $nat_ports \
to any $tcpflags keep state
anchor "authpf/*" in on $ext_if
|
5.2. Autoriser l'accès au réseau sans fil
Un établissement scolaire offre un accès sans-fil pour permettre
aux élèves comme aux enseignants de consulter des sites Internet.
Ce trafic est contrôlé en ayant recours à des serveurs de mandatement
internes pour les protocoles HTTP et DNS et doit donc obligatoirement
passer par eux. De plus, ces utilisateurs devront montrer patte
blanche avant d'accéder aux ressources réseau mises à leur
disposition.
Les administrateurs systèmes et réseaux, qui seront également amenés
à recourir au sans-fil pour travailler, souhaitent disposer d'un
accès administratif (SSH) vers les machines qui assurent des services
mandataires.
Le réseau est représenté de manière simplifiée comme suit :
Les règles générales sont, par conséquent, définies telles que :
ext_if = "ath0"
int_if = "sis0"
tcpflags = "flags S/SFRA"
dns_server = "192.168.100.101"
http_proxy = "192.168.100.102"
set skip on lo0
set block-policy drop
table <utilisateurs_authpf> persist
scrub in
block all
pass in quick on $ext_if inet proto tcp from any \
to $ext_if port bootpc $tcpflags keep state
pass in quick on $ext_if inet proto tcp from $ext_if:network \
to $ext_if port ssh $tcpflags keep state
pass in quick on $ext_if inet proto tcp from <utilisateurs_authpf> \
to $http_proxy port { http https } $tcpflags keep state
pass in quick on $ext_if inet proto udp from <utilisateurs_authpf> \
to $dns_server port domain keep state
anchor "authpf/*" in on $ext_if
|
Enfin, nous attribuons des règles spécifiques à l'administrateur
dupont.j lui permettant d'avoir un accès SSH vers le serveur DNS et
le mandataire HTTP depuis son portable équipé de la technologie Wifi.
Pour cela nous créons /etc/authpf/users/dupont.j/authpf.rules
pour lui donner cet accès :
ext_if = "ath0"
tcpflags = "flags S/SFRA"
dns_server = "192.168.100.101"
http_proxy = "192.168.100.102"
pass in quick on $ext_if inet proto tcp from $user_ip \
to { $dns_server $http_proxy } port ssh $tcpflags keep state
|
 |
Veillez à recopier ou remplacer les macros que vous souhaitez
utiliser dans de tels fichiers de règles car celles-ci ne sont
pas héritées du fichier de règles principales.
|
6. Conclusion
6.1. Epilogue
Authpf est un programme fiable basé sur le mécanisme appelé ancre de
Packet Filter qui permet de charger dynamiquement des règles. Cette
fiabilité est en grande partie assurée par le protocole SSH dont il
ne faut pas, par conséquent, négliger la configuration. Sa capacité
à journaliser les évènements de démarrage et fin de session raviront
sans aucun doute les administrateurs.
Toutefois, sous forme d'interpréteur de commande, authpf restreint
l'utilisation du compte utilisateur à cet usage : il ne sera en effet
impossible d'utiliser SSH pour exécuter des commandes.
Récapitulatif des sources associées :
Liens Developpez :
Liens externes :
6.2. Remerciements
Mais également aux bénévoles de la section Linux
Olivier Regnier,
ovh et
gorgonite pour leurs suggestions constructives et leur soutien.


Copyright © 2007 julp. Aucune reproduction, même partielle, ne peut être faite
de ce site et de l'ensemble de son contenu : textes, documents, images, etc
sans l'autorisation expresse de l'auteur.
Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E
de dommages et intérêts.
Cette page est déposée à la
SACD.