[OpenBSD]

[Précédent : Haute disponibilité des pare-feux avec CARP et pfsync] [Index]

PF : Exemple : Pare-feu pour réseau domestique ou petite société


Table des Matières


Le Scenario

Dans cet exemple, PF fonctionne sur une machine OpenBSD jouant le rôle de pare-feu et de passerelle NAT pour un réseau SoHo. L'objectif global est de fournir un accès Internet au réseau local, de fournir un accès limité au pare-feu depuis Internet et d'exposer un serveur web interne à l'Internet. Ce document a pour but de vous montrer comment on construit un jeu de règles correspondant à l'objectif précité.

Le Réseau

Le réseau est conçu de la manière suivante :
    
  [ COMP1 ]    [ COMP3 ]
      |            |                               
   ---+------+-----+------- xl0 [ OpenBSD ] fxp0 -------- ( Internet )
             |
         [ COMP2 ]

Il y a un certain nombre de machines sur le réseau interne. Le diagramme en montre trois mais le vrai nombre n'est pas une donnée utile. Ces machines sont des stations de travail normales servant à surfer sur le web, écrire des messages électroniques, participer à des forums de discussion en ligne, etc à l'exception de COMP3 qui sert aussi de serveur Web. Le réseau interne utilise le bloc de réseau 192.168.0.0 / 255.255.255.0.

Le pare-feu OpenBSD est une machine dotée d'un Celeron 300 et de deux cartes réseau : une 3Com 3c905B (xl0) et une Intel EtherExpress Pro/100 (fxp0). Le pare-feu a une connexion câble vers Internet et utilise la NAT pour partager cette connexion avec le réseau interne. L'adresse IP de l'interface externe est attribuée dynamiquement par le Fournisseur d'Accès Internet.

Les Objectifs

Les objectifs sont les suivants :

Préparation

Ce document suppose que l'hôte OpenBSD a été correctement configuré pour fonctionner comme routeur : configuration réseau, connexion Internet et positionnement des variables sysctl(3) net.inet.ip.forwarding et/ou net.inet6.ip6.forwarding à "1". Vouc devez également activer PF en utilisant pfctl(8) ou en définissant la variable appropriée dans /etc/rc.conf.local. PF est activé par défaut sur OpenBSD 4.6 et les nouvelles versions.

Le Jeu de Règles

Les sections ci-après détaillent la manière dont le jeu de règles répondra aux objectifs précités.

Macros

Les macros suivantes sont définies pour rendre la maintenance et la lecture du jeu de règles plus faciles :
int_if="xl0"

tcp_services="{ 22, 113 }"
icmp_types="echoreq"

comp3 = "192.168.0.3"

