Table des matières Page précédente Page suivante

III-8 IP masquerading / Port forwarding

Si Netfilter est très efficace pour filtrer les connexions entrantes et sortantes des processus locaux, il peut servir aussi à d'autres fonctionnalités, comme le masquage IP et le suivi de port.

III-8-1 IP masquerading

Jusqu'à présent, la machine Paradise de notre réseau n'a pas été très utilisée. Son activité réseau est restreinte à celle du réseau sky.net. Alors que Phoenix, lui, peut se connecter au réseau internet.net. Tout cela n'est pas très juste, aussi allons nous y remédier. Comment ? En transformant tout simplement Phoenix en une passerelle entre les réseaux sky.net et internet.net.

Dans tout ce qui suit, nous allons nous arranger pour que paradise.sky.net puisse se connecter au serveur web web.internet.net.

Sous Windows®, ce que nous allons faire s'appelle du "partage de connexion Internet", ce qui est tout à fait vrai : Phoenix va partager sa connexion à Internet avec les machines du réseaux sky.net.

Pour réaliser ceci, il nous faut réaliser plusieurs opérations :
  • La première, c'est de charger les modules dont nous allons avoir besoin. En premier, nous avons besoin du module de NAT, c'est à dire "iptables_nat". Comme nous voulons aussi faire du suivi de connexion sur les paquets NAT, nous chargerons de même les modules NAT FTP et IRC, "ip_nat_ftp" et "ip_nat_irc" :
    [root@phoenix /]# modprobe iptable_nat
    [root@phoenix /]# modprobe ip_nat_ftp
    [root@phoenix /]# modprobe ip_nat_irc
    
  • Bien entendu, tout comme nous initialisons la table "Filter" nous devons initialiser la tables NAT :
    [root@phoenix /]# iptables -t nat -F
    [root@phoenix /]# iptables -t nat -X
    
  • Pour ce qui est des cibles par défaut des chaînes de la table NAT, nous acceptons toutes les connexions. Il n'est pas nécessaire de faire pointer ces cibles sur "DROP", car la sécurité est établie au niveau de la table "Filter", par le "DROP" par défaut de la chaîne FORWARD :
    [root@phoenix /]# iptables -t filter -P FORWARD     DROP
    [root@phoenix /]# iptables -t nat    -P PREROUTING  ACCEPT
    [root@phoenix /]# iptables -t nat    -P POSTROUTING ACCEPT
    [root@phoenix /]# iptables -t nat    -P OUTPUT      ACCEPT
    
  • Bien, maintenant nous allons faire suivre sur le réseau internet.net, les connexions issues du réseau sky.net. Bien entendu, nous ne ferons suivre que les connexions qui sont à destination du réseau internet.net, et non celles destinées à la machine Phoenix elle-même. Pour cela, nous allons avoir besoin d'utiliser la table "Filter" (he oui, encore !), afin de faire suivre les paquets venant de la carte eth0 (phoenix0.sky.net) à la carte eth1 (phoenix1.internet.net), et vice versa. En plus de cela, comme ce sont uniquement les connexions initialisées par le réseau interne que nous désirons faire sortir, nous rajouterons un peu de suivi de connexion.
    [root@phoenix ]# iptables -t filter -A FORWARD -i eth0 -o eth1 -s 192.168.0.0/24 -d 0.0.0.0/0 \
                              -m state --state ! INVALID           -j ACCEPT
    [root@phoenix ]# iptables -t filter -A FORWARD -i eth1 -o eth0 -s 0.0.0.0/0 -d 192.168.0.0/24 \
                              -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    L'accumulation des paramètres "-i", "-o", "-s", "-d" et "--state" permettent de garantir que seul les connexions initialisées par le domaine sky.net seront autorisées à passer, et non l'inverse.
  • Au point où nous en somme, les paquets venant de sky.net et sortant par l'interface eth1, ont :
    • pour adresse de destination, une adresse du réseau internet.net, ce qui est parfaitement normal. Celle de web.internet.net par exemple
    • pour adresse source, l'adresse d'une machine du domaine sky.net, comme par exemple celle de paradise.sky.net (voir lien "(1)"). Oui, mais ce domaine est un réseau privé, dont l'adresse IP n'est pas du tout routable sur Internet. Conclusion : lorsque web.internet.net recevra la requête, il ne saura absolument pas où envoyer la réponse... C'est assez ennuyeux, non ?
    Il va donc falloir que Phoenix subtilise l'adresse IP source des trames qui le traverse, et la remplace par la sienne (voir lien "(2)"). C'est là qu'intervient (enfin !) la table NAT, avec la cible "MASQUERADE" (pour "masquage" en anglais) :
    [root@phoenix /]# iptables -t nat -A POSTROUTING -o eth1 \
                               -s 192.168.0.0/24 -j MASQUERADE
    
    Vous pouvez cependant vous poser la question suivante : que deviennent les paquets revenant du réseau internet.net sur l'interface eth1 ? Ils ont pour adresse source web.internet.net, et pour adresse cible phoenix1.internet.net (voir lien "(3)"). Donc si ils sont recopiés sur le réseau sky.net, ils ne saurons pas qu'ils doivent aller sur paradise.sky.net, non ? En théorie, ceci est exacte, et demanderait la mise en place d'une seconde règle de de "MASQUERADE". Mais en fait, c'est inutile, car avec la première règle, Netfilter gère une table en mémoire qui suit ces masquage d'adresses IP, et elle réassigne aux connexions rentrantes la bonnes adresse IP cibles (voir lien "(4)").

    En fait, ce serait même terriblement dangereux de mettre en place une telle règle de ce type. En effet, cela pourrait faire passer pour des connexions de Phoenix, des connexions initialisées par les machines de internet.net ! C'est comme si vous poussiez vous-même le loup dans la bergerie ! Donc l'utilisation de la table NAT et de la cible "MASQUERADE" doivent se faire avec le plus rigueur possible, souvenez vous en bien.

  • Enfin, maintenant que tout le NAT est configuré, il ne reste plus qu'à autoriser dûment votre Linux à faire jouer son rôle de gateway. Pour cela, il faut utiliser simplement écrire un "1" dans le "/proc/sys/net/ipv4/ip_forward". Ce fichier est en fait un fichier virtuel, qui permet de dialoguer directement avec le kernel. Nous allons donc utiliser la commande suivante :
    [root@phoenix /]# echo 1 > /proc/sys/net/ipv4/ip_forward
    
