Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[PF] in or out

10 réponses
Avatar
Jérémy JUST
Bonsoir,

Je suis en train de m'arracher les cheveux sur le comportement d'une
règle de filtrage de PF. Je relis en boucle le manuel et je ne
comprends toujours pas. J'aimerais avoir une explication formulée
autrement.


J'ai deux machines, et un pare-feu sous OpenBSD au milieu. Je
voudrais écrire des règles PF pour pouvoir me connecter d'une machine à
l'autre en SSH.

Avec cette règle-ci, j'arrive à me connecter:
pass out quick from $prv_hosts to $dmz_hosts flags S/SA modulate state

mais pas avec celle-ci:
pass in quick from $prv_hosts to $dmz_hosts flags S/SA modulate state


La seule différence entre les deux est l'orientation (in/out). Je ne
vois pas pourquoi ça change radicalement le filtrage des paquets.

Pourriez-vous m'éclairer?


--
Jérémy JUST <jeremy_just@netcourrier.com>

10 réponses

Avatar
Benoit Izac
Bonjour,

le 17/02/2007 à 20:45, Jérémy JUST a écrit dans le message
:

Je suis en train de m'arracher les cheveux sur le comportement d'une
règle de filtrage de PF. Je relis en boucle le manuel et je ne
comprends toujours pas. J'aimerais avoir une explication formulée
autrement.


J'ai deux machines, et un pare-feu sous OpenBSD au milieu. Je
voudrais écrire des règles PF pour pouvoir me connecter d'une machine
à l'autre en SSH.


Note que je ne suis pas sur d'avoir bien compris ; soyons plus clair :

$prv_hosts $dmz_hosts
+-------+ +----+ +-------+
|Machine|____________| FW |____________|Machine|
| A | if0 | | if1 | B |
+-------+ +----+ +-------+


Avec cette règle-ci, j'arrive à me connecter:
pass out quick from $prv_hosts to $dmz_hosts flags S/SA modulate state


Cette règle dit : laisse passer (sur les 2 interfaces) dans le sens
sortant (de FW vers A via if0 et de FW vers B via if1) les paquets qui
viennent de $prv_hosts vers $dmz_hosts (soit de A vers B) et qui ont un
flag Syn sans le flag Ack ; met lui un bon ISN et enregistre tout ça
dans ta table d'état pour permettre le trafic.

Cette règle ne s'applique donc qu'à if1, elle est équivalente à :
pass out quick on if1 from $prv_hosts to $dmz_hosts
flags S/SA modulate state

Tout dépend de ce que tu as avant ; si tu a un « block all » en début de
configuration, je doute que cette règle suffise pour que ça fonctionne
car le paquet ne rentrera pas dans FW via if0.

mais pas avec celle-ci:
pass in quick from $prv_hosts to $dmz_hosts flags S/SA modulate state


Cette règle dit : laisse passer (sur les 2 interfaces) dans le sens
entrant (de A vers FW via if0 et de B vers FW via if1) les paquets qui
viennent de ....

Elle ne s'applique qu'à if0.


Si tu veux que A puisse accéder à B sur le port ssh :
pass from if0:network to if1:network proto tcp port ssh keep state
dans l'autre sens (B se connecte à A en ssh)
pass from if1:network to if0:network proto tcp port ssh keep state

Remplace ifX par le nom de tes interfaces.

--
Benoit Izac

Avatar
Jérémy JUST
Le Sat, 17 Feb 2007 22:22:28 +0100,

Note que je ne suis pas sur d'avoir bien compris ; soyons plus clair :


Oui, j'aurais dû dessiner moi-même le schéma que tu as fait.


$prv_hosts $dmz_hosts
+-------+ +----+ +-------+
|Machine|____________| FW |____________|Machine|
| A | $prv_if| |$dmz_if | B |
+-------+ +----+ +-------+


Cette règle ne s'applique donc qu'à if1, elle est équivalente à :
pass out quick on if1 from $prv_hosts to $dmz_hosts
flags S/SA modulate state


Je m'aperçois que j'aurais pu encore simplifier les règles que je
donnais. Disons:

pass out quick on $dmz_if from $prv_hosts to $dmz_hosts keep state


Tout dépend de ce que tu as avant ; si tu a un « block all » en début
de configuration, je doute que cette règle suffise pour que ça
fonctionne car le paquet ne rentrera pas dans FW via if0.


Oui, j'ai effectivement un « block in all », qui, dans ce sens, fait
comme tu dis. Pour essayer de comprendre, j'ai réduit mon pf.conf à sa
plus simple expression, et je n'ai plus que ces deux règles.

