OBSD4* : wiki

Version de traduction basée sur la 6.2 officielle


PF - Traduction d’adresses réseaux

Introduction

La traduction d’adresses réseaux (NAT - Network Address Translation) est une manière de cartographier un réseau entier (ou des réseaux) à une simple adresse IP. La NAT est nécessaire quand le nombre d’adresses IP qui vous est assignées par votre FAI (Fournisseur d’Accès à Internet) est inférieur au nombre total d’ordinateurs auxquels vous souhaitez fournir un accès internet. La NAT est décrit dans la RFC 1631.

La NAT vous permet de profiter des blocs d’adresses réservés dans la RFC 1918. Typiquement, votre réseau interne sera configuré pour utiliser un ou plusieurs de ces blocs d’adresses réseaux. Ils sont :

  10.0.0.0/8       (10.0.0.0 - 10.255.255.255)
  172.16.0.0/12    (172.16.0.0 - 172.31.255.255)
  192.168.0.0/16   (192.168.0.0 - 192.168.255.255)

Un système OpenBSD qui gère la NAT a au moins deux interfaces réseaux, l’une pour internet, l’autre pour votre réseau interne. La NAT traduira les requêtes du réseau interne de manière à ce qu’elles apparaissent comme si elles venaient toutes de votre système OpenBSD faisant fonctionner la NAT.

Comment NAT fonctionne

Lorsqu’un client sur un réseau interne contacte une machine sur internet, il envoie des paquets IP destinés à cette machine. Ces paquets contiennent toutes les informations d’adressage nécessaires pour les acheminer vers leur destination. La NAT est concernée par ces informations :

  • Adresse IP Source (par exemple, 192.168.1.35)
  • Port TCP ou UDP Source (par exemple, 2132)

Lorsque les paquets passent au-travers de la passerelle NAT, ils sont modifiés de manière à apparaître comme s’ils venaient de la passerelle NAT elle-même. La passerelle NAT enregistre les changements dans sa table d’état afin qu’elle puisse a) inverser les modifications sur les paquets de retour et b) s’assurer que les paquets de retour passent au-travers du pare-feu et qu’ils ne soient pas bloqués. Pour l’exemple, les modifications suivantes pourraient être faites :

  • Adresse IP Source : remplacée avec l’adresse externe de la passerelle (par exemple, 198.51.100.1)
  • Port Source : remplacé par un choisi aléatoirement, un port inutilisé sur la passerelle (par exemple, 53136)

Ni la machine interne ni l’hôte Internet ne connaissent ces étapes de traduction. Pour la machine interne, le système NAT est simplement une passerelle Internet. Pour l’hôte sur Internet, les paquets semblent venir directement du système NAT ; il n'est pas conscient de l’existence même de la station de travail interne.

Lorsque l’hôte sur Internet répond aux paquets de la machine interne, ils seront adressés à l’IP externe de la passerelle NAT (198.51.100.1) sur le port traduit (53136). La passerelle NAT cherchera dans sa table d’état pour déterminer si les paquets de réponses correspondent à une connexion déjà établie. Une correspondance unique sera trouvée, basée sur la combinaison IP/Port qui indique à PF que les paquets appartiennent à une connexion initiée par la machine interne 192.168.1.35. PF fait alors les changements opposés sur les paquets sortants et transmet les paquets de réponses à la machine interne.

La traduction de paquets ICMP fonctionne de la même manière mais sans la modification du port source.

IP forwarding

Étant donné que la NAT est presque toujours utilisée sur les routeurs et autres passerelles réseaux, il sera probablement nécessaire d’activer le transfert d’IP afin que les paquets puissent voyager entre les interfaces réseaux sur une machine OpenBSD. Le transfert d’IP est activé en utilisant le mécanisme de sysctl(3) :

  # sysctl net.inet.ip.forwarding=1
  # echo  'net.inet.ip.forwarding=1' >> /etc/sysctl.conf

