Packets forwarding

Published: 28-06-2015

Updated: 20-11-2018

By: Maxime de Roucy

tags: network sysctl system

Quelques notes concernant le routage de paquets (Packets Forwarding).

Je ne m’intéresserai ici qu’au routage IPv4 (pour l’instant).

Le routage se configure via l’outil sysctl ou via le pseudo système de fichier /proc. Il peut aussi se configuré via systemd-networkd, nous y viendrons ensuite.

Plusieurs options sont disponibles (je n’ai gardé que celle qui nous intéresse) :

root@laptop # sysctl -a | grep forward
net.ipv4.ip_forward = 0
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth1.forwarding = 0

Ces options sont décrites dans la documentation du noyau.
PS: Je détaille d’autres éléments de cette documentation sur la page IP-sysctl.

Si j’extraie les parties qui nous concerne (sachant que 0 = disabled et 1 = enabled) :

Bref, perso je ne trouve pas ça très claire…

Du coup je vais faire quelques tests.

root@laptop # sysctl -w net.ipv4.ip_forward=0

root@laptop # sysctl -a | grep 'ipv4.*\.forwarding'
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth1.forwarding = 0

root@laptop # sysctl -w net.ipv4.ip_forward=1

root@laptop # sysctl -a | grep 'ipv4.*\.forwarding'
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.eth0.forwarding = 1
net.ipv4.conf.eth1.forwarding = 1

Changer la valeur de « net.ipv4.ip_forward » permet de changer celle de tous les « net.ipv4.….forwarding ».

Comme il est indiqué dans la documentation, changer la valeur de « net.ipv4.ip_forward » : * de 1 (ou autre) à 0 : reset tous les autres paramètres à leurs valeurs par défaut en considérant que la machine doit se comporter comme un “host” (définit dans le RFC1122) * de 0 à 1 (ou autre) : reset tous les autres paramètres à leurs valeurs par défault en considérant que la machine doit se comporter comme un “router” (définit dans le RFC1812)

Ce qui se vérifie :

root@laptop # sysctl -a | grep 'ipv4.*\.forwarding'
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth1.forwarding = 0

root@laptop # sysctl -w net.ipv4.conf.default.forwarding=1
net.ipv4.conf.default.forwarding = 1

root@laptop # sysctl -a | grep 'ipv4.*\.forwarding'
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth1.forwarding = 0

root@laptop # sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

root@laptop # sysctl -a | grep 'ipv4.*\.forwarding'
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.eth0.forwarding = 1
net.ipv4.conf.eth1.forwarding = 1

root@laptop # sysctl -w net.ipv4.ip_forward=0
net.ipv4.ip_forward = 0

root@laptop # sysctl -a | grep 'ipv4.*\.forwarding'
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth1.forwarding = 0

J’ai aussi essayé de fixer le paramètre à 0 ou à 1 alors qu’il avait déjà cette valeur. Quelques soit la configuration, quant on change « net.ipv4.ip_forward » de 1 à 0 tout passe à 0, et quant on change de 0 à 1 tout passe à 1.

C’est le changement de valeur qui est important, si « net.ipv4.ip_forward=0 » et que le routage est activé sur certaines interfaces. On ne peut pas remettre tous à 0 en fixant « net.ipv4.ip_forward » à 0. Il faut d’abord le passer à 1 puis revenir à 0.

J’ai vérifié s’il y avait des changement sur d’autre paramètre que les « net.ipv4.conf.….forwarding » :

root@laptop # sysctl -w net.ipv4.ip_forward=0
net.ipv4.ip_forward = 0

root@laptop # sysctl -a | grep '^net' | grep -v 'net\.ipv4\.conf\..*\.forwarding' > /tmp/1 

root@laptop # sysctl -w net.ipv4.ip_forward=1                                             
net.ipv4.ip_forward = 1

root@laptop # sysctl -a | grep '^net' | grep -v 'net\.ipv4\.conf\..*\.forwarding' > /tmp/2
32c32
< net.ipv4.conf.all.accept_redirects = 1
---
> net.ipv4.conf.all.accept_redirects = 0
211c211
< net.ipv4.ip_forward = 0
---
> net.ipv4.ip_forward = 1

