D'une manière générale, les règles de PF sont définies dans un seul fichier de configuration, par défaut le fichier /etc/pf.conf. Ce fichier est composé de plusieurs sections :
Les définitions en utilisant les macros, les tables et les listes
les règles d'optimisation et de contrôle de bande passante
les règles de NAT
les règles de filtrage
Exemple 7. Exemples de listes
block out on fxp0 from { 192.168.0.1, 10.5.32.6 } to any
trusted = "{ 192.168.1.2 192.168.5.36 }"
pass in inet proto tcp from { 10.10.0.0/24 $trusted } to port 22
Lors de l'analyse par PF du fichier de configuration, les listes sont décomposées en plusieurs règles, chacune avec une valeur de la liste.
Les listes sont donc à utiliser dans le cas d'un nombre de valeur restreint.
Exemple 8. Exemples de macros
host1 = "192.168.1.1"
host2 = "192.168.1.2"
all_hosts = "{" $host1 $host2 "}"
ext_if = "fxp0"
block in on $ext_if from any to any
Dans le premier exemple, les macros sont définies récursivement.
Une table permet le regroupement d'adresses au sein d'une même entité. Les spécificités des tables par rapport aux listes standard sont les suivantes :
Utilisation directe et multiple dans les règles, comparable à une macro
Les recherches d'une adresse sont beaucoup plus rapides (utilise moins de mémoire et de temps CPU qu'une simple liste)
Existence qui va au-delà du fichier de configuration où elles sont définies puisqu'elles résident ensuite en mémoire ce qui permet de leur appliquer des modifications au niveau de leur contenu. Ces modifications sont immédiatement prises en compte par Packet Filter sans avoir à recharger les règles ou à procéder à une quelconque manipulation.
Le contenu d'une table est sensiblement identique à celui que l'on peut fournir comme adresse source ou de destination dans les règles en temps normal. Il peut prendre les différentes formes suivantes :
Une adresse IP (version 4 comme 6), exemples : 192.168.0.1, 66.80.97.134
Une adresse en notation CIDR (version 4 comme 6) : 192.168.0.0/24
Un nom de machine qui sera automatiquement remplacé par les adresses IP correspondantes (versions 4 et 6) à condition de pouvoir effectuer cette résolution (ne pas oublier de construire des règles visant à autoriser le trafic DNS)
Le nom d'une interface (
sis1,lo0, etc), qui sera substituée par la liste des adresses qui lui sont attribuéesLe nom d'une interface suivie de
:network,:broadcast,:peerou:0correspondant respectivement à l'adresse réseau, l'adresse de broadcast, l'adresse d'un pair sur un lien point à point ou l'adresse principale affectée à une carte réseau (ne tient pas compte des alias)
Exemple 9. Exemples de tables
table <dmz_hosts> const { \
172.17.0.1/32, \
172.17.0.239/32, \
172.17.0.240/32 \
}
table <banned> persist
Dans le deuxième exemple, la tables banned est déclarée vide, mais persistante. On pourra donc ajouter à la volée des adresses dans cette table, et dans notre cas précis, interdire à des postes certains traffics.
La manipulation des tables est possible en utiisant la commande pfctl (voir chapitre précédent).
Dans un fichier de configuration de PF, il peut-être intéressant de spécifier un certrain nombre de valeurs, modifiant les réactions du firewall. Sont présentées les plus communes :
block-policy: ce paramètre spécifie si les tentatives de connexion refusées sur des ports provoquent ou non un retour d'erreur (de typeconnexion-refused). Sa valeur peut-êtredrop(valeur par défaut) oureturn.set block-policy returnskip: cette directive permet d'ignorer les règles sur une interface (typiquement la boucle locale).set skip on lo0scrub: il est possible pour PF de normaliser une partie du traffic réseau en réassemblant des paquets fragmentés ou en en éliminant certains. L'utilisation commune de cette valeur est :scrub in allantispoof : cette directive permet de détecter et bloquer les tentatives d'usurpation d'adresse IP, sur les réseaux directement connectés à PF. Il permet par exemple de bloquer des paquets venant du WAN portant des adresses locales.
antispoof for $ext_if antispoof for $int_if
Mécanisme indispensable à l'interconnexion de réseaux de différentes classes d'adresses, la translation d'adresse (NAT : Network Address Translation) permet de modifier les adresses sources du traffic, pour masquer par exemple la structure du LAN. Dans l'exemple proposé en TP (cf. Figure 1, « Schéma du réseau » schéma réseau), lors d'une connexion d'une machine du LAN (192.168.36/0/24) vers un serveur du WAN, la passerelle/pare-feu transmettrait le flux vers le WAN, en translatant l'adresse source vers sa propre adresse (172.17.0.1). Le traffic retour est alors automatiquement translaté de manière symétrique, et les paquets remis à la machine du LAN.
Sous PF, il est possible de déifnir sur quelles interfaces, pour quels flux, la translation d'adresse doit se faire. La syntaxe générale des règles NAT est la suivante :
nat [pass] [log] on interface [af] from src_addr [port src_port] to \
dst_addr [port dst_port] -> ext_addr [pool_type] [static-port]
pass: désactive le filtrage pour les paquets translatésinterface: l'interface sur laquelle les paquets sont translatésext_addr: l'adresse (ou les adresses) sur laquelle les paquets sont translatés
Exemple 10. Exemple de règle NAT
ext_if = "re0"
int_if = "re1"
localnet = $int_if:network
nat on $ext_if from $localnet to any -> ($ext_if)
block all
pass from { lo0, $localnet } to any keep state
La redirection de ports permet de rediriger les flux arrivant sur une interface, un port vers une machine physique, sur un port précis. Dans l'exemple proposé en TP (cf. Figure 1, « Schéma du réseau » schéma réseau), le serveur WEB de la DMZ doit être joignable du WAN. IL faut donc rediriger les connexions sur le port HTTP vers le serveur WEB.
Exemple 11. Exemple de règle de redirection
server = 192.168.1.40
rdr on $ext_if proto tcp from any to $ext_if port 80 -> $server \
port 80
Les règles de filtrages sont examinées dans l'ordre d'apparition, la dernière règle correspondant au traffic examinée est appliquée. Si aucune règle ne correspond au paquet, la politique par défaut est appliquée. Dans le cas où le mot clef quick est passé dans la règle, la règle est immédiatement appliqué, sans parcourir le reste des règles.
De manière générale, la politique par défaut d'un firewall est de bloqué tout traffic, puis d'autoriser unqiuement ce que l'on souhaite.
La syntaxe générale des règles est la suivante :
action [direction] [log] [quick] [on interface] [af] [proto protocol] \
[from src_addr [port src_port]] [to dst_addr [port dst_port]] \
[flags tcp_flags] [state]
action : prend les mots clefs pass ou block
quick : si le mot clef est présent et que le paquet correspond à la règle, l'action est immédiatement appliquée
on interface : l'interface où a lieu le filtrage
state : si la règle contient les mots clefs keep state, les paquets futurs correspondant à cet échange seront acceptés
Exemple 13. Exemples de règles
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
pass in on fxp0 proto tcp from any to fxp0 port www
block in on fxp0 proto tcp from any to any port ssh
pass out on fxp0 proto tcp from any to any keep state