Limiter un utilisateur avec pf

OpenBSD Packet Filter permet de filtrer les paquets suivant l’UID de provenance (et peut être même de destination mais ça nous intéresse moins.

Vous avez un amis qui se connecte en ssh chez vous pour poser un irssi dans un GNU screen. C’est super sympa de votre part, seulement si on a pas une confiance totale en cet utilisateur il pourrait (lui ou un virus) se servir de son accès pour utiliser votre IP et balancer du spam, lancer une attaque de banque ou je ne sais quoi encore. Résultat : vous êtes responsable.

L’idée est simple, nous allons filtrer le trafic sortant de cet utilisateur (de login fictif machin) en lui autorisant uniquement le port IRC 6667 :

pass out on $ext_if proto tcp to port 6667 user machin tag TAG_MACHIN
block out quick on $ext_if proto tcp all user machin ! tagged TAG_MACHIN

La première règle autorise le port 6667 sortant pour machin et tagge le paquet avec TAG_MACHIN. La deuxième bloque tout ce qui vient de machin et qui n’est pas taggé avec TAG_MACHIN. Ce qui fait exactement ce que l’on veut.

Le mot clef quick permet a la règle d’être prise en compte immédiatement peu importe les règles suivantes (ce qui protège d’une éventuelle règle qui ferait tout passer ensuite).

Pour continuer dans l’exemple, il peut être utile d’autoriser les query DNS pour cet utilisateur (si vous n’avez pas de serveur DNS en interne), ça se passe en 53/udp :

pass out on $ext_if proto tcp to port 6667 user machin tag TAG_MACHIN
pass out on $ext_if proto udp to port domain user machin tag TAG_MACHIN
block out quick on $ext_if proto tcp all user machin ! tagged TAG_MACHIN

On peut même faire des listes sur les port et/ou utilisateurs :

users = { machin, truc }
pass out on $ext_if proto tcp to port { 6667, http } user $users tag TAG_USERS
pass out on $ext_if proto udp to port domain user $users tag TAG_USERS
block out quick on $ext_if proto tcp all user $users ! tagged TAG_USERS