Je pense comprendre ce que tu expliques. Quand on filtre sur « in »
ou « out », il faut que le paquet, en plus du match sur la règle « in »
ou « out », puisse traverser l'autre interface.


Si tu veux que A puisse accéder à B sur le port ssh :
pass from if0:network to if1:network proto tcp port ssh keep state


Effectivement, ça marche. Mais j'aimais bien le contrôle de
l'interface d'entrée; ça me paraît être une donnée parfaitement fiable
(puisque c'est le pare-feu qui la génère, et non le paquet qui
l'apporte). Est-ce qu'il y a un moyen de faire quand même ce contrôle.

J'ai écrit ça, qui marche, mais ça oblige à passer par des tags, ce
qui me semble bien compliqué pour un problème simple:


pass in on $prv_if from $prv_hosts to any tag FROM_PRV

block return all

pass from $prv_hosts to $dmz_hosts tagged FROM_PRV keep state





--
Jérémy JUST

Avatar
Stephane Catteau
Jérémy JUST devait dire quelque chose comme ceci :

Quand on filtre sur « in » ou « out », il faut que le paquet, en
plus du match sur la règle « in » ou « out », puisse traverser l'autre
interface.


Ton cas est simple, d'où ton oublie, mais imagine une machine comme la
mienne, avec quatre interfaces :


Wild1 _______ LAN
------| | -------
| |
------| | -------
Wild2 ~~~~~~~ DMZ


Ce qui est autorisé à rentrer par une interface n'est pas autorisé à
ressortir n'importe par n'importe quelle interface. Le cas de figure le
plus évident étant que ce qui rentre par Wild1 et Wild2 est autorisé à
sortir vers DMZ, mais pas vers LAN. Sans oublier que ce qui entre par
LAN ou DMZ peut très bien ne pas devoir aller plus loin que la machine
elle-même, ce qui arrive vu que j'ai placé le serveur NTP sur la
passerelle (je sais, c'est mal).
Donc, oui, tout ce qui est autorisé à rentrer doit aussi être autorisé
à sortir, même si cela semble implicite lorsque la machine n'a que deux
interfaces.

Le mieux, selon moi, c'est de ne filtrer que sur le 'in' et de laisser
les TAG faire le reste. Dans ton cas ça donne ceci :

pass in quick from $prv_hosts to $dmz_hosts tag PERMIT flags S/SA modulate state
[les autres règles]
block return in log quick from $prv_hosts to any
block return in quick all


pass out quick all tagged PERMIT
[Les règles "out" spécifiques à la passerelle (NTP, plus FTP, HTTP et CVS
pour les mises à jour)]
block return out quick all

Au final, excepté pour ce qui concerne la machine elle-même, tu n'as que
des règles "in". De cette façon, la maintenance est largement simplifiée,
puisque tu ne risques pas d'oublier de modifier la règle "out" associée,
et parce que la lecture de l'ensemble est beaucoup plus facile.

Avatar
Benoit Izac
Bonjour,

le 18/02/2007 à 13:06, Jérémy JUST a écrit dans le message
:

$prv_hosts $dmz_hosts
+-------+ +----+ +-------+
|Machine|____________| FW |____________|Machine|
| A | $prv_if| |$dmz_if | B |
+-------+ +----+ +-------+


Cette règle ne s'applique donc qu'à if1, elle est équivalente à :
pass out quick on if1 from $prv_hosts to $dmz_hosts
flags S/SA modulate state


Je m'aperçois que j'aurais pu encore simplifier les règles que je
donnais. Disons:

pass out quick on $dmz_if from $prv_hosts to $dmz_hosts keep state


Tout dépend de ce que tu as avant ; si tu a un « block all » en début
de configuration, je doute que cette règle suffise pour que ça
fonctionne car le paquet ne rentrera pas dans FW via if0.


Oui, j'ai effectivement un « block in all », qui, dans ce sens, fait
comme tu dis. Pour essayer de comprendre, j'ai réduit mon pf.conf à sa
plus simple expression, et je n'ai plus que ces deux règles.


Si tu as un « block in all » seulement, le filtre ne bloquera jamais un
paquet sortant (de FW vers A ou B). La seule chose à faire est
d'indiquer ce qui peut rentrer.

Je pense comprendre ce que tu expliques. Quand on filtre sur « in »
ou « out », il faut que le paquet, en plus du match sur la règle « in »
ou « out », puisse traverser l'autre interface.


Tout à fait.

Si tu veux que A puisse accéder à B sur le port ssh :
pass from if0:network to if1:network proto tcp port ssh keep state


Effectivement, ça marche. Mais j'aimais bien le contrôle de
l'interface d'entrée; ça me paraît être une donnée parfaitement fiable
(puisque c'est le pare-feu qui la génère, et non le paquet qui
l'apporte). Est-ce qu'il y a un moyen de faire quand même ce contrôle.


Je ne suis pas sur de comprendre (bis). Dans la règle si dessus il est
dit de laisser passer les paquets du réseau attaché à l'interface if0
vers le réseau attaché à l'interface if1. Tous les paquets arrivant sur
l'interface if0 ($prv_hosts) et non à destination de $dmz_if sur le port
22 ne passeront pas en raison de ton « block in all » plus haut.

J'ai écrit ça, qui marche, mais ça oblige à passer par des tags, ce
qui me semble bien compliqué pour un problème simple:

pass in on $prv_if from $prv_hosts to any tag FROM_PRV
block return all
pass from $prv_hosts to $dmz_hosts tagged FROM_PRV keep state


Je ferais un truc comme ça pour commencer :
# cat > /etc/pf.conf < 'EOF'
prv_if=if0
dmz_if=if1
prv_hosts=$prv_if:network
dmz_hosts=$dmz_if:network
scrub in all
antispoof for { $prv_if $dmz_if }
block in log all
pass from $prv_hosts to $dmz_hosts keep state
EOF
# pfctl -e -f /etc/pf.conf
# ifconfig pflog0 up
# tcpdump ${others_options} -i pflog0

Plus éventuellement 2 autres fenêtres avec des tcpdump sur if0 et if1 et
tester. Dans tous les cas, je te conseille vivement la lecture de
<http://www.bgnett.no/~peter/pf/>.

--
Benoit Izac


Avatar
Jérémy JUST
On Sun, 18 Feb 2007 16:59:16 +0100
Benoit Izac wrote:

Dans la règle si dessus il est dit de laisser passer les paquets du
réseau attaché à l'interface if0 vers le réseau attaché à l'interface
if1.


Oui, mais le filtrage se fait concrètement sur l'IP du paquet (est-ce
une IP qui appartient au réseau attaché à if0?) et non sur l'interface
physique réelle (est-ce que le paquet est passé à travers if0?).
Enfin, il me semble que c'est expliqué comme ça dans le bouquin de Jacek
Artymiak.

Avec les règles d'antispoofing, il y a de bonnes chances que les
filtrages sur « les IP du réseau attaché à l'interface » et sur « la
traversée de l'interface » donnent la même chose, mais, qui sait, un
paquet habilement forgé pourrait ne pas être bloqué par « antispoof ».


prv_hosts=$prv_if:network
dmz_hosts=$dmz_if:network


J'ai même des listes d'IP beaucoup plus restrictives pour les différents
sous-réseaux.


# ifconfig pflog0 up
# tcpdump ${others_options} -i pflog0


Tu as raison, je vais commencer par jeter un oeil aux logs. Je n'ai
qu'un accès par un port série au routeur, donc ce n'est pas très
confortable, mais ça me semble indispensable.


Dans tous les cas, je te conseille vivement la lecture de
<http://www.bgnett.no/~peter/pf/>.


Je l'avais lu il y a quelques mois, quand j'avais configuré tout le
reste de mon routeur (je suis simplement en train de modifier sa
configuration après avoir ajouté deux interfaces). Il y a eu une mise à
jour depuis, je vais regarder ce qui a changé.

Je ne sais plus si c'est ce document ou le livre de Jacek Artymiak qui
conseille de ne considérer que le côté « in » ou « out » du routeur, mais
pas les deux. Ce conseil est peut-être finalement fondé. ;)


--
Jérémy JUST

Avatar
Jérémy JUST
On Sun, 18 Feb 2007 16:38:49 +0100
Stephane Catteau wrote:

imagine une machine comme la mienne, avec quatre interfaces :


Mon fire-wall a aussi quatre interfaces (dont une WiFi condamnée pour
l'instant), mais jusque là, la DMZ n'avais pas de configuration
particulière parce que rien n'était accessible de l'extérieur.



Ce qui est autorisé à rentrer par une interface n'est pas autorisé à
ressortir n'importe par n'importe quelle interface.


C'est bien pour ça que je tiens à tenir compte des interfaces d'entrée
et de sortie (même si j'ai retiré ces mentions dans mon premier exemple,
pour faire plus simple).


ce qui arrive vu que j'ai placé le serveur NTP sur la passerelle (je
sais, c'est mal).


Oui, mais c'est tellement logique et simple. En parlant de « proxy
NTP » plutôt que « serveur », ça passe mieux intellectuellement. Note que
j'ai aussi mon DNS sur la passerelle, ce qui est probablement pire.


Le mieux, selon moi, c'est de ne filtrer que sur le 'in' et de laisser
les TAG faire le reste.


Donc tu confirmes que pour filtrer confortablement sur les interfaces,
on est plus ou moins obligé de jouer avec les tags?


pass in quick from $prv_hosts to $dmz_hosts tag PERMIT flags S/SA
modulate state [les autres règles]
block return in log quick from $prv_hosts to any
block return in quick all

pass out quick all tagged PERMIT
[Les règles "out" spécifiques à la passerelle (NTP, plus FTP, HTTP et CVS
pour les mises à jour)]
block return out quick all


Ne serait-il pas plus fin de stocker dans le tag le nom de l'interface
d'entrée, plutôt que simplement l'autorisation de sortie? Je pense par
exemple à des règles qui commenceraient par:

pass in on $prv_if from $prv_hosts to any tag PRV
pass in on $dmz_if from $dmz_hosts to any tag DMZ
pass in on $ext_if from any to any tag EXT
block in all
...


Au final, excepté pour ce qui concerne la machine elle-même, tu n'as que
des règles "in". De cette façon, la maintenance est largement
simplifiée, puisque tu ne risques pas d'oublier de modifier la règle
"out" associée, et parce que la lecture de l'ensemble est beaucoup plus
facile.


Oui, c'est un bon conseil. Je vais essayer de me focaliser sur un côté
ou l'autre, mais ne pas jongler sur les deux.


Merci.

--
Jérémy JUST

Avatar
Benoit Izac
Bonjour,

le 18/02/2007 à 17:34, Jérémy JUST a écrit dans le message
<45d88032$0$3693$ :

Avec les règles d'antispoofing, il y a de bonnes chances que les
filtrages sur « les IP du réseau attaché à l'interface » et sur « la
traversée de l'interface » donnent la même chose, mais, qui sait, un
paquet habilement forgé pourrait ne pas être bloqué par « antispoof ».


Si l'on commence à douter la dessus, on peut aussi se dire qu'un autre
paquet encore plus habilement forgé va contourner la règle block et
ainsi de suite... Faudrait pas tomber dans la paranoïa non plus. ;-)

prv_hosts=$prv_if:network
dmz_hosts=$dmz_if:network


J'ai même des listes d'IP beaucoup plus restrictives pour les
différents sous-réseaux.


Ça ne change rien du tout. C'était juste pour donner un exemple sans
avoir d'informations précises sur la topologie de ton réseau et ce que
tu veux en faire.

Je ne sais plus si c'est ce document ou le livre de Jacek Artymiak
qui conseille de ne considérer que le côté « in » ou « out » du
routeur, mais pas les deux. Ce conseil est peut-être finalement
fondé. ;)


