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.
1. Prise en main 2. Changement de votre ruleset 3. Script pour crontab(1)
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
--- 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 ---
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)