PF et tables dynamiques

Intro

Rien de tel qu'un petit exemple pratique pour se familiariser avec les tables dans pf(4). Lors d'un chargement des règles firewall vous avez peut-être mis des macros du genre :

smtp_allowed="{ smtp.monfai.fr }"

C'est pratique, mais il y a au moins deux inconvénients à cette solution :

Lors du traitement des règles par pfctl(8), celui-ci va mettre un temps incertain pour résoudre le nom DN et il est fréquent d'en avoir une grosse dizaine.

Si vous invoquez pfctl(8) au démarrage, et que vous n'avez pas le net ou accès à votre DNS pour une raison ou pour une autre, les règles ne seront tout simplement pas chargées, ce qui est assez génant pour un firewall.

Une utilisation des tables pf(4) peut vous aider dans vos problèmes de maçonnerie :

En remplaçant les DN par des IP, votre pfctl sera rapide comme l'éclair (même dans des rulesets conséquents). Plus de problème au démarrage, même si votre firewall est actif avant votre connexion au net. Si en plus votre FAI a tendance à changer tous les 10 jours les IP de ses SMTP et consorts, il y a une solution pour que ces changements soit apportés à votre firewall.

Conditions d'Utilisation

  1. Posséder un Net/Open/FreeBSD-like
  2. Avoir chargé pf(4) dans votre système
  3. Connaître les bases pour manipuler pfctl(8) et avoir déjà un ruleset (non traité ici)

Plan

      1. Prise en main
      2. Changement de votre ruleset
      3. Script pour crontab(1)

1.Prise en Main

Lorsque l'on a un bloc d'IP à traiter, le mieux est d'utiliser le système de tables qu'offre pf(4) : il est prévu à cet effet et gère le tout d'une manière très rapide.

Définition d'une table dans pf.conf(5) :

table <string> tableopts { tableaddr-list }

avec    string = nom de la table
        tableopts = persist | const | file
        table-list = liste IP

Une petite explication des keywords :

        persist = la table est créée même si aucune des règles n'y fait réference
        const = le contenu de la table n'est pas altéré par l'utilisateur (constant)
        file = le contenu de la table est pris directement dans un fichier

Exemples pratiques :

        table <smtp.fai> const { 111.111.111.1, 111.111.111.2 }
ou
        table <smtp.fai> persist file "/etc/pf.smtp.table"
et
        cat /etc/pf.smtp.table
111.111.111.1
111.111.111.2

Nous pouvons gérer de manière dynamique le contenu des tables avec pfctl(8) :

        pfctl -t table -T command
avec :
        table = nom de la table
        command = kill | flush | add | delete | replace | show | test | zero | load

Se réferer au fichier man de pfctl qui est très explicite.

Exemple :

        pfctl -t smtp.fai -T replace -f /etc/pf.smtp.table

a pour effet de remplacer la liste d'IP contenue dans pf.smtp.table dans la table smtp.fai

2.Changement du ruleset

--- SNIP ---
table <smtp.fai> persist file "/etc/pf.smtp.table"
table <pop.fai> persist file "/etc/pf.pop.table"
--- SNIP ---

--- SNIP ---
block log all

pass out on $if_ext inet proto tcp to <smtp.fai> port 25 modulate state
pass out on $if_ext inet proto tcp to <pop.fai> port 110 modulate state
--- SNIP ---

3. Script de crontab

Afin de mettre à jour la liste des SMTP Server et POP Server de votre FAI, nous allons créer un petit script qui va remplir les fichiers correspondants dans lesquels votre ruleset va piocher les IP.

#!/bin/sh
# Script de MAJ des tables pf
# Date : 11/04/2006
# Comments : GCU powered gruik style fashion victim ALAIN

#Variables
smtpserver="smtp.monfai.fr"
popserver="pop.monfai.fr"
smtpfile="/etc/pf.smtp.table"
popfile="/etc/pf.pop.table"
smtptable="smtp.fai"
poptable="pop.fai"

#Verification de l'existence des fichiers
if [ ! -r $smtpfile ] || [ ! -r $popfile ]
then
        host $smtpserver | awk '{print $4}' | sort > $smtpfile
        host $popserver | awk '{print $4}' | sort > $popfile
        exit 0
fi

#Debut de la comparaison
host $smtpserver | awk '{print $4}' | sort | diff -q - $smtpfile > /dev/null

if [ ! $? -eq 0 ]
then
        logger "Changement Table PF SMTP"
        host $smtpserver | awk '{print $4}' | sort > $smtpfile
        pfctl -t $smtptable -T replace -f $smtpfile
fi

host $popserver | awk '{print $4}' | sort | diff -q - $popfile > /dev/null

if [ ! $? -eq 0 ]
then
        logger "Changement Table PF POP3"
        host $popserver | awk '{print $4}' | sort > $popfile
        pfctl -t $poptable -T replace -f $popfile
fi

exit 0

Donc ce script a l'avantage de vérifier que les tables different avant d'invoquer pfctl(8). Mais nous aurions très bien pu nous passer de ces tests : ça fonctionne aussi ! Vérifiez quand même que votre shell connaît bien le chemin des différentes commandes utilisées dans ce script.

L'interêt est de le faire executer par cron(8) assez fréquemment (voir crontab -e en root)

Changelog

  • 11/04/2006 Création du tip par hotbox
bsd/pf_tables.txt · Last modified: 2010/01/12 13:29 (external edit)