Masquage d'adresse
Masquage d'adresse
Le NAT étant maintenant configuré et activé, il reste à configurer les machines du réseau sky.net, afin de leur indiquer quelle est la passerelle. C'est chose faite en lançant par exemple sur paradise.sky.net :
[root@paradise /]# route add default gw phoenix0.sky.net
[root@paradise /]# route
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic Metric Ref    Use Iface
192.168.0.0     *               255.255.255.0   U     0      0        0 eth0
127.0.0.0       *               255.0.0.0       U     0      0        0 lo
default         phoenix0.sky.ne 0.0.0.0         UG    0      0        0 eth0
Bien, tout est en place. Voyons ce que cela donne. Depuis paradise.sky.net, tentons une connexion sur web.internet.net:
[olivier@paradise /]$ nmap web.internet.net -p 80,443

Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on web.0.0.10.in-addr.arpa (10.0.0.200):
Port       State       Service
80/tcp     open        http
443/tcp    open        https

Nmap run completed -- 1 IP address (1 host up) scanned in 0 seconds
Bien ! Comme on le voit, la connexion se fait d'un réseau à l'autre, à travers Phoenix. Opération réussie donc ! Cela qui nous donne l'occasion de trouver ici le script iptables de cet exemple.

Remarques : Dans tout nos exemples, nous avons systématiquement autorisé tout le réseau sky.net à accéder à internet.net. Cependant, nous aurions très bien pu limiter cet accès à uniquement quelques machines de notre réseau interne. Pour cela, il suffit de changer les options "-s" et "-d" de nos règles de "FORWARD", et d'indiquer l'adresse IP de la machine qui est autorisée à passer d'un réseau à un autre.
Exemple :
[root@phoenix ]# iptables -t filter -A FORWARD -i eth0 -o eth1 -s 192.168.0.2 -d 0.0.0.0/0 \
                          -m state --state ! INVALID           -j ACCEPT
[root@phoenix ]# iptables -t filter -A FORWARD -i eth1 -o eth0 -s 0.0.0.0/0 -d 192.168.0.2 \
                          -m state --state ESTABLISHED,RELATED -j ACCEPT