Généralement on dit que le filtrage des flux sortants ne sert à rien
d'autre que de créer des problèmes.

--
Benoit Izac


Avatar
Jérémy JUST
On Sun, 18 Feb 2007 18:15:32 +0100
Benoit Izac wrote:

Si l'on commence à douter la dessus, on peut aussi se dire qu'un autre
paquet encore plus habilement forgé va contourner la règle block et
ainsi de suite... Faudrait pas tomber dans la paranoïa non plus. ;-)


Je me soigne. :}


Généralement on dit que le filtrage des flux sortants ne sert à rien
d'autre que de créer des problèmes.


On dirait qu'il peut aussi servir aussi à montrer qu'on n'a pas tout
compris au filtrage...


Merci pour tes remarques, je vais faire quelques essais et simplifier
mon pf.conf en suivant tes conseils.
Ce qui m'étonne, c'est que tout le reste avait marché presque du premier
coup, il y a quelques mois (mais je venais de lire toutes les docs).


--
Jérémy JUST

Avatar
Stephane Catteau
Jérémy JUST devait dire quelque chose comme ceci :


Le mieux, selon moi, c'est de ne filtrer que sur le 'in' et de laisser
les TAG faire le reste.


Donc tu confirmes que pour filtrer confortablement sur les interfaces,
on est plus ou moins obligé de jouer avec les tags?


