Questions iptables, DNS, ip forwarding, VirtualBox

Tags: #<Tag:0x00007f371e7e2e88> #<Tag:0x00007f371e7e2c58>

Bonjour amis débianistes!

Attention pavé!

Débutant sur debian/ubuntu (moins d’un an), je m’intéresse depuis peu au fonctionnement réseau/pare-feu, etc. Mais plus je lis sur le sujet et plus je pratique, moins j’ai l’impression de comprendre…

J’essaie d’utiliser des règles iptables pour me familiariser avec cet outil, et j’essaie de comprendre ce qu’il se passe avant d’aller plus loin. Etant fan de virtualisation, mon but est d’avoir une VM debian qui sert de “gateway” (“static networking”, pas de serveur dhcp) pour les autres VM debian clientes qui se connectent dessus. J’y suis arrivé après de nombreux essais, mais de nombreuses questions restent en suspens, surtout en ce qui concerne la gestion des résolutions DNS, gros mystère pour moi. J’espère que des spécialistes pourront m’aider à comprendre ce qui se trame “sous le capot”. Je précise que tout se passe sous VirtualBox, n’étant pas assez calé pour le moment pour tenter KVM…

Sans plus attendre, voici ma configuration actuelle:

1. VM debian 9, “gateway” (vm1):

Cette VM sert de “gateway” aux autres VM s’y connectant et “forwarde” leur traffic sur internet.

Cette VM est reliée à deux interfaces dans le gestionnaire de VirtualBox:

  • la première interface est “NAT”, le NAT virtuel par défaut créé par VirtualBox qui communique directement avec le host. Elle correspond à l’interface enp0s3 dans la vm1.

  • la deuxième interface est “intnet” (le nom n’a aucune importance), un “internal network” qui sert à relier des machines entre elles sur un réseau virtuel privé qui n’est connecté ni au host, ni à l’internet public. Cette interface correspond à l’interface enp0s8 dans la vm1.

Dans la vm1, j’ai configuré ces interfaces de la manières suivante (contenu de /etc/network/interfaces):

allow-hotplug enp0s3
iface enp0s3 inet dhcp

allow-hotplug enp0s8
iface enp0s8 inet static
	address 192.168.42.10
	netmask 255.255.192.0

