La traduction d'adresses IP ("NAT") est un mécanisme destiné à
faire correspondre un réseau entier (ou des réseaux) à une seule adresse
IP. Un tel mécanisme est nécessaire lorsque le nombre des adresses IP
qui vous sont attribuées par votre Fournisseur d'Accès à Internet est plus
petit que le nombre de machines qui doivent pouvoir bénéficier d'une
connexion Internet. La NAT est décrite dans la
RFC 1631,
"The IP Network Address Translator (NAT)".
La NAT vous permet de bénéficier des blocs d'adressage privés décrits
dans la
RFC 1918,
"Address Allocation for Private Internets".
Typiquement, votre réseau interne sera paramétré pour
utiliser un ou plusieurs des blocs réseau suivants :
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 mettant en oeuvre la NAT aura au moins deux cartes
réseau dont une est connectée à Internet; l'autre étant connectée à
votre réseau interne. La NAT traduit les requêtes en provenance de votre
réseau interne de telle façon à les faire apparaître comme si elles
étaient générées par votre système de NAT OpenBSD.
Comment Fonctionne la NAT
Lorsqu'un client du réseau interne entre en communication avec une
machine sur Internet, il envoie des paquets IP à destination de cette
machine. Ces paquets contiennent toutes les informations sur leur
émetteur et leur destinataire nécessaires à leur bon acheminement. La
NAT prend en compte les informations suivantes :
L'adresse IP source (192.168.1.35 par exemple)
Port TCP ou UDP source (2132 par exemple)
Lorsque les paquets passent à travers la passerelle NAT, ils sont
modifiés de telle façon à ce qu'ils semblent provenir de la passerelle
NAT. Cette passerelle enregistrera les modifications effectuées dans sa
table d'état afin de a) inverser les modifications pour les paquets de
retour et b) s'assurer que les paquets de retour sont autorisés à
traverser le pare-feu et ne sont pas bloqués. Par exemple, les
modifications suivantes peuvent être effectuées :
Adresse IP source : remplacée par l'adresse externe de la passerelle
(24.5.0.5 par exemple)
Port source : remplacé par un port non utilisé sur la passerelle et
choisi de manière aléatoire (53136 par exemple)
Aucune des deux extrémités de la communication ne se rend compte de ces
modifications. Pour la machine interne, le système qui effectue la NAT
est simplement une passerelle Internet. Pour l'hôte sur Internet, les
paquets semblent provenir directement du système de NAT; il ne sait même
pas que la machine interne existe.
Lorsque l'hôte sur Internet répond aux paquets de la machine interne, ils
seront envoyés à l'adresse IP externe de la passerelle NAT (24.5.0.5)
sur le port de traduction (53136). Dès réception de ces paquets, la
passerelle NAT cherchera dans sa table d'état si ces paquets de retour
correspondent à une connexion déjà établie. Une correspondance unique
sera trouvée, basée sur la combinaison IP/port qui permet à PF de voir
que les paquets appartiennent à une connexion initiée par la machine
interne 192.168.1.35. PF effectuera les modifications inverses à celles
effectuées sur les paquets sortants puis enverra ces paquets à la
machine interne.
La traduction de paquets ICMP s'effectue de manière similaire mais sans
la modification du port source.
NAT et Filtrage de Paquets
REMARQUE :
Les paquets traduits doivent, comme n'importe quel autre paquet, être
évalués par le mécanisme pare-feu suivant les règles de filtrage
définies. La seule exception à cette règle est lorsque le
mot-clé pass est utilisé dans la règle de nat. Ce
mot-clé permettra aux paquets traduits d'être autorisés immédiatement
par le pare-feu.
Il est à noter que la traduction a lieu avant le filtrage. Ce qui
veut dire que le pare-feu verra le paquet traduit avec l'adresse
IP et le port traduits tel que c'est expliqué dans
Comment Fonctionne la NAT.
Routage IP
Vu que la NAT est utilisée la plupart du temps sur des routeurs et des
passerelles réseau, il sera probablement nécessaire d'activer le routage
IP pour permettre aux paquets de traverser les interfaces réseau du
système OpenBSD. Le routage IP peut être activé à l'aide du mécanisme
sysctl(3) :
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1 (si Ipv6 est utilisé)
Pour rendre cette modification permanente, les lignes suivantes doivent
être ajoutées au fichier
/etc/sysctl.conf :
Ces lignes sont déjà présentes dans l'installation par défaut mais sont
commentées (préfixées avec un caractère #). Supprimez le
# et sauvegardez le fichier. Le routage IP sera désormais
activé automatiquement à chaque redémarrage.
Configurer la NAT
Le format général des règles de NAT dans pf.conf est le suivant
:
nat [pass] [log] on interface [af] from src_addr
[port src_port] to \ dst_addr [port dst_port] ->
ext_addr [pool_type] [static-port]
nat
Le mot-clé qui permet de créer une règle de NAT.
pass
Permet aux paquets traduits de contourner complètement les règles de
filtrage et d'être autorisés systématiquement par le pare-feu.
log
Journaliser les paquets correspondants à l'aide de
pflogd(8).
Normalement, uniquement le premier paquet qui correspond à la règle sera
tracé. Pour tracer tous les paquets correspondants, utilisez log
(all).
interface
Le nom ou groupe de l'interface réseau sur laquelle les paquets
seront traduits.
af
La famille d'adresses : inet pour IPv4 ou inet6
pour IPv6. PF est normalement capable de déterminer ce paramètre à
partir des adresses source/destination.
src_addr
L'adresse source (interne) des paquets qui seront traduits.
L'adresse source peut être spécifiée de plusieurs manières :
Un nom de domaine au format FQDN qui sera résolu via DNS lorsque les
règles seront chargées. Ce nom de domaine sera remplacé par toutes
les adresses IP résultant de la résolution.
Un nom ou groupe d'interface réseau. Ce nom sera remplacé par toutes
les adresses IP attribuées à cette interface au moment du chargement
des règles.
Un nom d'interface réseau suivi d'un /netmask
(/24 par exemple). Chaque adresse IP attribuée à
l'interface sera combinée avec le netmask pour former un bloc réseau
en notation CIDR. Le résultat remplacera la spécification initiale
dans la règle.
Le nom ou groupe d'une interface réseau suivi par un modificateur
parmi les modificateurs suivants :
:network - remplace le bloc réseau en notation
CIDR (192.168.0.0/24 par exemple)
:broadcast - remplace l'adresse de broadcast
réseau (192.168.0.255 par exemple)
:peer - remplace l'adresse IP du pair dans une
communication point-à-point
De plus, le modificateur :0 peut être ajouté au
nom/groupe de l'interface ou à l'un des modificateurs précités
pour indiquer à PF que les alias IP ne doivent pas être inclus
dans la substitution. Ces modificateurs peuvent aussi être
utilisés lorsque le nom de l'interface est entre parenthèses.
Exemple :
fxp0:network:0
Les deux derniers opérateurs sont des opérateurs binaires
(ils prennent deux arguments) et n'incluent pas les
arguments dans l'intervalle.
: (intervalle avec inclusion)
L'opérateur d'intervalle avec inclusion est aussi un
opérateur binaire mais contrairement aux deux opérateurs
précédents, il inclut les arguments dans l'intervalle.
L'option port n'est pas habituellement utilisée dans les règles
nat vu que le but est souvent de traduire tout le trafic peu
importe le(s) port(s) utilisé(s).
dst_addr
L'adresse destination des paquets à traduire. L'adresse de
destination est spécifiée de la même manière que l'adresse source.
dst_port
Le port destination dans l'en-tête du paquet (couche 4). Ce port est
spécifié de la même manière que le port source.
ext_addr
L'adresse externe (de traduction) sur la passerelle NAT. C'est
l'adresse qui figurera dans les paquets une fois ceux-ci traduits.
L'adresse externe peut être spécifiée comme suit :
Un nom de domaine au format FQDN qui sera résolu via DNS lorsque les
règles seront chargées. Ce nom de domaine sera remplacé par toutes
les adresses IP résultant de la résolution.
Le nom de l'interface réseau externe. Ce nom sera remplacé par
toutes les adresses IP attribuées à cette interface au moment du
chargement des règles.
Le nom de l'interface réseau externe entouré de parenthèses (
). Ceci permet à PF de mettre à jour la règle si l'adresse ou
les adresses IP de cette interface change(nt). C'est très utile
lorsque l'interface obtient son adresse IP via DHCP ou un système
dial-up. Dans ce cas, les règles n'ont pas à être rechargées chaque
fois que l'adresse change.
Le nom d'une interface réseau suivi par un modificateur parmi les
modificateurs suivants :
:network - remplace le bloc réseau en notation
CIDR (192.168.0.0/24 par exemple)
:peer - remplace l'adresse IP du pair dans une
communication point-à-point
De plus, le modificateur :0 peut être ajouté au nom de
l'interface ou à l'un des modificateurs précités pour indiquer à
PF que les alias IP ne doivent pas être inclus dans la
substitution. Ces modificateurs peuvent aussi être utilisés lorsque
le nom de l'interface est entre parenthèses. Exemple :
fxp0:network:0
Spécifie le type de pool d'adresses à
utiliser pour la traduction.
static-port
Si cette option est utilisée, PF ne traduira pas le port source des
paquets TCP et UDP.
Ceci nous donne une ligne de la forme basique suivante :
nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5
Cette règle permet d'effectuer la NAT sur l'interface tl0 sur
tout paquet provenant de 192.168.1.0/24 et remplace l'adresse IP source
par 24.5.0.5.
Bien que cette règle soit correcte, ce n'est pas la forme recommandée.
La maintenance peut s'avérer difficile vu que toute modification des
adresses réseau externe ou interne nécessitera une modification de la
règle. La forme suivante est plus facile à maintenir (tl0 est
l'interface externe, dc0 est l'interface interne) :
nat on tl0 from dc0:network to any -> tl0
L'avantage de cette forme doit être clair maintenant : vous pouvez
changer les adresses IP des deux interfaces sans changer la règle.
Lorsque vous spécifiez un nom d'interface comme adresse de traduction
tel que c'est fait dans la règle ci-dessus, l'adresse IP est déterminée
lors du chargement de pf.conf. Elle n'est pas déterminée à la
volée. Si vous utilisez DHCP pour configurer votre interface externe,
ceci peut poser problème. Par exemple, si l'adresse qui vous est
attribuée change, le système de NAT continuera à traduire les paquets
sortants en utilisant l'ancienne adresse IP. Les connexions sortantes ne
fonctionneront donc plus. Pour éviter ce problème, vous pouvez dire à PF
de mettre à jour automatiquement l'adresse de traduction en mettant des
parenthèses autour du nom de l'interface :
nat on tl0 from dc0:network to any -> (tl0)
Cette méthode fonctionne aussi bien pour la traduction d'adresses IPv6
que pour la traduction d'adresses IPv4.
Mise en Correspondance Bidirectionnelle (mise en correspondance
1:1)
Une mise en correspondance bidirectionnelle (traduction 1 à 1) peut être
établie en utilisant une règle binat. Une règle binat
établit une correspondance 1 à 1 entre une adresse IP interne et une
adresse externe. Ceci peut être pratique par exemple pour permettre à un
serveur web interne d'avoir sa propre adresse de traduction externe. Les
connexions en provenance d'Internet à destination de cette adresse
externe seront acheminées vers l'adresse interne du serveur web. Quant
aux requêtes émanant du serveur web (telles que les requêtes DNS), elles
seront traduites de telle façon à remplacer l'adresse interne par
l'adresse externe de traduction attribuée au serveur web. Contrairement
aux règles nat, les règles binat ne modifient jamais
les ports TCP.
binat on tl0 from $web_serv_int to any -> $web_serv_ext
Exceptions aux Règles de Traduction
Des exceptions aux règles de traduction peuvent être faites en utilisant
le mot-clé no. Par exemple, si la règle de NAT précédente était
modifiée de la manière suivante :
no nat on tl0 from 192.168.1.208 to any
nat on tl0 from 192.168.1.0/24 to any -> 24.2.74.79
Alors tous les paquets du réseau 192.168.1.0/24 seront traduits avec
l'adresse externe 24.2.74.79 excepté pour la machine 192.168.1.208.
Il est à noter que la première règle à laquelle un paquet correspond est
appliquée et aucune évaluation supplémentaire n'est effectuée. S'il y a
une règle no, alors le paquet n'est pas traduit. Le mot-clé
no peut être utilisé avec les règles binat et
rdr.
Vérification de l'état de la NAT
Pour voir les traductions actives, il faut utiliser
pfctl(8)
avec l'option -s state. Cette option affichera une liste de
toutes les sessions NAT en cours :
# pfctl -s state
fxp0 TCP 192.168.1.35:2132 -> 24.5.0.5:53136 -> 65.42.33.245:22 TIME_WAIT:TIME_WAIT
fxp0 UDP 192.168.1.35:2491 -> 24.5.0.5:60527 -> 24.2.68.33:53 MULTIPLE:SINGLE
Explications (première ligne uniquement) :
fxp0
Indique l'interface à laquelle est rattachée la session. Le mot-clé
self apparaîtra si la session est de type
floating.
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 sera remplacée au niveau de l'en-tête IP.
24.5.0.5:53136
L'adresse IP (24.5.0.5) et le port (53136) sur la passerelle
utilisés pour la traduction.
65.42.33.245:22
L'adresse IP (65.42.33.245) et le port (22) auxquels la machine
interne est connectée.