Ou, pour IPv6:

  # sysctl net.inet6.ip6.forwarding=1
  # echo  'net.inet6.ip6.forwarding=1' >> /etc/sysctl.conf

Configuration NAT

La NAT est spécifiée avec le paramètre optionnel nat-to sur une règle sortante pass. Souvent, au lieu d'utiliser directement une règle pass, une règle match est utilisée. Quand un paquet est sélectionné par une règle match, les paramètres (ex., nat-to) dans cette règle sont rappelés et sont appliqués au paquet quand une règle pass correspondante est atteinte. Cela permet à toute une classe de paquets d’être capturés par une simple règle match et alors de prendre des décisions spécifiques sur l’opportunité d'allouer le trafic, ce qui peut être fait avec des règles block et pass.

Le format général dans le fichier pf.conf ressemble à quelque chose comme cela :

  match out on interface [af] \
     from src_addr to dst_addr \
     nat-to ext_addr [pool_type] [static-port]
  [...]
  pass out [log] on interface [af] [proto protocol] \
     from ext_addr [port src_port] \
     to dst_addr [port dst_port]

match
Lorsqu'un paquet parcourt le jeu de règles et correspond à une règle match, tous les paramètres optionnels spécifiés dans cette règle sont mémorisés pour un usage ultérieur (rendue “collante”)


pass
Cette règle permet que le paquet soit transmis. Si le paquet correspondait précédemment à une règle match où des paramètres étaient spécifiés, ils seront appliqués au paquet. Les règles pass peuvent avoir leurs propres paramètres ; ceux-ci ont la priorité sur les paramètres spécifiés dans la règle match.


out
Spécifie la direction du flux de paquets lorsque cette règle s’applique. nat-to peut seulement être spécifié sur les paquets sortants.


log
Enregistre la correspondance des paquets via pflogd(8). Normalement, seul le premier paquet qui correspond sera enregistré. Pour consigner tous les paquets correspondants, utilisez log (all).


interface
Le nom ou le groupe d'interfaces réseaux où transmettre les paquets.


af
La famille d'adresse, soit inet pour IPv4 ou inet6 pour IPv6. PF est généralement capable de déterminer le paramètre en fonction de la ou les adresse(s) sources ou destinations.


protocol
Le protocole (ex. tcp, udp, icmp) des paquets à autoriser. Si src_port ou dst_port est spécifié, le protocole doit également être donné.


src_addr
L’adresse source (interne) des paquets qui sera traduite. L’adresse source peut être spécifiée ainsi :

  • Une unique adresse IPv4 ou IPv6.
  • Un bloc réseau CIDR.
  • Un nom de domaine pleinement qualifié qui sera résolu via DNS quand le jeu de règles sera chargé. Toutes les adresses IP résultantes seront substituées dans cette règle.
  • Le nom ou le groupe d'interface réseau. Toutes les adresses IPv4 ou IPv6 assignées à l’interface seront substituées dans la règle lors du chargement.
  • Le nom d'une interface réseau suivi du masque réseau /netmask (ex. /24). Chaque adresse IP sur l’interface sera combinée avec le masque de réseau formant un bloc réseau CIDR qui sera substitué dans la règle.
  • Le nom ou le groupe d'interface réseau suivi d'un des ces modificateurs :
    • :network - substitue le bloc réseau CIDR (ex., 192.168.0.0/24)
    • :broadcast - substitue l’adresse de bouclage réseau (ex., 192.168.0.255)
    • :peer - substitue l'adresse IP du pair d'un lien point à point.
      De plus, le modificateur :0 peut être ajouté soit à un nom ou un groupe d'interface soit à un des modificateurs ci-dessus pour indiquer que PF ne devrait pas inclure les alias d'adresses IP dans la substitution. Ces modificateurs peuvent aussi être utilisés quand l’interface se trouve entre parenthèses. Exemple : fxp0:network:0
  • Une table.
  • L'un des éléments ci-dessus, mais en utilisant le modificateur négatif ! (“not”).
  • Un ensemble d’adresses utilisant une liste.
  • Le mot-clé any signifiant toutes les adresses.