Lorsque j'ai rajouté un FAI à ma passerelle, j'ai voulu étendre les
règles d'IPF déjà existantes. Après deux tubes d'aspirines je suis passé
à pf et, entre autre grace aux tags, j'ai réussi à créer ces foutues
règles, divisé par 7 le nombre de règles, et je suis persuadé qu'il y a
en plus moins de trous noirs imprévus.
Alors bon, les puristes raleront peut-être, mais oui, selon moi c'est
mille fois plus confortable avec les tags.


pass in quick from $prv_hosts to $dmz_hosts tag PERMIT flags S/SA
modulate state [les autres règles]
block return in log quick from $prv_hosts to any
block return in quick all

pass out quick all tagged PERMIT
[Les règles "out" spécifiques à la passerelle (NTP, plus FTP, HTTP et CVS
pour les mises à jour)]
block return out quick all


Ne serait-il pas plus fin de stocker dans le tag le nom de l'interface
d'entrée, plutôt que simplement l'autorisation de sortie? Je pense par
exemple à des règles qui commenceraient par:

pass in on $prv_if from $prv_hosts to any tag PRV
pass in on $dmz_if from $dmz_hosts to any tag DMZ
pass in on $ext_if from any to any tag EXT
block in all


Ca dépend de la façon dont tu filtres et de la façon dont tu comptes
gérer tout cela sur le long terme. Personnellement, plutôt que d'avoir
plusieurs tag, je préfère avoir plusieurs règles, du style (à la va vite):

