Bridge

Published: 06-07-2015

Updated: 15-03-2017

By: Maxime de Roucy

tags: bridge network

Quelques notes rapides sur les bridges sous GNU/Linux.

Un bridge permet en quelques sorte de transformer sont PC en switch. Quand on lie plusieurs interfaces à un bridge il ne faut pas imaginer qu’on connecte ces interfaces à un switch mais qu’on transforme sa machine en un switch manageable dont les ports sont ces interfaces. Les interfaces liées à un bridge n’ont d’ailleur pas d’IP associé et n’utilise pas leurs adresse MAC.

Source : Wiki Archlinux

Création

Avec iproute2.

Création du bridge :

root@laptop # ip link add name br0 type bridge
root@laptop # ip link set br0 up

Pour ajouter l’interface eth0 dans ce bridge vous devez d’abord supprimer les IP qui y sont associés.

Une interface liée à un bridge ne doit pas avoir d’adresse IP, de la même façon que les ports d’un switch n’ont pas d’adresse IP ou de MAC. En revanche un switch manageable possède une adresse MAC et une IP, ce sont la MAC et l’IP associé au bridge.

En théorie, en plus de supprimer l’adresse IP des interface liées à un bridge, on devrais aussi pouvoir supprimer leurs adresse MAC. En pratique je n’ai pas trouvé de moyen de le faire (j’ai aussi demandé à des « experts », qui n’ont pas sut me dire comment faire). Le fait que ces interfaces aient toujours leurs adresses MAC n’est pas grave, le principal c’est qu’elle ne répondent pas aux requêtes ARP. En fait le bridge utilise l’adresse MAC la plus petit de ces interfaces interne.

Activation du mode promiscuous sur l’interface eth0, permet de configurer la carte pour ne pas rejeter les paquets qui sont marqué à destination d’une adresse MAC qui n’est pas la sienne (eg. l’adresse MAC de l’interface bridge). En gros tous les paquets qui arrivent par cette interface sont remontés au noyaux. Ça permet d’une certaine façon de simuler la suppression de l’adresse MAC de l’interface eth0.

root@laptop # ip link set promisc on dev eth0

Activation de l’interface

root@laptop # ip link set up dev eth0

Ajout de l’interface eth0 dans le bridge

root@laptop # ip link set master br0 dev eth0

eth0 avec IP

Que ce passe t-il si une interface conserve son adresse IP alors qu’elle est liée à un bridge ?

L’interface « host0 » sur le host n°0 est liée physiquement (layer 1) à l’interface « host1 » sur le host n°1. L’interface « host1 » est bridgé sur le « br1 » sur le host n°1.

Sur le host n°0 :

host-0 # ip link show
2: host0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 66:9f:76:b2:31:5f brd ff:ff:ff:ff:ff:ff link-netnsid 0

host-0 # ip addr show
2: host0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 66:9f:76:b2:31:5f brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.0.1/24 scope global host0
       valid_lft forever preferred_lft forever
    inet6 fe80::649f:76ff:feb2:315f/64 scope link
       valid_lft forever preferred_lft forever

host-0 # ip route show
10.0.0.0/24 dev host0  proto kernel  scope link  src 10.0.0.1

host-0 # ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.085 ms

host-0 # arping 10.0.0.2
ARPING 10.0.0.2 from 10.0.0.1 host0
Unicast reply from 10.0.0.2 [52:81:B0:3A:00:7A]  0.588ms

Sur le host n°1 j’ai du modifier la table de routage ajouté par défaut à la création des adresse pour que le ping passe. Ces commandes ont donc été passé sur host n°1 avant celles exposées ci-dessus :

host-1 # ip route delete 10.0.0.0/24 dev host1
host-1 # ip route add    10.0.0.0/24 dev br1 src 10.0.0.2

J’ai aussi désactivé le routage sur les deux hosts.

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

Sur le host n°1 :

host-1 # ip link show
5: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
    link/ether 52:81:b0:3a:00:7a brd ff:ff:ff:ff:ff:ff
7: host1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br1 state UP mode DEFAULT group default qlen 1000
    link/ether 2a:27:80:df:57:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0

host-1 # ip addr show
5: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 52:81:b0:3a:00:7a brd ff:ff:ff:ff:ff:ff
    inet6 fe80::5081:b0ff:fe3a:7b/64 scope link
       valid_lft forever preferred_lft forever
7: host1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br1 state UP group default qlen 1000
    link/ether 2a:27:80:df:57:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.0.2/24 scope global host1
       valid_lft forever preferred_lft forever
    inet6 fe80::2827:80ff:fedf:570b/64 scope link
       valid_lft forever preferred_lft forever

host-1 # ip route show
10.0.0.0/24 dev br1  scope link  src 10.0.0.2

host-1 # ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.070 ms

host-1 # arping -I br1 10.0.0.1
ARPING 10.0.0.1 from 10.0.0.2 br1
Unicast reply from 10.0.0.1 [66:9F:76:B2:31:5F]  0.594ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)

host-1 # arping -I host1 10.0.0.1
ARPING 10.0.0.1 from 10.0.0.2 host1
Sent 1 probes (1 broadcast(s))
Received 0 response(s)

J’ajoute une adresse IP au bridge de host n°1, et je supprime la route créé précédemment :

host-1 # ip addr add 10.0.0.3/24 dev br1
host-1 # ip route delete 10.0.0.0/24 dev br1 scope link src 10.0.0.2
host-1 # ip route show
10.0.0.0/24 dev br1  proto kernel  scope link  src 10.0.0.3

Je vire les table ARP des deux host pour pas que ça fausse mes résultats.

host-0 # ip neigh flush dev host0
host-1 # ip neigh flush dev host1
host-1 # ip neigh flush dev br1

Puis sur le host n°0 :

host-0 # arping -I host0 10.0.0.2
ARPING 10.0.0.2 from 10.0.0.1 host0
Unicast reply from 10.0.0.2 [52:81:B0:3A:00:7A]  0.585ms

host-0 # arping -I host0 10.0.0.3
ARPING 10.0.0.3 from 10.0.0.1 host0
Unicast reply from 10.0.0.3 [52:81:B0:3A:00:7A]  0.585ms

host-0 # ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.055 ms

host-0 # ping 10.0.0.3
PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=0.055 ms

L’adresse MAC de l’interface « host1 » n’est jamais utilisée dans les échanges. C’est le bridge qui répond au requête ARP sur une IP qui normalement ne lui est pas directement associé, c’est comme si le bridge avait « pris » l’IP de l’interface qui lui est associée.

D’un autre coté j’ai du faire attention aux routes créées par défaut par le système pour faire fonctionner le ping et l’arping.

Même si ça à l’aire d’être plutôt bien géré je conseille de supprimer les adresses IP associées aux interfaces liées à un bridge.

Run

iproute2 contient un outil appelé bridge

List les bridge et les interfaces qui leurs sont associées :

root@laptop # bridge link show

Suppression

Avant de supprimer un bridge, retirer toutes les interface qui lui sont associées. Désactivé le mode « promiscuous » et placer l’interface en « down » pour revenir à l’état originel.

root@laptop # ip link set eth0 promisc off
root@laptop # ip link set eth0 down
root@laptop # ip link set dev eth0 nomaster
root@laptop # ip link delete bridge_name type bridge