src_port
Le port source dans l’entête du paquet de la Couche 4. Les ports peuvent être spécifiés comme :

  • Un nombre entre 1 et 65 535
  • Un nom de service valide issu de services(5)
  • Un ensemble de ports utilisant une liste
  • Un plage :
    • != (non égal)
    • < (+ petit que)
    • > (+ grand que)
    • (+ inférieur ou égal)
    • >= (+ supérieur ou égal)
    • >< (plage )
    • <> (plage inverse)
      Ces deux derniers opérateurs binaires (qui prennent deux arguments) n’incluent pas les arguments.
    • : (plage inclusive)
      Cet opérateur de plage inclusif est aussi un opérateur binaire et inclut les arguments.

L'option port n'est généralement pas utilisée dans les règles nat car le but du NAT est habituellement de traduire tout le trafic quel que soit le(s) port(s) utilisé(s).


dst_addr
L'adresse de destination des paquets à traduire. L’adresse de destination est spécifiée de la même manière que pour l'adresse source.


dst_port
Le port de destination dans l’entête du paquet de la Couche 4. Ce port est spécifié de la même manière que le port source.


ext_addr
L’adresse externe (traduite) sur la passerelle NAT depuis laquelle les paquets vont être traduits. L'adresse externe peut être ainsi spécifiée :

  • Une unique adresse IPv4 ou IPv6.
  • Un bloc réseau CIDR.
  • Un nom de domaine pleinement qualifié qui sera résolu via DNS quand le jeu de règles est chargé.
  • Le nom ou le groupe d'interface réseau externe. Toute adresse IP assignée à l'interface sera substituée dans la règle au chargement.
  • Le nom ou le groupe d'interface réseau externe entre parenthèses ( ). Cela indique à PF de mettre à jour la règle si la ou les adresse(s) IP de l'interface désignée change(nt). Ceci est très utile quand l'interface externe obtient son adresse IP via DHCP ou connexion commutée, ainsi le jeu de règles n'a pas à être rechargé à chaque fois qu'une adresse change.
  • Le nom ou le groupe d'interface réseau suivi d'un de ces modificateurs :
    • :network - substitue le bloc réseau CIDR (ex., 192.168.0.0/24)
    • :peer - substitue l'adresse IP du pair d'une liaison point à point
      De plus, le modificateur :0 peut être ajouté soit à un nom ou un groupe d'interface soit à l'un des modificateurs ci-dessus pour indiquer que PF ne devrait pas inclure les alias d'adresses IP dans la substitution. Ces modificateurs peuvent aussi être utilisés lorsque l'interface est mis entre parenthèses. Exemple : fxp0:network:0
  • Un ensemble d'adresses utilisant une liste.

pool_type
Spécifie le type du groupe d'adresses à utiliser pour la traduction.


static-port
Indique à PF de ne pas traduire le port source dans les paquets TCP et UDP.

Cela conduirait à la forme la plus basique de ces lignes telles que :

  match out on tl0 from 192.168.1.0/24 to any nat-to 198.51.100.1
  pass on tl0 from 192.168.1.0/24 to any

Ou vous pouvez simplement utiliser :

  pass out on tl0 from 192.168.1.0/24 to any nat-to 198.51.100.1

Cette règle dit d'assumer la NAT sur l'interface tl0 pour tout paquet venant depuis le réseau 192.168.1.0/24 et de remplacer l'adresse IP source par 198.51.100.1.

Bien que la règle ci-dessus soit correcte, elle n'est pas recommandée. La maintenance peut être difficile car toute modification des numéros de réseau externe ou interne exigerait que la ligne soit modifiée. Comparez plutôt avec cette ligne plus facile à maintenir (tl0 est l'externe, dc0 est l'interne) :

  pass out on tl0 inet from dc0:network to any nat-to tl0

L'avantage doit être assez clair : vous pouvez changer la ou les adresses IP de n'importe quelle interface sans changer la règle. Notez que inet devrait être spécifié dans ce cas afin de s'assurer que seules les adresses IPv4 soient utilisées, évitant les surprises inattendues.