pass in quick on $if_wild1 from <nntp_specials> to any port 119 tag OK
pass in quick on $if_wild2 from any to any port 119 tag OK
pass in quick on $if_LAN from <LAN_all> to any port 119 tag OK
pass in quick on $if_DMZ from $nntp_host to <nntp_peer> port 119 tag OK
block in quick from any to any port 119

Dans l'absolue, il y a un risque potentiel avec les deux premières
règles, puisqu'elles laissent tout rentrer. Mais avec la NAT tout ce qui
vient de l'extérieur à destination du port 119 ne peut aller que sur la
bonne machine.
C'est, pour moi tout du moins, toujours une question de lecture des
règles. Tout le filtrage restant groupé au niveau des règles "in", si en
plus les règles sont groupées en fonction du plus petit dénominateur
commun (ici le port) au lieu d'avoir un découpage
[règles pour l'interface wild1]
[règles pour l'interface wild2]
[règles pour l'interface LAN]
[règles pour l'interface DMZ]
il suffit de voir ces cinq lignes pour savoir exactement tout ce qui peut
ou ne peut pas se faire avec le protocole NNTP.
Il reste le flou correspondant à ce qu'il y a derrière les tables et
les macros, mais si les noms sont bien choisi, à la limite on s'en fiche.
Qu'importe ici de savoir quels sont les machines avec lesquels mon
serveur à un feed, l'important c'est que l'on voit tout de suite que ce
sont les seuls adresses auxquelles il a peut accéder, et qu'il n'y a que
lui qui peut y accéder. Ca oblige à multiplier les tables, mais ça évite
bien des migraines. Cela d'autant plus que les-dites tables sont faciles
à remplir, je connais le nom de mes feeds, et il n'y a qu'eux qui doivent
figurer dans la table "nntp_peer".
Cerise sur le gateau, lorsque j'enlève ou ajoute un feed, je n'ai que la
table à modifier.

Ensuite, dans la mesure où je filtre déjà sur l'interface au niveau de
la règle elle-même, doubler ça au niveau du tag n'apporterait pas grand
chose de plus.
Bon, évidement, tout dépend de la taille du réseau et du fait que la
DMZ est ou non en adresses IP routables. Mais pour un réseau de
particulier, un seul tag me semble suffisant, voir à la limite, pour les
paranoïaques, un second tag NOT_OK placé sur toutes les règles /block/
et doublée d'un "block quick all tagged NOT_OK"


Merci.


De rien.


Avatar
Stephane Catteau
Jérémy JUST devait dire quelque chose comme ceci :

Généralement on dit que le filtrage des flux sortants ne sert à rien
d'autre que de créer des problèmes.


On dirait qu'il peut aussi servir aussi à montrer qu'on n'a pas tout
compris au filtrage...


En fait, excepté pour ce qui concerne la machine elle-même, si tu te
retrouve à écrire des règles "out", c'est que tu doutes de tes règles
"in", et si tu es obligé d'écrire des règles "out", c'est que tes
règles "in" sont mal pensées.
C'est donc un bon témoin d'alerte : Si cette règle "out" existe, c'est
qu'il reste une faille quelque part, corrigeons là.