Et qu'en dit la sécurité ? Est-ce que par hasard pirate.internet.net peut accéder à paradise.sky.net ? Est-ce possible ? Techniquement oui, il suffit que pirate.internet.net déclare phoenix1.internet.net comme étant sa passerelle pour le réseau internet.net :
[root@pirate /]# route add default gw phoenix1.internet.net
[root@pirate /]# route
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic Metric Ref    Use Iface
10.0.0.0        *               255.0.0.0       U     0      0        0 eth0
127.0.0.0       *               255.0.0.0       U     0      0        0 lo
default         phoenix1.intern 0.0.0.0         UG    0      0        0 eth0
Puis, de lancer par exemple un "ping" sur l'adresse IP de paradise.sky.net :
[root@pirate /]# ping -c 3 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.

--- 192.168.0.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2014ms
Bien, notre machine est correctement sécurisée. Tout va donc pour le mieux ? Indéniablement, oui. Mais tel un funambule entrain de traverser le vide sur une corde tendue, il ne faut pas grand chose pour que cette état idéal se transforme en un cauchemar sans nom... Smiley

En effet, regardons les traces qu'on laissé la dernière connexion de pirate.internet.net dans les statistiques de Netfilter :
[root@phoenix /]# iptables -L -v -n -t nat
Chain PREROUTING (policy ACCEPT 3 packets, 252 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  *     eth1    192.168.0.0/24       0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Cette commande nous indique que 3 paquets ont été acceptés par le comportement par défaut de la chaîne "PREROUTING" de la table "NAT". C'est tout à fait normal, ce sont nos 3 paquets de ping qui arrivent de pirate.internet.net et qui s'apprêtent à passer à travers Phoenix. Mais qui va les arrêter ?

[root@phoenix /]# iptables -L -v -n -t filter
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     all  --  lo     *    0.0.0.0/0      0.0.0.0/0
    0     0 ACCEPT     all  --  eth0   *    192.168.0.0/24 192.168.0.0/24

Chain FORWARD (policy DROP 3 packets, 252 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     all  --  eth0   eth1 192.168.0.0/24 0.0.0.0/0      state NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  eth1   eth0 0.0.0.0/0      192.168.0.0/24 state RELATED,ESTABLISHED

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     all  --  *      lo   0.0.0.0/0      0.0.0.0/0
    0     0 ACCEPT     all  --  *      eth0 192.168.0.0/24 192.168.0.0/24
Cette commande là nous indique que 3 paquets ont été détruits par le comportement par défaut de la chaîne "FORWARD" de la table "Filter". Là encore, c'est ce à quoi nous attendions. Pourquoi ? Parce qu'aucune des autres règles de la chaîne "FORWARD" de cette table ne les ont laissé passer.

Maintenant, changeons seulement le comportement par défaut de la table "FORWARD" de la table "Filter" :
[root@phoenix /]# iptables -t filter -P FORWARD ACCEPT
Juste pour information, on pourra télécharger ce méchant script iptables ici.

Et relançons notre "ping" depuis pirate.internet.net :
[intrus@pirate /]$ ping -c 3 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=254 time=0.957 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=254 time=0.987 ms
64 bytes from 192.168.0.2: icmp_seq=3 ttl=254 time=0.957 ms

--- 192.168.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2021ms
rtt min/avg/max/mdev = 0.957/0.967/0.987/0.014 ms
QUOI !?!? Notre intrus peut accéder sans problème à l'intérieur de notre réseau ? Diantre, il y a un bug, et un méchant ! Et tout cela à cause d'un malheureuse règle par défaut ?

Oui, exactement. Regardons les statistiques d'iptables pour la table "Filter" :
[root@phoenix /]# iptables -L -v -n -t filter
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp dpt:6000
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp dpt:6000
    0     0 ACCEPT     all  --  lo     *    0.0.0.0/0      0.0.0.0/0
    0     0 ACCEPT     all  --  eth0   *    192.168.0.0/24 192.168.0.0/24

Chain FORWARD (policy ACCEPT 3 packets, 252 bytes)
 pkts bytes target     prot opt in     out  source         destination
    3   252 ACCEPT     all  --  eth0   eth1 192.168.0.0/24 0.0.0.0/0      state NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  eth1   eth0 0.0.0.0/0      192.168.0.0/24 state RELATED,ESTABLISHED

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp spt:6000
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp spt:6000
    0     0 ACCEPT     all  --  *      lo   0.0.0.0/0      0.0.0.0/0
    0     0 ACCEPT     all  --  *      eth0 192.168.0.0/24 192.168.0.0/24
Voilà quelque chose de très intéressant :
  • 3 paquets sont passés par la cible "ACCEPT" par défaut de la chaîne "Filter". Ce sont les 3 pings venant de pirate.internet.netà destination de paradise.sky.net. Notre trou de sécurité se trouve indéniablement ici.
  • 3 autres paquets ont utilisés la règle basée sur du suivi de connexion, partant du réseau sky.net et allant sur internet.net. Bien sûr, c'est tout à fait normal. Car pour Netfilter, une connexion sky.net -> internet.net est bien initialisée ou en relation avec une autre...
Regardons maintenant les statistiques de la table "NAT" :
[root@phoenix /]# iptables -L -v -n -t nat
Chain PREROUTING (policy ACCEPT 3 packets, 252 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 3 packets, 252 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  *      eth1    192.168.0.0/24       0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
3 paquets sont passés par les chaînes "PREROUTING" puis "POSTROUTING" afin de sortir du réseau internet.net et atteindre le réseau sky.net. Par contre, il n'y a pas de traces des paquets de réponse de paradise.sky.net à pirate.internet.net. Ceci est dû au mécanisme interne de Netfilter qui identifie les connexions en réponse, et qui ne les fait pas passer par la table NAT. C'est pour cela, et comme vu plus haut, qu'il n'y a pas besoin d'écrire des règles spécifiques pour le "MASQUERADING rentrant".

De cette (longue) explication nous pourrons en tirer 3 leçons :
  • Il faut toujours initialiser les cibles par défaut, même pour les chaînes des tables que nous ne pensons peut-être pas utiliser. Il faut en toute situation connaître l'état de de ces cibles. Un script Netfilter devrait donc toujours commencer par :
    # Initialisation de la table FILTER
    iptables -t filter -F
    iptables -t filter -X
    iptables -t filter -P INPUT   DROP
    iptables -t filter -P OUTPUT  DROP
    iptables -t filter -P FORWARD DROP
    
    # Initialisation de la table NAT
    iptables -t nat -F
    iptables -t nat -X 
    iptables -t nat -P PREROUTING  ACCEPT
    iptables -t nat -P POSTROUTING ACCEPT
    iptables -t nat -P OUTPUT      ACCEPT
    
    # Initialisation de la table MANGLE
    iptables -t mangle -F
    iptables -t mangle -X 
    iptables -t mangle -P PREROUTING  ACCEPT
    iptables -t mangle -P INPUT       ACCEPT
    iptables -t mangle -P OUTPUT      ACCEPT
    iptables -t mangle -P FORWARD     ACCEPT
    iptables -t mangle -P POSTROUTING ACCEPT
    
  • Avant de mettre en place un système de NAT, il faut bien prendre en compte tous les paramètres, et se rendre compte de l'impact que cela peut avoir sur la sécurité de votre réseau. Il n'y a rien de pire que de copier/coller un mauvais morceau de script "iptables", et de se dire que cela doit bien marcher tout seul. Voir de bidouiller affreusement le script dans son coin, et de jouer à l'apprenti sorcier ! Smiley
  • En cas de doute, ou de problème sur l'utilisation de Netfilter, il ne fait pas hésiter à utiliser la commande "iptables -L -v -t [table]" qui donne plein d'informations quand aux nombre de paquets passant par une règle ou un comportement par défaut.
Bien, l'IP masquerading étant vu, passons au port forwarding.

III-8-2 Port forwarding

Bien caché derrière notre firewall Phoenix, notre réseau sky.net ne craint plus grand chose. De plus, avec ce que nous avons vu au chapitre précédent, les machines de notre réseau local peuvent rejoindre le réseau internet.net.

Maintenant, nous voudrions avoir un serveur (HTTP, FTP, IRC, peer-to-peer, etc...) qui puisse proposer des informations et des services non plus sur le réseau sky.net, mais carrément sur le réseau internet.net. L'emplacement d'un tel service devrait se faire en toute logique sur la machine Phoenix, qui est le seul accès que nous ayons sur le réseau internet.net. Mais ceci serait une très mauvaise idée. Pourquoi ? Parce qu'un tel accès est inévitablement une faille dans notre système de sécurité. Grâce à ce service que nous proposons, l'intrus pourrait essayer de se l'accaparer, puis d'en profiter pour prendre la main sur Phoenix, et enfin de court-circuiter toutes nos règles Netfilter. Notre machine se trouverait alors sans aucune protection vis à vis de l'extérieur... Inquiétant, non ? Au minimum, il faudrait configurer ce service pour fonctionner sous un utilisateur n'ayant que peu de droits, et en plus dans un chroot. Mais même avec cela, la sécurité ne pourrait pas être garantie.

Alors, comment faire ? C'est là qu'intervient le suivi de port ("port fowarding" en anglais). L'idée d'un tel système est que toute connexion entrante sur un certain port de phoenix1.internet.net (par exemple le port 80, pour du HTTP), soit automatiquement redirigée vers une autre machine de sky.net : paradise.sky.net par exemple. Vu de l'extérieur, on aurait l'impression que le port 80 de phoenix1.internet.net serait ouvert, mais en fait, ce serait le port 80 de paradise.sky.net qui serait réellement ouvert, et sur lequel tournerait un serveur Apache.
Est-ce réellement une "solution miracle" ? Presque, mais à condition de prendre quelques précautions :
  • Dans cette configuration, nous ne faisons que déplacer le problème de sécurité sur Paradise. Il faut donc que cette machine soit très bien sécurisée, avec les paramétrages vus dans la section "risque" du chapitre II. Mais ce ne sera pas suffisant.
  • Paradise devenant donc un serveur web à part entière, et du fait des risques énoncés, Phoenix devra donc s'en méfier comme de la peste. Fini les gentilles règles Netfilter laissant paradise.sky.net pleinement accéder à phoenix0.sky.net. Il faudra durcir tout cela, et utiliser le conntrack ! Dans notre esprit, paradise.sky.net devra devenir aussi soupçonnable que pirate.internet.net.
  • Enfin, dans le cas où un intrus prendrait le contrôle de Paradise, et même si Phoenix à des règles Netfilter très strictes, rien n'empêcherait l'intrus de s'attaquer à une autre machine du réseau sky.net ! Voir dans le pire des cas, de s'approprier le contrôle d'une autre machine de sky.net, puis d'attaquer Phoenix par l'arrière, en profitant d'éventuelles règles Netfilter plus souples vis à vis de ce 2nd hôte...
En terme de sécurité informatique, la paranoïa peut devenir un jeu d'esprit où il faut systématiquement envisager les pires cas, et les hypothèses les plus tordues. Dans le cas de notre réseau, les 3 problèmes ci-dessus peuvent êtres réglés par une technique plutôt efficace, appelée DMZ ("DeMilitarized Zone ou "Zone DéMilitarisée" en français). La mise en place d'une telle DMZ se fait en installant une 3ème carte réseau sur Phoenix ("eth2"), sur laquelle on ne reliera que une seule machine qui ne servira qu'au seul usage de serveur web. On appellera cette machine DMZ, tout simplement. Voir à ce sujet l'illustration ci-contre. Mais ceci sort du cadre de ce document, et d'un réseau personnel, je n'en parlerai donc pas plus longuement.
DMZ
DMZ pour port fowarding
Mais revenons à un réseau un peu plus simple, et baissons d'un cran notre paranoïa. Nous allons supposer que la machine qui hébergera notre serveur HTTP est fiable, et que personne ne peut en prendre la main (ceci n'est qu'une hypothèse bien sûr !). Nous la laisserons donc dans le réseau sky.net, en compagnie des autres machines de notre réseau interne.

Que devons nous faire ?
  • Tout d'abord, nous devons initialiser la table NAT, tout comme nous l'avons fait pour le IP masquerading. Et aussi bien sûr charger le module "iptables_nat" :
    [root@phoenix /]# modprobe iptable_nat
    [root@phoenix /]# iptables -t nat -F
    [root@phoenix /]# iptables -t nat -X
    [root@phoenix /]# iptables -t filter -P FORWARD     DROP
    [root@phoenix /]# iptables -t nat    -P PREROUTING  ACCEPT
    [root@phoenix /]# iptables -t nat    -P POSTROUTING ACCEPT
    [root@phoenix /]# iptables -t nat    -P OUTPUT      ACCEPT
    
  • Comme nous voulons partager un serveur HTTP, il peut être intéressant d'autoriser les machines de internet.net de pouvoir utiliser le "ping" sur notre serveur. Ce n'est absolument pas une obligation, mais cela peut-être pratique pour les Internautes qui, avant de lancer la connexion HTTP, vérifient que notre machine est bien active. Ce choix relève plus d'une bonne manière qu'autre chose, et n'est donc pas obligatoire. Notre "port forwarding" pourra très bien marcher sans cela. On utilise quand même du "suivi de connexion", afin de ne pas accepter les paquets ICMP volontairement mal formatés :
    [root@phoenix /]# iptables -t filter -A INPUT  -i eth1 -s 0.0.0.0/0 -d 10.0.0.1 \
                               -p icmp -m state --state ! INVALID           -j ACCEPT
    [root@phoenix /]# iptables -t filter -A OUTPUT -o eth1 -s 10.0.0.1  -d 0.0.0.0/0 \
                               -p icmp -m state --state RELATED,ESTABLISHED -j ACCEPT
    
    Au passage, vous noterez qu'il n'est pas nécessaire d'ouvrir d'autres accès. Et notamment via les chaînes "INPUT" et "OUTPUT" afin autoriser l'échange avec le port 80. Pourquoi ? Simplement parce que dans le cas du port forwarding, les trames à destination de paradise.sky.net ne sont pas destinées aux processus locaux, et donc elle ne passent pas à travers les chaînes "INPUT" et "OUTPUT". En fait, comme on le verra tout de suite, seul la chaîne "FORWARD" de la table "Filter" devra être modifiée.
  • Nous allons maintenant faire suivre un certain type de paquets de l'interface "eth1" à l'interface "eth0" : Ce sera les paquets à destination du serveur HTTP. De même que nous laisserons passer les paquets en réponse. Là encore, nous utilisons du "conntrack" afin d'améliorer la sécurité de ce suivi de port :
    [root@phoenix /]# iptables -t filter -A FORWARD -i eth1 -o eth0 -s 0.0.0.0/0   \
                               -d 192.168.0.2 -p tcp --dport 80                    \
                               -m state --state ! INVALID           -j ACCEPT
    [root@phoenix /]# iptables -t filter -A FORWARD -i eth0 -o eth1 -s 192.168.0.2 \
                               -d 0.0.0.0/0   -p tcp --sport 80                    \
                               -m state --state RELATED,ESTABLISHED -j ACCEPT
    
  • Nous arrivons à la 1er spécificité du "port forwarding". Pour les paquets entrant sur phoenix1.internet.net et à destination du port 80, nous allons modifier l'adresse de destination. Ce ne sera plus phoenix1.internet.net, mais paradise.sky.net, c'est à dire notre réel serveur HTTP. Pour cela, nous allons utiliser dans la table NAT, la chaîne "PREROUTING" et la cible "DNAT" (pour "Destination Network Adress Translation" en anglais).
    [root@phoenix /]# iptables -t nat -A PREROUTING  -i eth1 -s 0.0.0.0/0   \
                               -d 10.0.0.1  -p tcp --dport 80               \
                               -m state --state ! INVALID -j DNAT --to-destination 192.168.0.2:80
    
    Au passage, on voit que l'on peut aussi modifier le port de destination, et mettre autre chose que 80. Cela peut-être utile si le serveur HTTP sur paradise.sky.net tourne sur autre chose que le port 80.
  • La seconde spécificité du "port forwarding", c'est de modifier aussi l'adresse source de la requête. En effet, si nous laissons l'adresse source actuelle (une adresse de 10.0.0.0/8 par exemple), paradise.sky.net sera bien ennuyé pour répondre, car ce sera une adresse d'un réseau qu'il ne peut pas joindre. Évidement, nous pourrions indiquer à paradise.sky.net que phoenix0.sky.net est une passerelle, et dans ce cas là les paquets retrouveraient tout de suite la sortie du réseau sky.net. Mais, et même si cette solution marche effectivement très bien, c'est une solution particulièrement mal propre, comme nous le verrons un peu plus loin. Donc, modifions cette adresse source :
    [root@phoenix /]# iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 \
                               -d 192.168.0.2 -p tcp --dport 80            \
                               -m state --state ! INVALID -j SNAT --to-source 192.168.0.1
    
  • Bien, au niveau de Netfilter, tout est configuré. Il nous reste qu'à activer le NAT par la commande que nous connaissons déjà :
    [root@phoenix /]# echo 1 > /proc/sys/net/ipv4/ip_forward
    
Le script iptables décrit ici est téléchargeable ici.

Il ne nous reste plus qu'à vérifier que pirate.internet.net a bien accès à phoenix1.internet.net :
[intrus@pirate /]$ telnet phoenix1.internet.net 80
Escape character is '^]'.
GET /
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <meta name="GENERATOR" content="Mozilla/4.61 [en] (X11; I; Linux 2.2.9-23mdk i686) [Netscape]">
   <meta name="Author" content="MandrakeSoft">
   <title>Welcome to the Advanced Extranet Server, ADVX!</title>
   <LINK REL="SHORTCUT ICON" HREF="/favicon.ico">
<!-- Background white, links blue (unvisited), navy (visited), red (active) --> </head>

<body text="#000000" bgcolor="#FFFFFF" link="#0000FF" vlink="#000080" alink="#FF0000">
<table border=0>
<tr>
<td valign=top><a href=http://www.advx.org><img border=0 src=/icons/advx.png
ALT="Powered by ADVX.org software" height=47 width=102 align=LEFT></a></td>
<td valign=top width=100%><h2><center>Welcome to paradise.sky.net
</center></h2>
</td></tr>
La fin de la réponse a été tronquée. Bien que l'on accède à phoenix1.internet.net, c'est paradise.sky.net qui répond. Regardons maintenant le log du serveur Apache de paradise.sky.net :
[root@paradise /]# tail -1 /var/log/httpd/access_log
192.168.0.1 - - [06/Jul/2003:21:02:21 +0200] "GET /" 200 6988 "-" "-"
On voit la connexion faite par pirate.internet.net, et le téléchargement de la page web. Cependant, on notera que l'adresse IP qui est logée n'est pas celle de pirate.internet.net, mais bien celle de phoenix1.internet.net, ce qui est tout à fait normal, du fait de l'utilisation de la cible "SNAT".

Enfin, regardons ce que nous donne les statistiques de Netfilter sur Phoenix :
[root@phoenix /]# iptables -L -v -n -t filter
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp dpt:6000
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp dpt:6000
    0     0 ACCEPT     all  --  lo     *    0.0.0.0/0      0.0.0.0/0
    0     0 ACCEPT     all  --  eth0   *    192.168.0.0/24 0.0.0.0/0
    0     0 ACCEPT     icmp --  eth1   *    0.0.0.0/0      10.0.0.1       state NEW,RELATED,
                                                                          ESTABLISHED

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source      destination
    8   430 ACCEPT     tcp  --  eth1   eth0 0.0.0.0/0      192.168.0.2    tcp dpt:80 state
                                                                          NEW,RELATED,ESTABLISHED
    8  7412 ACCEPT     tcp  --  eth0   eth1 192.168.0.2    0.0.0.0/0      tcp spt:80 state
                                                                          RELATED,ESTABLISHED

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp spt:6000
    0     0 ACCEPT     tcp  --  *      *    0.0.0.0/0      0.0.0.0/0      tcp spt:6000
    0     0 ACCEPT     all  --  *      lo   0.0.0.0/0      0.0.0.0/0
    0     0 ACCEPT     all  --  *      eth0 0.0.0.0/0      192.168.0.0/24
    0     0 ACCEPT     icmp --  *      eth1 10.0.0.1       0.0.0.0/0      state RELATED,
                                                                          ESTABLISHED
[root@phoenix /]# iptables -L -v -n -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    1    60 DNAT       tcp  --  eth1   *    0.0.0.0/0      10.0.0.1       tcp dpt:80 state NEW,RELATED,
                                                                          ESTABLISHED to:192.168.0.2:80

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source         destination
    1    60 SNAT       tcp  --  *      eth0 0.0.0.0/0      192.168.0.2    tcp dpt:80 state NEW,RELATED,
                                                                          ESTABLISHED to:192.168.0.1
La requête et l'envoi de la page HTML ont demandés au total 2 fois 8 paquets, qui sont passés à travers les chaînes "FORWARD".

On voit bien que les paquets entrant dans phoenix1.internet.net sont bien passés par les cibles "DNAT" et "SNAT" des chaînes "PREROUTING" et "POSTROUTING". Par contre ces statistiques ne montre pas les paquets en réponses à la demande de connexion. C'est dû à la même routine de suivi de connexion de Netfilter que pour l'IP masquerading.

Nous pourrions nous arrêter ici pour le port fowarding, mais un dernier point est intéressant à soulever : que se passe t'il si nous n'incluons pas la règles SNAT, ce qui est indiqué plus haut comme étant une "méthode sale" ?

Commençons par retirer cette règle :
[root@phoenix /]# iptables -D POSTROUTING 1 -t nat
Puis, indiquons à Paradise que sa passerelle est phoenix0.sky.net
[root@paradise /]# route add default gw phoenix0.sky.net
[root@paradise /]# route

Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic Metric Ref    Use Iface
192.168.0.0     *               255.255.255.0   U     0      0        0 eth0
127.0.0.0       *               255.0.0.0       U     0      0        0 lo
default         phoenix0.sky.ne 0.0.0.0         UG    0      0        0 eth0
Et maintenant, demandons à nouveau notre page HTML depuis pirate.internet.net. Suite à cette connexion, les statistiques d'"iptables" nous donne :
[root@phoenix /]# iptables -L -v -n -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out source       destination
    1    60 DNAT       tcp  --  eth1   *   0.0.0.0/0    10.0.0.1    tcp dpt:80 state NEW,RELATED,
                                                                    ESTABLISHED to:192.168.0.2:80

Chain POSTROUTING (policy ACCEPT 1 packets, 60 bytes)
 pkts bytes target     prot opt in     out source       destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
Comme précédemment, un paquet est passé par le chaîne "PREROUTING", mais aucun n'est passé par de règles "POSTROUTING". Et pour cause, il n'y en a plus. Par contre, le paquet de retour est passé par la règle par défaut de la chaîne POSTROUTING... C'est parce que les paquets n'empruntent pas les mêmes canaux en entrée et en sortie que j'estime cette méthode comme étant "sale".

Enfin ce qui est le plus intéressant c'est le log d'Apache sur paradise.sky.net :
[root@paradise /]# tail -1 /var/log/httpd/access_log
10.0.0.66 - - [06/Jul/2003:22:27:43 +0200] "GET /" 200 6988 "-" "-"
Cette fois ci, c'est bien l'adresse IP de la machine à distance qui est stockée, forcément, puisque Phoenix ne la dissimule plus.

Vous trouverez le script de cet exemple ici, mais comme indiqué, plus haut c'est la méthode "sale" pour effectuer du port forwarding...

Ceci conclue donc l'utilisation du port forwarding. Dans le cadre d'un usage personnel, cette technique est assez peu utile : qui chez lui héberge son propre serveur HTTP, FTP, IRC, etc...

Pas utile donc ? En fait non, il y a bien un usage personnel fort utile où l'on peut utiliser le port forwarding, et qui est particulièrement à la mode au jour où j'écris ces lignes : il s'agit du peer-to-peer (P2P). C'est un système d'échange de fichiers à travers Internet, où toutes les machines connectées partagent des fichiers sur un morceau de son disque dur. Chaque machine agit donc à la fois comme un client et un serveur. Une grand partie des clients pour ce type d'échange se trouvant sous Windows®, et comme c'est un OS dont l'usage courant est peu orienté sur la sécurité, on peut utiliser le port forwarding de Linux pour le protéger.

Avec les explications ci-dessus, vous pouvez sans difficulté écrire vos propres scripts iptables afin de renvoyer vos connexions entrantes vers la machine sur lequel tourne votre client P2P. Cependant, souvenez vous que vous ne faites que déplacer le problème de sécurité sur cette machine ci, et donc que c'est à vous d'en assurer la responsabilité. Si cette machine est par exemple sous Windows®, la présence de Netfilter en tête de votre réseau ne vous dispense pas de mettre en place un firewall logiciel sur cette machine, afin par exemple de surveiller ce que fait votre Windows®. Ceci étant, je me lave les mains de ce que vous pourriez faire de l'usage du port forwarding et du P2P. Et si je ne fournis aucun script d'exemple, c'est entre autre parce que je n'utilise pas ce type de logiciel... Smiley

Enfin, je dirais que la mise en place du port forwarding n'est pas forcément ce qui se fait le plus facilement, bien qu'en fait les règles ne soit pas beaucoup plus complexes que pour l'IP masquerading. Sur Internet, vous trouverez beaucoup de bribes d'explications sur cette techniques, et beaucoup de scripts plus où moins bien fait à ce sujet. Méfiez vous donc de ce que vous trouverez. Le mieux est sans aucun doute de tester votre configuration par étape, et de regarder systématiquement les statistiques d'iptables afin de voir par où passent vos paquets. D'une manière générale, si les paquets utilisent les cibles par défaut de PREROUTING ou de POSTROUTING, c'est qu'il y a probablement une mauvaise configuration de votre script. Enfin, comme indiqué dans les 2 scripts "iptables-portforwarding-*.sh" que vous pouvez télécharger, vous avez la possibilité d'utiliser la cible LOG afin d'analyser quelles sont les paquets qui utilisent ces cibles par défaut.

Table des matières Page précédente Page suivante
Valid XHTML 1.0! Valid CSS!
Site de référence : http://olivieraj.free.fr/ Last modified: Wed Jul 23 19:21:53 CEST 2003