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