Lors de la spécification d'un nom d'interface pour la traduction d'adresse comme ci-dessus, l'adresse IP est déterminée lors du chargement de pf.conf, pas à la volée. Si vous utilisez DHCP pour configurer votre interface externe, cela peut poser problème. Si votre adresse IP assignée change, la NAT continuera à traduire les paquets sortant en utilisant l'ancienne adresse IP. Ceci aura pour conséquence que les connexions sortantes cesseront de fonctionner. Pour contourner cela, vous pouvez dire à PF de mettre à jour automatiquement la traduction d'adresse en mettant des parenthèses autour du nom de l'interface :

  pass out on tl0 inet from dc0:network to any nat-to (tl0)

Cette méthode fonctionne pour la traduction sur les adresses IPv4 et IPv6.

Cartographie bidirectionnelle (1:1)

Une cartographie bidirectionnelle peut être établie en utilisant le paramètre binat-to. Une règle binat-to établit une correspondance 1 pour 1 entre l'adresse IP interne et l'adresse externe. Cela peut être utile, par exemple, pour fournir un serveur web sur un réseau interne avec sa propre adresse IP externe. Les connexions depuis Internet vers l'adresse externe seront traduites vers l'adresse interne et les connexions depuis le serveur web (telles que les requêtes DNS) seront traduites vers l'adresse externe. Les ports TCP et UDP ne sont jamais modifiés avec les règles binat-to comme ils le sont avec les règles nat.

Exemple :

  web_serv_int = "192.168.1.100"
  web_serv_ext = "198.51.100.6"
  
  pass on tl0 from $web_serv_int to any binat-to $web_serv_ext

Exceptions aux règles de traduction

Si vous avez besoin de traduire la plupart du trafic, mais de fournir des exceptions dans certains cas, assurez-vous que ces exceptions soient gérées par une règle de filtrage qui n'inclue pas le paramètre nat-to. Par exemple, si l'exemple de NAT ci-dessus était modifié pour ressembler à cela :

  pass  out on tl0 from 192.168.1.0/24 to any nat-to 198.51.100.79
  pass  out on tl0 from 192.168.1.208  to any

Alors l'ensemble du réseau 192.168.1.0/24 aurait ses paquets traduits vers l'adresse externe 198.51.100.79 excepté pour 192.168.1.208.

Vérifier le statut NAT

Pour voir les traductions de la NAT en cours, pfctl(8) est utilisé avec l'option -s state. Cette option listera toutes les sessions NAT courantes :

  # pfctl -s state
  fxp0 tcp 192.168.1.35:2132 (198.51.100.1:53136) -> 198.51.100.10:22 TIME_WAIT:TIME_WAIT
  fxp0 udp 192.168.1.35:2491 (198.51.100.1:60527) -> 198.51.100.33:53   MULTIPLE:SINGLE

Des explications (seulement la première ligne) :


fxp0
Indique l'interface sur lequel l'état est traité. Le mot self apparaîtra si l'état est flotting.


TCP
Le protocole utilisé par la connexion.


192.168.1.35:2132
L'adresse IP (192.168.1.35) de la machine sur le réseau interne. Le port source (2132) est affiché après l'adresse. C'est aussi l'adresse qui est remplacée dans l'entête IP.


198.51.100.1:53136
L'adresse IP (198.51.100.1) et le port (53136) sur la passerelle vers laquelle les paquets sont traduits.


198.51.100.10:22
L'adresse IP (198.51.100.10) et le port (22) sur laquelle est connectée la machine interne.


TIME_WAIT:TIME_WAIT
Cela indique dans quel état PF croit que la connexion TCP est établie.


Cette page est la traduction officieuse de la page «Network Address Translation» de la FAQ officielle d'OpenBSD.
En cas de doute, merci de vous y référer !

Si vous voulez participer à l’effort de traduction, merci de lire ce topic.