Firewall dynamique avec authentification par authpf.

Introduction:

Pour commencer, clarifions ce titre.
OpenBSD utilise le filtre de paquets (Firewall) PF de Daniel Hartmeier (man pf(4), pf.conf(5), pf.os(5), pfctl(8), authpf(8)).
Ce firewall est très robuste, et facile à configurer. De plus, couplé à CARP (man carp(4)), il peut même devenir redondant.
Outre la translation d'adresses (NAT), le suivi des états (statefull inspection), il intègre un module nommé authpf (man authpf(8)) qui permet de charger des règles de façon dynamique.

Aperçu:

Nous voulons autoriser l'accès à Internet à un groupe d'employés. Pour cela, on pourrait opter pour proxy transparent genre squid, mais il faut reconnaître que cela représente pas mal de travail, pour pas grand chose. De plus, on ajoute un port qui n'a pas bénéficié d'un audit aussi approfondi que le système de base.
Ou bien, on peut utiliser authpf. Ainsi, seuls les utilisateurs auxquels on aura créé un compte et qui auront ouvert une session ssh pourront accéder à l'Internet. De plus, on pourra suivre leur consommation (en temps) ce qui peut être utile à certains.

Pré requis:

Une machine qui officie en tant que passerelle sous OpenBSD 3.4 ou supérieure (ce qui signifie que vous savez configurer un firewall PF basique).
Au moins 2 doigts.
Un cerveau en état de marche.
Votre stimulant préféré à portée de main (clope, alcool, THC, etc. bien que peu recommandé pour maintenir le point précédent)

Configuration:

Commençons par rédiger un petit /etc/pf.conf en bonne et due forme qui ne laisse pas passer le trafic Internet.

# /etc/pf.conf
#
# Définissons quelques macros
# $Ext correspondant à l'interface extérieure
# $Int correspondant à l’interface intérieure
# $Lo qui n’est autre que loopback himself
# $IntNet qui est notre plage d’IP locale
# $NoRoute est la liste des plage d’adresses privées qu’on    va filtrer

   Ext = "tun0"
   Int = "vr0"
   Loop = "lo0"
   NameServer = "{ 193.252.19.3, 193.252.19.4 }"
   IntNet = "10.0.0.0/8"
   NoRoute = "{ 127.0.0.1/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, \
   255.255.255.255/32 }"

# Définissons maintenant quelques options
# Pour commencer, la politique de refus par défaut (mode prudence=on)

	set block-policy drop

# Durée de vie des états et des fragments (on joue à Dieu    là)

   set timeout interval 10
   set timeout frag 30

# L’interface qu’on va surveiller

   set loginterface tun0

# l’espace qu’on va réserver aux états et aux fragments

   set limit { states 20000, frags 20000 }

# Comportement du firewall (soyons conservateurs, en cas de lag)

   set optimization conservative

# Normalisation des paquets

   scrub in all
   scrub out all

# Translation d’adresses (ne pas oublier net.inet(6).ip.forwarding)

   nat on $Ext from ! $Ext to any -> $Ext

# Les règles de filtrage
# On commence par tout bloquer (on est prudents, on prends pas de risques)

   block in log on $Ext all
   block out log on $Ext all

# On se relaxe un peu avec le trafic local

   pass in on $Int all
   pass out on $Int all
   pass in on $Loop all
   pass out on $Loop all

# On reste un peu paranoïaque

   antispoof for $Loop

# Et on s’assure que personne essaie de nous entuber

   block in quick log on $Ext from $NoRoute to any
   block out quick log on $Ext from any to $NoRoute

# On laisse passer la résolution de noms (DNS)

   pass out on $Ext from $IntNet to $NameServer port domain keep state

# Pour finir, on définit une ancre qui va communiquer avec authpf pour
# charger d’autres règles si nécessaire

   anchor authpf

# end of /etc/pf.conf

Maintenant, créons une classe login.conf pour nos utilisateurs privilégiés.

# /etc/login.conf
   (...)
   lucky:\
   	:shell=/usr/sbin/authpf:\
   	:tc=default:
# end /etc/login.conf

Note : Ajoutez ceci à la fin du fichier, laisser le reste tel quel.

Ensuite on va créer des utilisateurs avec la commande adduser (man adduser(8)).
Au moment où il vous demande "login-class :", vous entrez "lucky", ainsi il aura authpf comme shell.

Maintenant, nous pouvons nous attaquer à la configuration d’authpf lui-même.

Pour fonctionner il faut impérativement que les fichiers /etc/authpf/authpf.conf et /etc/authpf/authpf.rules existent, même vides.
Si on s’en tient à notre configuration, on ajoutera les règles de filtrage dans /etc/authpf/authpf.rules, toutefois, si quelqu’un avait des besoins particuliers, on pourrait lui créer des règles plus spécifiques et personnelles dans /etc/authpf/$USER/authpf.rules (où $USER est à remplacer par le login de l’utilisateur).

On crée donc un fichier /etc/authpf/authpf.conf (touch /etc/authpf/authpf.conf) et on édite le fichier /etc/authpf/authpf.rules comme suit :

# /etc/authpf/authpf.rules
Ext = "tun0"
pass out log quick on $Ext from $user_ip to any keep state
# end /etc/authpf/authpf.rules

La macro $user_ip n’a pas besoin d’être déclarée car authpf la détermine automatiquement par la session SSH.
Pour verrouiller le tout un peu mieux, configurons sshd (man sshd(8)).
Dans le fichier de configuration du démon ssh (/etc/ssh/sshd_config) activez les options suivantes :

Protocol 2
ClientAliveInterval 15
ClientAliveCountMax 3
Ceci permet de couper la connexion au bout d’une minute si la connections sh est inactive ou spoofée.

Voila pour la partie technique. On peut rendre la chose plus « friendly-user » en ajoutant des messages à l’attention des utilisateurs, mais je vous laisse consulter ça dans la page man d’authpf.

Feedback:

Propositions de job, commentaires, déclarations d'amour, insultes, menaces, virus, dons etc.
D'autres infos sur beuchede.net
Vous me trouverez é sur #OpenBSD.fr@freenode