Comme on le voit, l’interface connectée au NAT virtuel obtient son IP automatiquement par le dhcp virtuel de VirtualBox. Elle est donc connectée à internet. La deuxième interface enp0s8 obtient l’adresse statique 192.168.42.10 que je lui ai attribuée dans /etc/network/interfaces. C’est un choix arbitraire, j’aurais pu prendre n’importe quelle autre adresse IP privée. Voici ce que renvoie ifconfig:

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        ether 08:00:27:c8:c2:9f  txqueuelen 1000  (Ethernet)
        RX packets 16369  bytes 7812753 (7.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 11244  bytes 2025946 (1.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.42.10  netmask 255.255.192.0  broadcast 192.168.63.255
        ether 08:00:27:ee:89:b0  txqueuelen 1000  (Ethernet)
        RX packets 6985  bytes 1206798 (1.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7157  bytes 6129776 (5.8 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

On constate que par défaut, enp0s3 se voit attribuer l’IP 10.0.2.15 par le NAT virtuel de VirtualBox.

Le contenu de /etc/resolv.conf est:

domain home
search home
nameserver 10.0.2.3

Là aussi, généré automatiquement par VirtualBox.

Je précise que j’ai désactivé le support IPV6 sur les deux machines virtuelles et qu’elles n’ont pas de network-manager. Tout se passe avec /etc/network/interfaces.

2. VM debian 9 “client” (vm2)

Cette VM n’a qu’une interface réseau, enp0s3, uniquement connectée au réseau interne “intnet”. Par défaut, elle n’a donc pas accès à internet, seulement à ce réseau virtuel. En l’état, elle peut “pinger” la gateway ou s’y connecter en ssh, ainsi qu’à toute autre machine partageant ce réseau interne virtuel, mais ne peut pas communiquer avec le “vrai” internet externe. Voici le contenu de son /etc/network/interfaces:

auto lo
iface lo inet loopback

allow-hotplug enp0s3
iface enp0s3 inet static
	address 192.168.42.11
	gateway 192.168.42.10
	netmask 255.255.192.0

tandis que ifconfig retourne:

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.42.11  netmask 255.255.192.0  broadcast 192.168.63.255
        ether 08:00:27:9a:84:a1  txqueuelen 1000  (Ethernet)
        RX packets 8238  bytes 6430199 (6.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8514  bytes 1768757 (1.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1  (Local Loopback)
        RX packets 108  bytes 6727 (6.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 108  bytes 6727 (6.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Concernant son /etc/resolv.conf ça se corse… Par défaut, le contenu est le même que pour une machine virtuelle sous NAT VirtualBox: 10.0.2.3. En effet, la machine a été installée normalement avec le NAT de VirtualBox, j’ai modifié l’interface après. Je n’ai donc pas touché à ce fichier, car je partais du principe que ason contenu n’avait pas d’importance et que la résolution DNS serait de toute façon opérée dans la vm2 “gateway” (ce n’est apparememnt pas tout à fait le cas, et c’est d’ailleurs l’objet de ma question, on y reviendra plus tard):

domain home
search home
nameserver 10.0.2.3

3. IP forwarding et règles iptables sur la “gateway” (vm1)

Pour permettre à la vm2 de communiquer avec internet, j’ai activé l’ip forwarding sur la vm1 (en ajoutant net.ipv4.ip_forward=1 dans /etc/sysctl.conf)
et entré les règles iptables suivantes (je rappelle que je suis en “static networking”, pas de serveur dhcp sur la vm1):

iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
iptables -A FORWARD -i enp0s3 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i enp0s8 -o enp0s3 -j ACCEPT

Depuis la vm2, je peux maintenant “pinger” des adresses ip externes. Mais curieusement, la vm1 ne peut pas résoudre de noms… Un “curl google.fr” renvoie systématiquement curl: (6) Could not resolve host: google.fr Pour permettre la résolution de noms, j’ajoute encore ces deux règles sur la “gateway” qui d’après ce que j’ai compris redirigent le traffic DNS de la vm2 sur le serveur DNS de la vm1 (par défaut avec le NAT de VirtualBox: 10.0.2.3):

iptables -t nat -A PREROUTING -i enp0s8 -p udp --dport 53 -j  DNAT --to-destination 10.0.2.3
iptables -t nat -A PREROUTING -i enp0s8 -p tcp --dport 53 -j DNAT --to-destination 10.0.2.3

A présent, je peux accéder normalement à internet depuis la vm1.

4. Questions

Tout fonctionne donc me direz-vous (si vous êtes encore là!), mais alors:

  • Pourquoi, si je vide le fichier /etc/resolv.conf sur la vm2, ou remplace 10.0.2.3 par une adresse bidon, la vm2 ne peut plus résoudre aucun nom? La résolution DNS étant censée être faite par la vm1 “gateway”, pourquoi la vm2 “cliente” “bloque” lorsque son fichier /etc/resolv.conf est vide ou comprend une adresse invalide? Pourquoi la vm2 cherche-t-elle absolument à résoudre les noms?

  • Pourquoi l’entrée 10.0.2.3 dans le fichier /etc/resolv.confest-elle considérée comme correcte par la vm2, alors qu’elle n’a pas accès à ce réseau virtuel (si je “pinge” 10.0.2.3 je n’obtiens rien), son interface étant uniquement un réseau interne avec comme ip statique 192.168.42.11?

  • Y a-t-il un moyen d’empêcher la vm2 cliente de résoudre les noms et de lui faire comprendre qu’elle doit forwarder cette tâche à la gateway (vm1), comme le reste de son traffic?

  • D’une manière générale, pourquoi le traffic DNS a-t-il besoin d’une règle à part dans les règles iptables de la “gateway”? Qu’a-t-il de spécial pour cela? Pourquoi n’est-il pas forwardé avec le reste du traffic?

  • Mes règles iptables pour le traffic DNS sont-elles correctes?

Je vous assure avoir bien googlé tout ça, en français comme en anglais, mais je n’ai pas réussi à trouver de réponses satisfaisantes. Je suis preneur de toutes explications, je suis encore très débutant en la matière et certaines choses sont bien confuses…

Merci d’avance!

j’ai l’impression que tu n’as pas installé Bind par exemple pour gérer le DNS donc quand tu dis que la résolution DNS est censée être faite par VM1 oui pour autant que ce soit un serveur DNS et pour autant que les autres serveurs soient paramétrés pour avoir VM1 comme DNS.

Merci de ta réponse, effectivement je n’ai pas installé bind sur la vm2 (gateway). Je vais essayer et voir ce que ça donne.

Je pense que j’ai de grosses lacunes en ce qui concerne la gestion du traffic DNS (entre autre), en fait je ne savais pas que c’était à ce point à part du reste du traffic internet.

Avec bind sur la vm2 (gateway), sera-t-il possible de se passer de la résolution DNS sur la vm1 (client)? Ce que je cherche à atteindre, c’est que l’ensemble du traffic de la vm1 transite de manière transparente par la vm2 (gateway), y compris les résolutions DNS. Donc /etc/resolv.conf devrait être vide de contenu sur la vm1, car la vm1 ne ferait aucune résolution DNS. Je vais voir si ça marche avec bind et vous tiens au courant.

Merci beaucoup!

fait le avec une route sinon

http://www.thegeekstuff.com/2012/04/route-examples/

ou tu forward avec iptables

ll y a des incohérences dans ton exposé. Au début vm1 est censée être le routeur (on ne dit plus passerelle ni gateway, ces termes sont ambigus et dépréciés) et vm2 le client, et ensuite ça devient l’inverse. Qui envoie des requêtes DNS à qui n’est pas clair non plus. Relis tout ça, corrige et on en reparle.

Aucun rapport entre la fonction de routeur et la résolution DNS en tout cas.

Merci de ta réponse, et désolé s’il y a des incohérences, j’en ai vu une dans mes questions que j’ai corrigée, je n’en ai pas vu d’autres?

C’est parfois compliqué à expliquer, et je manque sûrement de vocabulaire précis.

Je reprends pour résumé:

  • vm1 est le routeur

  • vm2 est le client

  • vm1 et vm2 sont connectés ensemble par un réseau interne virtuel sur VirtualBox qui n’a pas accès à l’internet public (“intnet”)

  • vm1 est également connecté à internet via le host par un NAT virtuel configuré par VirtualBox

  • vm1 a l’ip forwarding activé et des règles iptables qui lui font forwarder le traffic en provenance de vm2

  • vm2 est connecté à internet par le biais de la vm1 grâce aux règles iptables et à l’ip forwarding activé sur la vm1

Questions:

  • Pourquoi les requêtes DNS semblent-elles encore gérées par la vm2, même après ajout de règles iptables spécifiques pour les requêtes DNS sur la vm1 (cf plus haut)?
  • Comment empêcher que les requêtes DNS soient gérées par la vm2 et faire qu’elles soient entièrement gérées par la vm1 (routeur)?
  • Mes règles iptables pour les requêtes DNS (voir plus haut) sont-elles correctes?

A plusieurs endroits dans ton second message, comme par exemple :

Qu’entends-tu par “gérer les requêtes DNS” ?
La vm2, comme toute machine, envoie évidemment des requêtes DNS au serveur défini dans /etc/resolv.conf, personne ne va les envoyer à sa place.

Je pense que la confusion vient de ma méconnaissance de la gestion des requêtes DNS.

Je m’explique: vu que la vm2 (client) est connectée uniquement à un réseau interne, et qu’elle communique avec internet seulement grâce au FORWARD permis par les règles iptables de la vm1 (routeur), j’en déduis que son traffic est en réalité résolu par la vm1 (routeur), qui reçoit ses requêtes par le réseau interne, les forwarde sur internet, puis les redirige sur la vm2. C’est donc la vm1 (routeur) qui en réalité gère le traffic avec internet “externe”, et se charge de l’acheminer sur la vm2 (client). Est-ce que jusque là ma compréhension est correcte?

Partant de là, je pensais que les requêtes DNS étaient également assurées par la vm1 (routeur), qui s’en chargeait pour le compte de la vm2 (client). Ce n’est apparemment pas le cas, la vm2 essayant toujours de résoudre elle-même les requêtes DNS.

D’où ma question: comment faire pour que les requêtes DNS soient résolues par la vm1 et pas par la vm2? Et à quoi servent exactement les deux dernières règles que j’ai ajoutées dans mes iptables:

iptables -t nat -A PREROUTING -i enp0s8 -p udp --dport 53 -j  DNAT --to-destination 10.0.2.3
iptables -t nat -A PREROUTING -i enp0s8 -p tcp --dport 53 -j DNAT --to-destination 10.0.2.3

Sans aucun doute. Pourtant le protocole DNS en lui-même n’a pas grand-chose de particulier : il s’agit juste d’un protocole client-serveur comme beaucoup d’autres : HTTP, FTP, SSH, NTP… Le client envoie une requête à un serveur, le server renvoie la réponse au client. Exemple de dialogue DNS :

client à serveur : Q. quelle est l’adresse IP de www.example.com ?
serveur à client : R. www.example.com a pour adresse IP 192.0.2.67

La seule particularité par rapport aux autres protocoles client-serveur est qu’étant donné son rôle-clé (la résolution de noms) il s’agit d’un protocole d’infrastructure utilisé conjointement avec les autres protocoles.

Cette situation n’a rien d’exceptionnel. Il en est de même de la plupart des machines sur internet, du PC d’un utilisateur connecté derrière une box internet, au serveur web d’un hébergeur. Chacun est connecté à un réseau local connecté à d’autres réseaux via des routeurs. C’est cela qui constitue internet.

Cette phrase ne veut rien dire. On ne résoud pas le trafic. On résoud un nom de domaine, on route des paquets IP.

Un routeur ne reçoit pas de requête. Il ne sait pas ce que c’est. Il reçoit et route des paquets IP.

Faudrait savoir : il les forwarde sur internet ou les redirige sur la vm2 ? Ce sont des directions opposées.

Pas seulement la vm1 mais tous les routeurs amont sur le chemin entre la source et la destination.
Et pourquoi “en réalité” ? Il y a toujours un ou plusieurs routeurs entre une source et une destination, sauf lorsqu’elles sont dans le même réseau local. Le premier routeur n’a pas un rôle plus important que les autres.

“Assurer les requêtes DNS”, ça ne veut rien dire. Si tu veux dire “répondre aux requêtes DNS”, c’est la fonction d’un serveur DNS, pas d’un routeur. Ta confusion est peut-être entretenue par le fait que la plupart des box internet et “routeurs” domestiques assurent aussi la fonction de serveur DNS (ou plutôt simple relais vers un vrai serveur DNS, mais peu importe pour le client). Mais c’est une fonction additionnelle indépendante du routage.

Ça non plus, ça ne veut rien dire. Il faut être deux dans une résolution DNS : un client et un serveur DNS.

Installer un serveur DNS récursif sur vm1.

A rien, si tu ne mets pas n’importe quoi dans le fichier /etc/resolv.conf des VM clientes.
Concrètement, elles redirigent les connexions TCP et UDP à destination du port 53 (donc les requêtes DNS) reçues par le routeur vers l’adresse IP 10.0.2.3. Si vm1 envoie déjà les requêtes DNS à cette adresse, ces règles sont sans effet.

Note qu’un fichier /etc/resolv.conf vide est interprété par le résolveur local comme équivalent à :

nameserver 127.0.0.1

c’est-à-dire que le résolveur local suppose qu’il y a un serveur DNS local installé sur la machine elle-même.

Merci beaucoup pour tes réponses détaillées et pour le temps que tu consacres à mes questions. Vraiment, j’apprécie, d’autant plus que je me rends bien compte du caractère confus et approximatif de ce que j’écris. Comme tu peux t’en rendre compte, je ne suis pas informaticien et le peu que j’ai appris c’est sur le tas et en autodidacte et sur internet, d’où parfois ma difficulté à exprimer précisément certains concepts.

Ca paraît anodin, mais en fait c’est très important d’employer le vocabulaire approprié, car je confonds des concepts très différents, comme la résolution et le routage, et du coup certaines phrases ne veulent rien dire et il faut un peu lire entre les lignes.

J’ai bien lu toutes tes réponses, et plutôt que de les reprendre une à une, je te propose de t’exposer ce que j’ai compris jusqu’à maintenant, toute correction et remarque étant bienvenue.

On a donc une machine virtuelle cliente (vm2), qui est connectée à un réseau privé (intnet), sur lequel est également connecté un routeur (vm1), qui lui a une autre interface connectée à internet. Quand la vm2 cherche à se connecter à un service sur internet, pour faire simple, par exemple en ouvrant firefox et en entrant google.fr, son traffic transite par le serveur (qui est indiqué comme sa “gateway” dans /etc/network/interfaces) qui va router (et non “résoudre”, terme qui ne veut rien dire ici) ses paquets IP sur google.fr grâce aux règles iptables et à l’ip forwarding. Les paquets IP vont revenir en sens inverse, par le routeur (vm1), et arriver sur le client (vm2). En fait, j’ai virtualisé ce qui se passe quand on connecte une machine à un routeur physique normal. Jusque là j’ai bon?

Ce qui reste trouble pour moi, c’est la gestion du traffic DNS.

Je m’explique. Si j’ai bien compris, par défaut, une machine debian, quand elle ne connaît pas l’adresse IP du nom recherché (ex: google.fr), va d’abord interroger le fichier “/etc/hosts", puis, si elle n’y trouve rien de pertinent, va interroger le fichier “/etc/resolv.conf”, ce dernier contenant l’adresse IP du serveur où envoyer la requête de résolution DNS. Dans une configuration “normale” (machine physique debian connectée à un routeur physique), l’IP contenue dans le fichier /etc/resolv.conf est en général celle du routeur (par exemple 192.168.1.1), qui relaie les requêtes DNS sur un vrai serveur DNS (pour reprendre ce que tu as écrit: " la plupart des box internet et “routeurs” domestiques assurent aussi la fonction de serveur DNS (ou plutôt simple relais vers un vrai serveur DNS, mais peu importe pour le client)” Est-ce bien correct?

Dans mon cas, la vm2 a pour adresse par défaut “10.0.2.3”, qui est l’adresse du routeur virtuel de l’interface NAT de VirtualBox. Si je n’utilise pas les deux dernières règles iptables sur la vm1:

iptables -t nat -A PREROUTING -i enp0s8 -p udp --dport 53 -j  DNAT --to-destination 10.0.2.3
iptables -t nat -A PREROUTING -i enp0s8 -p tcp --dport 53 -j DNAT --to-destination 10.0.2.3

Il ne se passe rien, la vm2 est incapable de résoudre les requêtes DNS (est-ce correct d’utiliser ces termes?). Si j’applique ces deux dernières règles dans la vm1, la vm2 parvient à résoudre correctement les requêtes DNS, et j’en déduis que la raison en est que ces requêtes sont routées sur la vm1, qui elle-même est connectée à 10.0.2.3 (qui est son propre routeur). Est-ce que ma compréhension est correcte?

Tu dis que ces règles ne servent à rien dans mon cas de figure: “elles redirigent les connexions TCP et UDP à destination du port 53 (donc les requêtes DNS) reçues par le routeur vers l’adresse IP 10.0.2.3. Si vm1 envoie déjà les requêtes DNS à cette adresse, ces règles sont sans effet”, pourtant si ne les applique pas, il ne se passe rien. Pourquoi? Est-ce que parce que 10.0.2.3 ne correspond à rien sur la vm2, qui est connectée uniquement à 192.168.42.10? Pourtant, si je remplace 10.0.2.3 par 192.168.42.10 (adresse du routeur, vm1), il ne se passe rien non plus sans ces règles (toujours pas de résolution de noms), alors pourquoi?

Et aussi, ce que je ne comprends pas, c’est pourquoi le traffic DNS a besoin de règles à part? L’ensemble du traffic est routé grâce à ces trois règles iptables:

iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
iptables -A FORWARD -i enp0s3 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i enp0s8 -o enp0s3 -j ACCEPT

alors pourquoi le traffic DNS a-t-il “besoin” de règles supplémentaires, avec précision du port 53? Même lorsque je remplace 10.0.2.3 par 192.168.42.10 (adresse du routeur, vm1) dans le fichier/etc/resolv.conf de la vm2, ce qui devrait pourtant lui dire de forwarder les requêtes DNS directement sur le routeur? Pourquoi le trafic DNS n’est-il pas “inclus” dans le reste du traffic et tout simplement routé directement vers la vm1 (routeur)? Est-ce une particularité de debian? Où est-ce que ce sont mes règles iptables qui pourraient être améliorées, voire changées complètement? Un système debian a-t-il toujours besoin d’avoir une adresse où envoyer les requêtes DNS, même si son traffic est routé par une autre machine?

Le routeur. Pour le reste, jusqu’ici c’est bon.

Oui.
Voire d’autres sources de résolution de nom (mDNS, NBNS…). Cf. la ligne “hosts:” du fichier /etc/nsswitch.conf.

Je persiste, ce n’est pas normal si le fichier /etc/resolv.conf de vm2 contient déjà

nameserver 10.0.2.3

Edit : j’aurais bien envie de faire une capture du trafic entre vm1 et vm2 pour voir ce qui se passe.

Non, rien à voir. Comme je l’ai déjà écrit, routage et résolution DNS sont indépendants. Les paquets DNS sont routés comme n’importe quels autres paquets IP, ils n’ont pas de traitement particulier.

10.0.2.3 ne correspond pas à rien pour vm2. Cette adresse correspond à la route par défaut dans sa table de routage, qui lui indique que l’adresse est joignable via le routeur 192.168.42.10. Tu peux afficher la table de routage avec :

ip route

Ça, c’est normal. 192.168.42.10 n’est pas un serveur DNS. Les règles iptables DNAT redirigent les paquets de requête DNS entrants vers 10.0.2.3, donc au lieu d’être traités par vm1 (en tant que routeur mais hôte, puisqu’elle en est la destination) et jetés puisque vm1 ne fait pas tourner de serveur DNS, 10.0.2.3, les paquets sont redirigés vers 10.0.2.3 qui est un serveur DNS. Tu pourrais mettre n’importe quelle adresse hors du réseau local dans /etc/resolv.conf et ça ferait la même chose.

PS : si tu n’as pas défini la politique par défaut de la chaîne FORWARD à DROP, les deux règles de cette chaîne ne servent à rien puisque la chaîne autorise déjà tout par défaut.

Merci de ta réponse!

Pour info, dans les exemples qui suivent, le réseau interne est cette fois configuré sur 192.168.40.0 au lieu de 192.168.42.0, mais ça ne change rien au reste…

Sur la vm2 (client), ip route renvoie

default via 192.168.40.10 dev enp0s3 onlink 
192.168.0.0/18 dev enp0s3 proto kernel scope link src 192.168.40.11 

Concernant les règles iptables, effectivement je n’ai pas de policy DROP, la policy est ACCEPT par défaut, mais alors pourquoi si je n’active pas ces règles de FORWARD, la vm2 n’envoie aucun trafic à la vm1? Sans ces règles, il ne se passe rien du tout, je ne peux même pas “pinger” 8.8.8.8…

Concernant les requêtes DNS et le fichier /etc/resolv.conf, j’ai refait des tests, et effectivement tu as raison, les deux règles suivantes ne servent à rien:

iptables -t nat -A PREROUTING -i enp0s8 -p udp --dport 53 -j  DNAT --to-destination 10.0.2.3
iptables -t nat -A PREROUTING -i enp0s8 -p tcp --dport 53 -j DNAT --to-destination 10.0.2.3

Les règles de FORWARD suffisent à router les requêtes DNS, j’ai dû m’emmêler les pinceaux quelque part quand j’affirmais le contraire…

Pour le reste, pour y voir plus clair, j’ai fait des tests en capturant le trafic avec wireshark sur les deux vms pour voir ce qui se tramait. Je fais à chaque fois

curl google.fr

dans un terminal de la vm2 (client) et je compare les résultats sur chaque interface, une fois sans les règles de FORWARD dans la vm1 (routeur), et une fois avec, et en variant l’adresse de résolution DNS dans /etc/resolv.conf de la vm2 (client).

Résultats

Test 1: aucune règle iptables sur la vm1 (routeur), la vm2 a 10.0.2.3 dans /etc/resolv.conf

  • Wireshark, vm2 (client):

On voit que la vm2 envoie des requêtes (8) DNS à 10.0.2.3, MAIS elle les envoie à l’adresse MAC du routeur, donc elle a bien “compris” qu’elle doit router ses paquetets par le routeur. Cela dit, il ne se passe rien, les adresses DNS ne sont pas résolues et la vm2 ne reçoit aucune réponse du routeur. La commande curl renvoie immanquablement:

curl: (6) Could not resolve host: ipinfo.io

  • Wireshark, vm1 (routeur), enp0s8 (interface interne connectée à vm2):

On voit les requêtes DNS exactement comme sur la vm2, c’est-à-dire venant de 192.168.42.11 à destination de 10.0.2.3. Mais toujours pas de réponse.

  • Wireshark, vm1 (routeur), enp0s3 (interface connectée au NAT de VirtualBox, donc internet):

On voit toujours les mêmes paquets DNS, mais cette fois on voit aussi du trafic ARP provenant de 10.0.2.2 cherchant à savoir qui a l’adresse 192.168.42.11. En faisant un routej’ai réalisé que le routeur par défaut du NAT VirtualBox n’était pas 10.0.2.3, mais 10.0.2.2… Alors pourquoi par défaut le NAT de VirtualBox génère l’adresse 10.0.2.3 dans /etc/resolv.conf? Mystère…

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         10.0.2.2        0.0.0.0         UG    0      0        0 enp0s3
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 enp0s3
192.168.0.0     0.0.0.0         255.255.192.0   U     0      0        0 enp0s8

Test 2: aucune règle iptables sur la vm1 (routeur), la vm2 a cette fois dans /etc/resolv.conf l’adresse du routeur (vm1, 192.168.40.10):

  • Wireshark, vm2 (client):

le client envoie des requêtes DNS au routeur qui sont cette fois résolues, par contre il n’arrive pas à recevoir le trafic TCP (c’est en tout cas ainsi que je le comprends). Je n’arrive pas à pinger non plus
d’adresse externes… Cette fois, la réponse de la commande curl est:

curl: (7) Failed to connect to google.fr port 80: Connection timed out

  • Wireshark, vm1 (routeur), enp0s8 (interface interne connectée à vm2):

Même résultat que dans la vm2:

  • Wireshark, vm1 (routeur), enp0s3 (interface connectée au NAT de VirtualBox, donc internet):

On voit les paquets TCP, mais pas les requêtes DNS… Pourquoi?? Je ne comprends pas comment 192.168.40.10 les envoie “magiquement” sur le net sans que l’interface enp0s3 (10.0.2.15) connectée au net ne s’en apercoive??

Test 3: règles de FORWARD appliquées sur la vm1 (routeur), la vm2 a 10.0.2.3 dans /etc/resolv.conf :

iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
iptables -A FORWARD -i enp0s3 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i enp0s8 -o enp0s3 -j ACCEPT
  • Wireshark, vm2 (client):

Cette fois, cela fonctionne: les requêtes DNS sont bien routées sur 10.0.2.3, et les réponses reçues. Puis du trafic TCP/HTTP qui correspond à la réponse de la commande curl.

  • Wireshark, vm1 (routeur), enp0s8 (interface interne connectée à vm2):

Le résultat est exactement le même que sur la vm2 client:

  • Wireshark, vm1 (routeur), enp0s3 (interface connectée au NAT de VirtualBox, donc internet):

Même résultat que précédemment, sauf que le trafic passe cette fois de 10.0.2.15 (adresse ip interne NAT) à 10.0.2.3. Logique, car le routeur route le trafic en provenance et à destination du client sur le net,
donc du point de vue de l’interface du routeur connectée au NAT (enp0s3, 10.0.2.15), c’est comme si le trafic partait de lui-même (correct?).

Test 4: règles de FORWARD appliquées sur la vm1 (routeur), la vm2 a cette fois 192.168.40.10 dans /etc/resolv.conf :

  • Wireshark, vm2 (client):

Même résultat que ci-dessus avec 10.0.2.3, sauf que cette fois tout passe par 192.168.40.10:

  • Wireshark, vm1 (routeur), enp0s8 (interface interne connectée à vm2):

Même résultat que dans la vm2:

  • Wireshark, vm1 (routeur), enp0s3 (interface connectée au NAT de VirtualBox, donc internet):

Comme précédemment, on voit le trafic TCP/HTTP, mais pas le trafic DNS!! Pourquoi??

En résumé:

  • Les règles de routage du port 53 pour le DNS sont effectivement superflues (déjà une chose de clarifié)

  • Selon toi, les règles de FORWARD sur le routeur (vm1) sont inutiles, puisque leur policy est ACCEPT par défaut, pourtant le routage ne fonctionne pas si je ne lui dis pas explicitement de FORWARD les paquets
    en provenance de la vm2 (client), pourquoi?

  • Lorsque je remplace l’adresse NAT par défaut (10.0.2.3) par l’adresse du routeur (192.168.40.10) dans /etc/resolv.conf du client (vm2), le trafic DNS n’est pas visible sur l’interface connectée à internet du routeur, pourquoi?

  • Comment 192.168.40.10, l’IP du serveur (vm1) du réseau interne est-elle capable de résoudre des requêtes DNS alors que le réseau interne 192.168.40.0 n’a pas accès à internet, et visiblement sans que l’interface connectée au net (sous-réseau 10.0.2.0) ne s’en aperçoive?? Gros mystère ici…

Avant tout, félicitations pour ce travail de capture et d’analyse. Je pense que cela aide beaucoup à appréhender et clarifier de quelle façon se passent les communications sur un réseau.

C’est l’illustration que les fonctions de routeur et de serveur DNS sont indépendantes l’une de l’autre. Ici elles sont assurées par des adresses IP différentes. 10.0.2.2 est le routeur, 10.0.2.3 est le serveur DNS.

J’ai dit que les règles ACCEPT de la chaîne FORWARD étaient inutiles. Cela n’incluait pas la règle MASQUERADE qui se trouve dans la chaîne POSTROUTING de la table nat, qui est indispensable car le “routeur” amont (le NAT de VirtualBox) ne sait pas comment router correctement la plage d’adresses du réseau interne.

Une parenthèse à ce sujet : tes captures de trafic ont montré que le pseudo-routeur NAT virtualBox 10.0.2.2 envoyait quand même des requêtes ARP pour les adresses du réseau interne. Le routeur vm1 pourrait y répondre en activant le proxy ARP sur l’interface externe (/proc/sys/net/ipv4/conf/enp0s3/proxy_arp=1). De cette façon, la règle MASQUERADE ne serait plus nécessaire. Néanmoins c’est une particularité du pseudo-routeur NAT VirtualBox. Un véritable routeur, ou une box internet, ne se comporterait pas ainsi sans une route explicite.

Concernant les deux dernières questions, ma seule explication est que vm1 fait tourner un serveur DNS local (bind9, unbound, dnsmasq…). Tu ne vois pas les requêtes DNS relayées vers l’extérieur parce que la réponse est déjà dans le cache du serveur local. Cela devrait se voir dans les sockets en écoute affichées par :

netstat -ntulp4

Si tu essaies avec un nom de domaine que tu n’as encore jamais demandé, tu devrais voir les requêtes DNS relayées.

PS : note qu’avec le masque 255.255.192.0 que tu as choisi, le réseau n’est pas 192.168.40.0 mais 192.168.0.0 (jusqu’à 192.168.63.255) comme on peut le voir dans la table de routage.

Merci de ta réponse, ça devient de plus en plus clair…

Je reprends:

Concernant les règles FORWARD d’iptables:

Effectivement, les règles FORWARD sont inutiles, si j’utilise uniquement la chaîne MASQUERADE, cela fonctionne également! Ca, c’est réglé :grinning:

Concernant les deux dernières questions (“Comment 192.168.40.10, l’IP du serveur (vm1) du réseau interne est-elle capable de résoudre des requêtes DNS alors que le réseau interne 192.168.40.0 n’a pas accès à internet, et visiblement sans que l’interface connectée au net (sous-réseau 10.0.2.0) ne s’en aperçoive?”…)

Effectivement, après vérification j’ai bien un service bind actif sur la vm1: j’avais installé le paquet bind9 sans persévérer et du coup j’avais oublié son existence…

Au démarrage, netstat -ntulp4 sur la vm1 (routeur) retourne:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 10.0.2.15:53            0.0.0.0:*               LISTEN      452/named           
tcp        0      0 192.168.40.10:53        0.0.0.0:*               LISTEN      452/named           
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      452/named           
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      478/sshd            
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      452/named           
tcp        0      0 0.0.0.0:6010            0.0.0.0:*               LISTEN      552/sshd: root@pts/ 
udp        0      0 10.0.2.15:53            0.0.0.0:*                           452/named           
udp        0      0 192.168.40.10:53        0.0.0.0:*                           452/named           
udp        0      0 127.0.0.1:53            0.0.0.0:*                           452/named           
udp        0      0 0.0.0.0:68              0.0.0.0:*                           506/dhclient  

le process 452, bizarrement appelé named, est en fait bind!:

root@host:~# ps aux | grep named
bind       452  0.0  0.8 238188 34308 ?        Ssl  13:43   0:00 /usr/sbin/named -f -u bind
root       619  0.0  0.0  12784   948 pts/0    S+   13:52   0:00 grep named

au passage, si tu pouvais m’expliquer pourquoi bind se met en LISTEN sur toutes ces adresses? c’est normal?

si je tente une requête qui ne devrait cette fois pas être dans le cache de bind (avec 192.168.40.10 dans /etc/resolv.conf de la vm2 et les règles iptables activées sur la vm1):

curl debian-fr.org

Sur la vm1 (routeur), on voit une requête DNS envoyée par 10.0.2.15 (adresse IP interne du routeur vm1 sur son interface exposée au net enp0s3):

J’en déduis que les requêtes passent par 10.0.2.15 et non par 10.0.2.3 (serveur DNS virtualbox) car la vm2 a fait une requête à 192.168.40.10, qui héberge son propre serveur DNS (bind), et donc se passe de 10.0.2.3, correct?

Maintenant, si je refais la même commande curl avec la même configuration:

curl debian-fr.org

Sur la vm1 (routeur), on voit qu’il n’y a plus de requêtes DNS, uniquement du trafic TCP/HTTP, car le serveur bind a déjà “caché” l’adresse IP de debian-fr.org, c’est bien ça?

Encore un test: cette fois je “kille” le process de bind sur la vm1, et je refais une requête avec la même configuration, mais cette fois sans bind pour gérer les requêtes DNS sur la vm1 (routeur):

vm1 (serveur):

root@host:~# kill 452
root@host:~# netstat -ntulp4
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      478/sshd            
tcp        0      0 0.0.0.0:6010            0.0.0.0:*               LISTEN      552/sshd: root@pts/ 
tcp        0      0 0.0.0.0:6011            0.0.0.0:*               LISTEN      686/sshd: root@pts/ 
udp        0      0 0.0.0.0:68              0.0.0.0:*                           506/dhclient 

vm2 (client):

curl debian-fr.org

Sur la vm2 (client), on voit que les requêtes n’aboutissent plus (port unreachable!):

Et la commande curl debian-fr.org renvoie:

curl: (6) Could not resolve host: debian-fr.org

Tandis que sur la vm1 (routeur), interface enp0s3 connectée au net, on ne voit aucun trafic:

Normal, car les requêtes sont envoyées sur 192.168.40.10, qui n’a plus de serveur DNS bind (désactivé), et qui n’est pas relié au net… Correct?

Dernière capture: même requête, mêmes conditions, mais cette fois on regarde l’interface enp0s8 de la vm1 (routeur), qui est connectée à la vm2 (client) en intranet:

Même résultat qu’en observant depuis la vm2 (client): il n’y a plus de serveur DNS sur 192.168.40.10, donc les requêtes ne peuvent pas être résolues.

EDIT: j’ai ajouté le petit résumé ci-dessous

Résumé de ce que j’ai compris (est-ce correct?)

  • Si le routeur a le service bind activé et que son adresse ip (192.168.40.10) est indiquée comme serveur DNS dans /etc/resolv.conf de la vm1, il gère les requêtes DNS. Lorsqu’il ne connaît pas l’adresse du nom recherché, il envoie une requête à internet en passant par l’interface connectée au net (logique), on peut la voir passer en capturant le trafic sur cette interface

  • Lorsqu’il connaît déjà l’adresse du nom recherché et qu’il l’a mis en cache, il se contente de renvoyer la réponse au client, il ne fait plus de requêtes sur le net. C’est pour cette raison qu’on ne voit plus de trafic DNS sur son interface connectée au net (enp0s3)!

  • Si le service bind est désactivé, les requêtes échouent, 192.168.40.10 n’étant plus capable de résoudre les requêtes DNS

BIND = Berkeley Internet Name Daemon
named = name daemon

Oui, c’est comme ça. BIND ouvre une socket séparée pour chaque adresse IPv4 locale sur laquelle il écoute. Par contre il ouvre une seule socket pour toutes les adresses IPv6 locales.

Dans sa configuration par défaut, BIND fait la résolution récursive complète lui-même en partant des serveurs racine jusqu’aux serveurs faisant autorité pour le nom de domaine demandé. On peut le configurer pour faire suivre les requêtes vers un ou plusieurs autres serveurs récursifs avec l’option “forwarders”.

Par contre j’attire ton attention sur le fait que la présence de BIND sur vm1 n’implique pas forcément que vm1 va l’utiliser pour la résolution DNS pour les programmes autres que BIND . Comme pour vm2, vm1 utilise les serveurs DNS définis dans son /etc/resolv.conf. Si c’est 10.0.2.3, il utilise le serveur DNS de VirtualBox. Si c’est une de ses adresses locales (10.0.2.15, 192.168.40.10, 127.0.0.1 ou rien, qui est interprété comme 127.0.0.1), alors il utilise le serveur DNS local.

Alors ça c’est curieux, car le serveur DNS dans /etc/resolv.conf de la vm1 (routeur) est bien 10.0.2.3, donc celui de VirtualBox. Pourtant, quand BIND est activé, les requêtes DNS ne semblent plus passer par lui (cf. captures d’écran wireshark). Se pourrait-il que l’adresse du routeur 192.168.40.10 dans /etc/resolv.conf de la vm2 (client) “force” la vm1 à utiliser son serveur BIND plutôt que le serveur VirtualBox, pourtant indiqué dans son fichier /etc/resolv.conf?

Pour le reste, est-ce qu’il te semble que ma compréhension de l’ensemble est correcte?

Non. Les programmes d’une machine n’utilisent que le fichier resolv.conf local de cette machine.

Sauf erreur de ma part, tous les tests que tu as faits précédemment l’ont été en exécutant un programme (curl, mais ça pourrait être ping ou un autre) sur vm2. Ce programme utilise le fichier /etc/resolv.conf de vm2, qui dit d’envoyer les requêtes DNS à l’adresse 192.168.40.10, sur laquelle BIND qui tourne sur vm1 écoute.

Les programmes exécutés sur vm1 utilisent le fichier /etc/resolv.conf de vm1, à l’exception de BIND qui a sa propre configuration et ne n’utilise pas. Donc un programme exécuté sur vm1 va interroger l’adresse figurant dans le fichier resolv.conf local, 10.0.2.3 et non BIND. Tu peux tester.

Oui, c’est bien ce que joulais dire: sur la vm2 (client), curl va envoyer ses requêtes sur 192.168.40.10, la vm1 (routeur), sur laquelle tourne BIND.

Merci beaucoup pour toutes ces réponses et ton aide en tout cas! J’ai bien avancé dans ma compréhension.