Il est normal que la valeur de « accept_redirects » change :

accept_redirects : Accept ICMP redirect messages. accept_redirects for the interface will be enabled if :

or

Si je refait exactement les mêmes tests en changeant « net.ipv4.conf.all.forwarding » j’obtient exactement le même résultat. De plus « net.ipv4.ip_forward » change avec « net.ipv4.conf.all.forwarding ». « net.ipv4.ip_forward » semble être un alias à « net.ipv4.conf.all.forwarding ».

Quand « net.ipv4.conf.all.forwarding=0 » certaines interface peuvent quand même activé le routage. Idem, quand « net.ipv4.conf.all.forwarding=1 » on peut quand même déactivé le routage sur certaines interface, et « net.ipv4.conf.all.forwarding » reste à 1.

Même le routage est complèttement désactivé, une machine connecté à l’interface eth0 peut pinguer l’IP de l’interface eth1 (pour peut que les tables de routage soit correctement configuré). En revanche elle ne peut pas pinguer une autre machine connecté à l’interface eth1.

Maintenant que ce passe-t-il si désactive le routage sur toutes les interface sauf une.

root@laptop # sysctl -a | grep -e 'ipv4.*\.forwarding' -e 'net.ipv4.ip_forward '
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth1.forwarding = 0
net.ipv4.ip_forward = 0

root@laptop # sysctl -w net.ipv4.conf.eth0.forwarding=1
net.ipv4.conf.eth0.forwarding = 1

root@laptop # sysctl -a | grep -e 'ipv4.*\.forwarding' -e 'net.ipv4.ip_forward '
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.eth0.forwarding = 1
net.ipv4.conf.eth1.forwarding = 0
net.ipv4.ip_forward = 0

Depuis une machine connecté à l’interface eth0, j’essaie de pinguer une machine connecté à l’interface eth1. On n’a l’impression que le ping ne passe pas mais en fait, seul les réponse ne passe pas. En effet les requêtes sont bien routé car elle arrive sur une interface sur laquel le routage est activé (eth0), mais les réponse (qui arrive sur eth1) ne sont pas routées car « net.ipv4.conf.eth1.forwarding = 0 ». (Ceci a été vérifié avec Wireshark).

La valeur de « net.ipv4.conf.default.forwarding » permet de spécifier quelle sera la valeur de « net.ipv4.conf.….forwarding » pour toutes les nouvelles interfaces.

Le service systemd-networkd permet de spécifier via le paramètre IPForward (par défaut à « no ») si le routage doit être activé ou non sur une interface.

IPForward=

Configures IP forwarding for the network interface. If enabled incoming packets on the network interface will be forwarded to other interfaces according to the routing table. Takes either a boolean argument, or the values “ipv4” or “ipv6”, which only enables IP forwarding for the specified address family, or “kernel”, which preserves existing sysctl settings. This controls the net.ipv4.conf..forwarding and net.ipv6.conf..forwarding sysctl options of the network interface (see ip-sysctl.txt for details about sysctl options). Defaults to “no”.

Note: unless this option is turned on, or set to “kernel”, no IP forwarding is done on this interface, even if this is globally turned on in the kernel, with the net.ipv4.ip_forward and net.ipv4.ip_forward sysctl options.

Pour toutes les interfaces gérées par systemd-networkd et pour lesquelles l’option « IPForward » n’est pas à « kernel », vous ne pouvez pas gérer le routage via « /etc/sysctl.d/ ». Une interface est gérée par systemd-networkd si elle correspont à une clause [Match] d’un des fichier « .network » du dossier « /etc/systemd/network ».

Par exemple, si via systemd-networkd, je créé une interface virtuel « eth2 » pour laquelle je ne spécifie pas « IPForward ». Sachant que « IPForward » est à « no » par défaut. Même si j’ai précédemment fixé « net.ipv4.conf.all.forwarding » et « net.ipv4.conf.default.forwarding » à 1, lorsque mon interface sera créée « net.ipv4.conf.eth2.forwarding » sera à 0.