La première ligne définit les interfaces réseau sur lesquelles le filtrage sera effectué. En les définissant ici, si nous devons déplacer ce système vers une autre machine avec un matériel différent, nous pourrons alors ne changer que ces deux lignes et le reste des règles restera valable. (Pour cet exemple, l'interface externe sera assurée en utilisant l'interface de groupe egress. C'est automatiquement activé sur toutes les interfaces ayant une route par défaut, dans ce cas, fxp0). Les deuxièmes et troisièmes lignes listent les numéros de port TCP des services ouverts depuis Internet (SSH et ident/auth) et les types de paquets ICMP qui sont autorisés à parvenir jusqu'aù pare-feu. Enfin, la dernière ligne définit l'adresse IP de COMP3.

Remarque : Si la connexion Internet nécessite l'utilisation de PPPoE, le filtrage et la NAT s'effectueront sur l'interface pppoe0 au lieu de l'interface de sortie (fxp0).

Options

Les deux options suivantes spécifient la réponse par défaut fournie par les règles de filtrage block et activent la collecte de statistiques sur l'interface externe :
set block-policy return
set loginterface egress

Chaque système Unix possède une interface de "loopback". C'est une interface réseau virtuelle utilisée par les applications pour converser avec les autres au sein du même système. Sur OpenBSD, l'interface de bouclage ("loopback") est lo(4). Le filtrage est communément désactivé sur ces interfaces. L'utilisation de set skip permet d'accomplir cela.

set skip on lo
Veuillez prendre note que nous n'effectuons pas de filtrage sur les interfaces lo, de cette manière nous pourrions rajouter des interfaces de loopback supplémentaire sans avoir à nous soucier de mettre à jour cette partie de la configuration.

Règles Pare-feu

On commencera avec des règles pour supporter l'utilisation de ftp-proxy(8) ainsi les clients FTP sur le réseau local pourront se connecter aux serveurs FTP sur Inernet. Cela fonctionne en insérant dynamiquement des règles quand une connexion ftp est effectuée. C'est réalisé en utilisant une ancre:
anchor "ftp-proxy/*"

Maintenant nous allons ajouter la règle permettant le détournement des connexions FTP pour qu'elles soient vues par ftp-proxy(8):

pass in quick on $int_if inet proto tcp to any port ftp \
    divert-to 127.0.0.1 port 8021

Cette règle intercepte les connexions FTP sur le port 21 et les détourne vers une instance ftp-proxy(8) tournant sur le port 8021 et, à travers l'utilisation du mot-clé quick, les paquets valides ne seront pas testés par le reste du jeu de règles. Si des utilisateurs se connectent sur les serveurs FTP sur des ports différents, une liste peut être utilisée pour spécifier le port de destination, par exemple : to any port { 21, 2121 }.

Il faut remarquer qu'aussi bien les ancres que la règle de redirection ftp-proxy(8) ont besoin d'être placées avant toutes règles match pour le NAT ou le ftp-proxy(8) ne fonctionnera pas bien.

Maintenant nous allons voir les règles match. Par elle-même, une règle match ne détermine pas si un paquet a la permission ou non de passer. À la place, les paquets qui sont conformes à cette règle auront les paramètres mémorisés; ils seront utilisés dans toutes les règles pass qui valident ces paquets.

C'est puissant : des paramètres comme NAT ou queueing peuvent être appliqués pour certaines classes de paquets, et les permissions d'accès définies séparement.

Pour avoir du NAT pour la totalité du réseau interne la règle match suivante est utilisée :

match out on egress inet from !(egress:network) to any nat-to (egress:0)

Dans ce cas, le "!(egress:network)" peut être facilement remplacé par un "$int_if:network", mais si vous ajoutez plusieurs interfaces internes, vous devrez ajouter des règles NAT en plus, par rapport à la structure, NAT sera utilisé sur toutes les interfaces protégées.

Comme l'adresse IP de l'interface externe est assignée dynamiquement, les parenthèses sont placées entre l'interface de traduction pour que PF soit notifié d'un chagement d'adresse. Le suffixe :0 est utilisé pour cela, si l'interface externe possède plusieurs adresses, seule la première est utilisée pour la traduction.

Pour finir, la famille de protocole inet (IPv4) est spécifiée. Cela supprime la traduction de tous les paquets inet6 (IPv6) qui sont reçus.

Maintenant les règles pour contrôler les permissions d'accès. On commence avec une interdiction par défaut :

block in log

À ce point, tout le trafic entrant sera bloqué, même celui en provenance du réseau interne. Ces paquets seront aussi tracés. Des règles suivantes vont ouvrir un certain nombre de flux sur le pare-feu afin de répondre aux objectifs précités et d'ouvrir toutes les interfaces virtuelles nécessaires.

Gardez à l'esprit que pf peut bloquer le trafic entrant ou sortant d'une interface. Cela peut vous simplifier la tâche de ne filtrer que dans une direction plutôt que d'essayer de rester consistant en filtrant le trafic sortant et entrant. Dans notre cas, nous choisirons de filtrer le trafic entrant uniquement, mais lorsque celui-ci sera permit sur une interface nous ne l'empêcherons pas d'en sortir. Pour se faire, nous utiliserons :

pass out quick
En utilisant quick, les paquets sortants ne seront pas vérifiés sur les règles suivantes, cela améliore les performances.

Il est utile d'utiliser la protection contre le spoofing d'adresses :

antispoof quick for { lo $int_if }

Maintenant, il faut ouvrir les ports utilisés par les services réseau disponibles depuis Internet. Tout d'abord, le trafic destiné au pare-feu lui-même :

pass in on egress inet proto tcp from any to (egress) \
    port $tcp_services

La spécification des ports réseau par le biais de la macro $tcp_services rend l'ouverture de nouveaux services pour des connexions provenant d'Internet plus facile dans la mesure où il suffira de modifier la macro et recharger le jeu de règles. Des services UDP peuvent aussi être mis à disposition en créant la macro $udp_services et en ajoutant une règle de filtrage adéquate similaire à la règle de filtrage ci-dessus en spécifiant proto udp.

La règle suivante récupère toutes les tentatives de quelqu'un sur Internet voulant se connecter sur le port 80 du pare-feu. Les tentatives légitimes pour accéder à ce port seront des utilisateurs essayant d'accéder au serveur web du réseau. Ces tentatives de connexion seront redirigées vers COMP3 :

pass in on egress inet proto tcp to (egress) port 80 rdr-to $comp3

Le trafic ICMP doit être permis :

pass in inet proto icmp all icmp-type $icmp_types

Comme pour la macro $tcp_services, la macro $icmp_types peut facilement être modifiée pour changer les types des paquets ICMP qui doivent être autorisés à atteindre le pare-feu. Notez que cette règle s'applique à toutes les interfaces réseau.

Maintenant, le trafic en provenance du réseau interne doit être autorisé. Nous supposerons que les utilisateurs du réseau interne savent ce qu'ils font et ne provoqueront pas de problème sur Internet. Ce n'est pas nécessairement une bonne supposition pour de nombreux environnements.

pass in on $int_if

Le trafic TCP, UDP et ICMP à destination d'Internet est autorisé à sortir du pare-feu grâce à la règle précédente "pass out". L'information sur l'état des connexions est sauvegardée pour permettre aux paquets de retour de passer à leur tour la barrière que constitue le pare-feu.

Le Jeu de Règles Complet

# macros

int_if="xl0"

tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"

comp3 = "192.168.0.3"

# options

set block-policy return
set loginterface egress

set skip on lo

# règles Proxy FTP

anchor "ftp-proxy/*"

pass in quick on $int_if inet proto tcp to any port ftp \
    divert-to 127.0.0.1 port 8021

# règles match

match out on egress inet from !(egress:network) to any nat-to (egress:0)

# règles de filtrage

block in log
pass out quick

antispoof quick for { lo $int_if }

pass in on egress inet proto tcp from any to (egress) \
    port $tcp_services

pass in on egress inet proto tcp to (egress) port 80 rdr-to $comp3

pass in inet proto icmp all icmp-type $icmp_types

pass in on $int_if

[Précédent : Haute disponibilité des pare-feux avec CARP et pfsync] [Index]


[back] www@openbsd.org
$OpenBSD: example1.html,v 1.44 2012/11/02 07:24:05 ajacoutot Exp $