<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>#blogdump &#187; arp</title>
	<atom:link href="http://aandre.evolix.net/tag/arp/feed/" rel="self" type="application/rss+xml" />
	<link>http://aandre.evolix.net</link>
	<description>geeky lines</description>
	<lastBuildDate>Wed, 17 Jun 2009 15:43:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>VRRP et Linux, un peu de bricolage&#8230;</title>
		<link>http://aandre.evolix.net/2009/04/08/vrrp-et-linux-un-peu-de-bricolage/</link>
		<comments>http://aandre.evolix.net/2009/04/08/vrrp-et-linux-un-peu-de-bricolage/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 13:05:37 +0000</pubDate>
		<dc:creator>arno</dc:creator>
				<category><![CDATA[vrrp]]></category>
		<category><![CDATA[arp]]></category>
		<category><![CDATA[bridge]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[ebtables]]></category>
		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">http://aandre.evolix.net/?p=142</guid>
		<description><![CDATA[On reprend l&#8217;article précédent en mettant un peu les mains dans le camboui.
Un petit patch
Un patch (peut-être pas très propre ni très abouti) est disponible ici http://aandre.evolix.net/files/vrrpd/vrrpd-1.0-ebtables.diff. Il permet d&#8217;utiliser la méthode décrite précédemment tout en améliorant l&#8217;affichage du statut de vrrpd pendant son exécution.
Le script /etc/vrrpd/vrrp_switch sera exécuté lors des changements d&#8217;états avec des [...]]]></description>
			<content:encoded><![CDATA[<p>On reprend <a title="VRRP et Linux" href="http://aandre.evolix.net/?p=8" target="_self">l&#8217;article précédent</a> en mettant un peu les mains dans le camboui.</p>
<p><strong>Un petit patch</strong></p>
<p>Un patch (peut-être pas très propre ni très abouti) est disponible ici <a title="vrrpd-1.0-ebtables.diff" href="http://aandre.evolix.net/files/vrrpd/vrrpd-1.0-ebtables.diff">http://aandre.evolix.net/files/vrrpd/vrrpd-1.0-ebtables.diff</a>. Il permet d&#8217;utiliser la méthode décrite précédemment tout en améliorant l&#8217;affichage du statut de vrrpd pendant son exécution.</p>
<p>Le script <em>/etc/vrrpd/vrrp_switch</em> sera exécuté lors des changements d&#8217;états avec des arguments supplémentaires:</p>
<ul>
<li>l&#8217;IP virtuelle VRRP,</li>
<li>l&#8217;interface sur laquelle l&#8217;instance VRRP tourne,</li>
<li>la priorité actuelle de l&#8217;instance,</li>
<li>l&#8217;advertisement interval VRRP</li>
<li>la preemption VRRP</li>
</ul>
<p><span id="more-142"></span></p>
<p>On récupère aussi l&#8217;adresse mac matérielle de l&#8217;interface du routeur, et l&#8217;adresse mac VRRP.</p>
<p>On va ainsi logger plus d&#8217;information sur l&#8217;état de notre routeur VRRP dans <em>/var/vrrp/vrrp-$VRRP_NAME</em>, mais surtout on aura à disposition les paramètres nécessaires pour le bon fonctionnement de nos règles ebtables gérant les états <em>master</em> et <em>slave</em>.</p>
<p>Il est prévu d&#8217;utiliser vrrpd avec l&#8217;option <em>-n</em> afin que ce dernier n&#8217;ait pas à gérer l&#8217;adresse mac virtuelle. Néanmoins cela entraîne aussi l&#8217;envoi des paquets d&#8217;échanges VRRP avec l&#8217;adresse mac matérielle. Le patch corrige cela.</p>
<p>On télécharge les sources de vrrpd ici <a title="vrrpd_1.0-1exp1.tar.gz" href="http://ftp.de.debian.org/debian/pool/main/v/vrrpd/vrrpd_1.0-1exp1.tar.gz">http://ftp.de.debian.org/debian/pool/main/v/vrrpd/vrrpd_1.0-1exp1.tar.gz</a></p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ wget http://ftp.de.debian.org/debian/pool/main/v/vrrpd/vrrpd_1.0-1exp1.tar.gz
$ tar zxvf vrrpd_1.0-1exp1.tar.gz</pre></div></div>

<p>On applique le patch et on compile:</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ wget http://aandre.evolix.net/files/vrrpd/vrrpd-1.0-ebtables.diff
$ cd vrrpd-1.0 &amp;&amp; patch -p1 &lt; ../vrrpd-1.0-ebtables.diff
$ make</pre></div></div>

<p>On prépare l&#8217;environnement de vrrpd à la main:</p>
<p>En root</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;"># mkdir /etc/vrrpd &amp;&amp; cp debian/vrrp_switch /etc/vrrp
# mkdir /var/vrrp</pre></div></div>

<p>Voilà on est prêt à tester vrrpd, en utilisant la topologie classique suivante :</p>
<div id="attachment_147" class="wp-caption aligncenter" style="width: 318px"><a rel="attachment wp-att-147" href="http://aandre.evolix.net/2009/04/08/vrrp-et-linux-un-peu-de-bricolage/vrrp_exemple1/"><img class="size-full wp-image-147" title="vrrp_exemple1" src="http://aandre.evolix.net/wp-content/vrrp_exemple1.png" alt="VRRP demo" width="308" height="257" /></a><p class="wp-caption-text">VRRP demo</p></div>
<p>Dans cet article on se contentera de tester la bascule VRRP en pingant continuellement l&#8217;adresse ip virtuelle et on regardera si les adresses MAC sont correctes dans /proc/net/arp de la machine &#8220;client&#8221;.</p>
<p><strong>Côté Cisco 800</strong></p>
<p>On configure une instance VRRP avec un group ID de 10, une priorité de 110, un advertisement interval de 2s et l&#8217;adresse IP virtuelle 192.168.10.250, sur l&#8217;interface configurée avec l&#8217;adresse 192.168.10.2/24 :</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">conf t
interface bla
vrrp 10 ip 192.168.10.250
vrrp 10 priority 110
vrrp 10 timers advertise 2</pre></div></div>

<p><strong>Côté Linux</strong></p>
<p>On prépare le bridge en y ajoutant la ou les interfaces que l&#8217;on souhaite, ici eth0.</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;"># brctl addbr br0
# ifconfig eth0 up
# brctl addif br0 eth0
# ifconfig br0 192.168.10.3</pre></div></div>

<p>On lance vrrpd sur cette interface avec une priorité de 90 (donc backup par rapport au cisco).</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;"># ./vrrpd -n -i br0 -v 10 -p 90 -d 2 -l demo 192.168.10.250 -D</pre></div></div>

<p>L&#8217;état de la machine faisant tourner vrrpd est bien slave :</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;"># cat /var/vrrp/state.10
slave
# cat /var/vrrp/vrrp-demo
VRRP - demo
Group 10
State is slave
Virtual IP address is 192.168.10.250
Virtual MAC address is 00:00:5E:00:01:a
demo is running on br0
Priority is 90
Advertisement interval is 2
Preemption is true</pre></div></div>

<p><strong>Côté client</strong></p>
<p>On peut lancer un tcpdump sur l&#8217;interface 192.168.10.12.</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;"># tcpdump -vvv -xx -i eth0 -n vrrp
&nbsp;
11:12:09.311568 IP (tos 0xc0, ttl 255, id 0, offset 0, flags [none], proto VRRP (112), length 40)
192.168.10.2 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 110, authtype none, intvl 2s, length 20, addrs: 192.168.10.250
0x0000:  0100 5e00 0012 0000 5e00 010a 0800 45c0
0x0010:  0028 0000 0000 ff70 0fe9 c0a8 0a02 e000
0x0020:  0012 210a 6e01 0002 a54f c0a8 0afa 0000
0x0030:  0000 0000 0000 0000 0000 0000</pre></div></div>

<p>Et l&#8217;on voit défiler les paquets VRRP d&#8217;avertissement émis par le routeur master (le cisco 800) avec l&#8217;adresse mac virtuelle 0000 5e00 010a</p>
<p>Un coup d&#8217;oeil sur les résolutions arp à partir de la machine client:</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ ping -c 1 192.168.10.2
$ ping -c 1 192.168.10.3
$ ping -c 1 192.168.10.250
$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.10.2     0x1         0x6         00:1e:7a:93:6f:21     *        eth0
192.168.10.3     0x1         0x2         00:13:72:76:23:aa     *        eth0
192.168.10.250   0x1         0x2         00:00:5e:00:01:0a     *        eth0</pre></div></div>

<p>Les deux routeurs sont toujours accessibles sur leur ip réelles avec les adresse mac matérielles correspondantes. La VMAC de l&#8217;instance VRRP est bien associée à 192.168.10.250.</p>
<p>Simulons grossièrement une &#8220;panne&#8221; du master en débranchant le cisco du lan et en pingant continuellement la VIP à partir du client:</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ ping 192.168.10.250
[...]
64 bytes from 192.168.10.250: icmp_seq=108 ttl=255 time=0.972 ms
64 bytes from 192.168.10.250: icmp_seq=109 ttl=255 time=0.959 ms
64 bytes from 192.168.10.250: icmp_seq=117 ttl=64 time=0.195 ms
64 bytes from 192.168.10.250: icmp_seq=118 ttl=64 time=0.171 ms
[...]</pre></div></div>

<p>La convergence vers le nouveau master s&#8217;est faite en quelques secondes, on l&#8217;observe sur le ping (ah regardez la ttl par exemple et /proc/sys/net/ipv4/ip_default_ttl sur la machine faisant tourner vrrpd&#8230;).</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ cat /var/vrrp/state.10
master
$ cat /var/vrrp/vrrp-demo
VRRP - demo
Group 10
State is master
Virtual IP address is 192.168.10.250
Virtual MAC address is 00:00:5E:00:01:a
vrrpd- is running on br0
Priority is 90
Advertisement interval is 2
Preemption is true</pre></div></div>

<p>Dans notre tcpdump, on voit que c&#8217;est vrrpd qui génère à présent les avertissements VRRP.</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">11:43:51.714625 IP (tos 0x0, ttl 255, id 256, offset 0, flags [none], proto VRRP (112), length 40)
192.168.10.3 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 90, authtype none, intvl 2s, length 20, addrs: 192.168.10.250
0x0000:  0100 5e00 0012 0000 5e00 010a 0800 4500
0x0010:  0028 0100 0000 ff70 0fa8 c0a8 0a03 e000
0x0020:  0012 210a 5a01 0002 b94f c0a8 0afa 0000
0x0030:  0000 0000 0000 0000 0000 0000</pre></div></div>

<p>L&#8217;interface br0 s&#8217;est bien appropriée la VIP 192.168.10.250:</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ ip addr show br0
3: br0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UNKNOWN 
    link/ether 00:13:72:76:23:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.3/24 brd 192.168.10.255 scope global br0
    inet 192.168.10.250/32 brd 192.168.10.250 scope global br0</pre></div></div>

<p>Vérifions à nouveau les adresses mac</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ ping -c 1 192.168.10.3
$ ping -c 1 192.168.10.250
$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.10.3     0x1         0x2         00:13:72:76:23:aa     *        eth0
192.168.10.250   0x1         0x2         00:00:5e:00:01:0a     *        eth0</pre></div></div>

<p>Tout est ok lorsque vrrpd est master.</p>
<p>On peut aussi vérifier les règles ebtables insérées lors du passage à l&#8217;état master :</p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">navi:/var/vrrp# ebtables -t broute -L
Bridge table: broute
&nbsp;
Bridge chain: BROUTING, entries: 1, policy: ACCEPT
-p IPv4 -d 0:0:5e:0:1:a --logical-in br0 -j redirect
navi:/var/vrrp# ebtables -L
Bridge table: filter
&nbsp;
Bridge chain: INPUT, entries: 0, policy: ACCEPT
&nbsp;
Bridge chain: FORWARD, entries: 0, policy: ACCEPT
&nbsp;
Bridge chain: OUTPUT, entries: 1, policy: ACCEPT
-p ARP -s 0:13:72:76:23:aa --logical-out br0 --arp-op Reply --arp-ip-src 192.168.10.250 -j DROP
navi:/var/vrrp# ebtables -t nat -L
Bridge table: nat
&nbsp;
Bridge chain: PREROUTING, entries: 1, policy: ACCEPT
-p ARP --logical-in br0 --arp-op Request --arp-htype 1 --arp-ptype IPv4 --arp-ip-dst 192.168.10.250 -j arpreply --arpreply-mac 0:0:5e:0:1:a --arpreply-target ACCEPT
&nbsp;
Bridge chain: OUTPUT, entries: 0, policy: ACCEPT
&nbsp;
Bridge chain: POSTROUTING, entries: 1, policy: ACCEPT
-p IPv4 --logical-out br0 --ip-src 192.168.10.250 -j snat --to-src 0:0:5e:0:1:a --snat-target ACCEPT</pre></div></div>

<p><strong> Conclusion</strong></p>
<p>L&#8217;exemple porte sur une seule instance de VRRP, mais il sera possible d&#8217;en lancer plusieurs en parallèle sur la mêmes interfaces et conserver la même cohérence.</p>
<p>Un autre sujet intéressant sur vrrpd pourrait concerner la fonctionnalité de tracking d&#8217;interface, qui prend tout son sens dans le cas par exemple d&#8217;un backup de ligne adsl. Néanmoins le code en l&#8217;état ne permet pas de l&#8217;utiliser sur <em>ppp0</em> (cf les fonctions monitorit() l.1984 et mido_read() l.2005).</p>
]]></content:encoded>
			<wfw:commentRss>http://aandre.evolix.net/2009/04/08/vrrp-et-linux-un-peu-de-bricolage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VRRP et Linux</title>
		<link>http://aandre.evolix.net/2009/02/12/vrrp-et-linux/</link>
		<comments>http://aandre.evolix.net/2009/02/12/vrrp-et-linux/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 10:41:49 +0000</pubDate>
		<dc:creator>arno</dc:creator>
				<category><![CDATA[vrrp]]></category>
		<category><![CDATA[arp]]></category>
		<category><![CDATA[bridge]]></category>
		<category><![CDATA[ebtables]]></category>
		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">http://aandre.evolix.net/?p=8</guid>
		<description><![CDATA[Ou comment faire croire aux machines de notre sous-réseau qu&#8217;on a plusieurs adresses MAC sur une seule interface (et par la même occasion redonner un peu de vie ici &#8230;).
Il existe une implémentation libre du protocole : vrrpd, apparemment plus maintenue à ce jour. On lui préfèrera la version patchée par les contributeurs debian qui [...]]]></description>
			<content:encoded><![CDATA[<p>Ou comment faire croire aux machines de notre sous-réseau qu&#8217;on a plusieurs adresses MAC sur une seule interface (et par la même occasion redonner un peu de vie ici &#8230;).</p>
<p>Il existe une implémentation libre du protocole : <a title="vrrpd" href="http://vrrpd.sourceforge.net" target="_blank">vrrpd</a>, apparemment plus maintenue à ce jour. On lui préfèrera la <a title="vrrpd debian experimental" href="http://packages.debian.org/source/experimental/vrrpd" target="_blank">version patchée</a> par les contributeurs debian qui amène pas mal d&#8217;améliorations et de corrections de bug. Je passe la description détaillée du protocole, on notera que <strong>vrrpd</strong> respecte la <a title="rfc 2338" href="http://tools.ietf.org/html/rfc2338" target="_blank">rfc 2338</a>, qui a été mise à jour par la <a title="rfc 3768" href="http://tools.ietf.org/html/rfc3768" target="_blank">rfc 3768</a> n&#8217;apportant en fait <a title="changes between rfc2338 and rfc3768" href="http://tools.ietf.org/html/rfc3768#section-13" target="_blank">rien de spécial</a>, à part en gros la suppression de l&#8217;authentification (tout en concervant la comptabilité avec l&#8217;ancienne rfc) et quelques clarifications.</p>
<p>Le principal problème sous linux quand on utilise un protocole de redondance utilisant une adresse MAC virtuelle est le fait qu&#8217;on ne puisse attribuer qu&#8217;une seule adresse mac par NIC, comme on peut le lire dans <a title="ce thread concernant justement VRRP" href="http://archive.linuxvirtualserver.org/html/lvs-users/2001-11/msg00256.html" target="_blank">ce thread concernant justement VRRP</a>.</p>
<p>Pour une <span style="text-decoration: underline;">unique instance</span> de VRRP, le problème est donc contourné dans <strong>vrrpd</strong> de la manière suivante:<br />
<span id="more-8"></span></p>
<ol>
<li>L&#8217;adresse MAC de l&#8217;interface sur laquelle tourne <strong>vrrpd</strong> est remplacée en mode Master par l&#8217;adresse MAC virtuelle de l&#8217;instance VRRP (que l&#8217;on notera <strong>VMAC</strong> par la suite),</li>
<li>La véritable adresse MAC est rajoutée à la liste des filtres multicast de l&#8217;interface, cette astuce permettra à celle-ci d&#8217;accepter les paquets envoyées à destination de son adresse IP réelle avec l&#8217;adresse MAC réelle.</li>
</ol>
<p>La première opération est effectuée par le code suivant dans la fonction <em>hwaddr_set</em> ligne 508:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* change the hwaddr */</span>
memcpy<span style="color: #009900;">&#40;</span> ifr.<span style="color: #202020;">ifr_hwaddr</span>.<span style="color: #202020;">sa_data</span><span style="color: #339933;">,</span> addr<span style="color: #339933;">,</span> addrlen <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* addr est VMAC */</span>
ifr.<span style="color: #202020;">ifr_hwaddr</span>.<span style="color: #202020;">sa_family</span> <span style="color: #339933;">=</span> AF_UNIX<span style="color: #339933;">;</span>
ret <span style="color: #339933;">=</span> ioctl<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> SIOCSIFHWADDR<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;</span>ifr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Et on retrouve la deuxième dans le code de la fonction  <em>rcvhwaddr_op</em> ligne 484:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">strncpy<span style="color: #009900;">&#40;</span>ifr.<span style="color: #202020;">ifr_name</span><span style="color: #339933;">,</span> ifname<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>ifr.<span style="color: #202020;">ifr_name</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
memcpy<span style="color: #009900;">&#40;</span> ifr.<span style="color: #202020;">ifr_hwaddr</span>.<span style="color: #202020;">sa_data</span><span style="color: #339933;">,</span> addr<span style="color: #339933;">,</span> addrlen <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    <span style="color: #808080; font-style: italic;">/* addr est ici la véritable adresse MAC de l'interface */</span>
ifr.<span style="color: #202020;">ifr_hwaddr</span>.<span style="color: #202020;">sa_family</span> <span style="color: #339933;">=</span> AF_UNSPEC<span style="color: #339933;">;</span>
ret <span style="color: #339933;">=</span> ioctl<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> addF <span style="color: #339933;">?</span> SIOCADDMULTI <span style="color: #339933;">:</span> SIOCDELMULTI<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;</span>ifr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ces deux fonctions sont appelées lors d&#8217;un changement d&#8217;état Backup -&gt; Master et inversement.</p>
<p>Alors si ce hack fonctionne pour une instance de VRRP, on est quand même confronté à un problème en mode Master:</p>
<p>- l&#8217;interface VRRP est joignable avec le bon couple VIP / VMAC. Quand un équipement du réseau fait une requête ARP pour connaître la VMAC liée à VIP, elle récupère bien la bonne adresse.</p>
<p>- Par contre si l&#8217;on essaye d&#8217;envoyer des paquets sur l&#8217;ancienne IP, soit notre équipement connait déjà l&#8217;adresse MAC et il n&#8217;y aura pas de requête ARP, soit il ne la connaît pas, effectue une requête ARP pour l&#8217;atteindre et reçoit la  VMAC au lieu de la véritable adresse MAC de l&#8217;interface. Bref cela fonctionnera, mais bon, ce n&#8217;est pas très cohérent &#8230;</p>
<p>Je vous laisse imaginer le chaos lorsque l&#8217;on tente de lancer <span style="text-decoration: underline;">plusieurs instances de VRRP</span> sur la même interface (avec des <em>group ids</em> différents) et observer ce qu&#8217;il se passe après chaque execution d&#8217;un nouveau <strong>vrrpd</strong> en pingant, sniffant, regarder <em>/proc/net/arp</em> sur les machines distantes, et jeter un oeil aux résultats de la commande <em>ip link show &lt;interface&gt;</em></p>
<p>Le problème apparait alors clairement: Comment faire pour conserver d&#8217;une part l&#8217;association adresse IP réelle de l&#8217;interface / adresse MAC réelle, et pour une ou plusieurs instances de VRRP l&#8217;association adresse IP virtuelle 1..n / adresse MAC virtuelle 1..n ?</p>
<p>Si l&#8217;on utilise <strong>vrrpd</strong> sur une interface de type <a title="bridge" href="http://linuxfoundation.org/en/Net:Bridge" target="_blank">bridge</a>, il est possible de simuler cette association avec <a title="ebtables" href="http://ebtables.sourceforge.net" target="_blank">ebtables</a>, dont la syntaxe est très proche d&#8217;iptables. Les schémas <a title="ici" href="http://ebtables.sourceforge.net/br_fw_ia/br_fw_ia.html#section2">ici</a> donnent une bonne idée du mécanisme et nous montrent où sont positionnés les hooks ebtables dans le cheminement d&#8217;un paquet.</p>
<p>Le but est de tromper la couche ethernet en falsifiant les réponses ARP et en créant les associations IP/MAC que l&#8217;on désire avec quelques règles.</p>
<p>On pose quelques variables:</p>
<p>- ROUTER_IF: Nom de l&#8217;interface sur laquelle tourne l&#8217;instance VRRP<br />
- ROUTER_MAC: Adresse MAC de l&#8217;interface<br />
- VRRP_IP: Adresse IP Virtuelle VRRP<br />
- VRRP_MAC: Adresse MAC Virtuelle VRRP</p>
<p>Et on attaque avec la première règle qui va empêcher les reply ARP avec la MAC réelle lorsque l&#8217;on reçoit un request ARP pour VRRP_IP (0&#215;0806 désigne l&#8217;ethertype ARP.):</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">$EBTABLES</span> <span style="color: #660033;">-A</span> OUTPUT \
<span style="color: #660033;">-p</span> 0X0806 \
<span style="color: #660033;">--logical-out</span> <span style="color: #007800;">$ROUTER_IF</span> <span style="color: #660033;">-s</span> <span style="color: #007800;">$ROUTER_MAC</span> \
<span style="color: #660033;">--arp-opcode</span> <span style="color: #000000;">2</span> \
<span style="color: #660033;">--arp-ip-src</span> <span style="color: #007800;">$VRRP_IP</span> \
<span style="color: #660033;">-j</span> DROP</pre></div></div>

<p>L&#8217;option &#8211;arp-opcode 2 désigne un paquet ARP reply (<em>ebtables -h arp</em>). Dans cette règle on matche les ARP reply générés par la couche ARP du kernel ayant pour source l&#8217;ip VRRP_IP.</p>
<p>On veut envoyer à la place la bonne VMAC:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">$EBTABLES</span> <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> PREROUTING \
<span style="color: #660033;">-p</span> 0x0806 <span style="color: #660033;">--logical-in</span> <span style="color: #007800;">$ROUTER_IF</span> \
<span style="color: #660033;">--arp-opcode</span> <span style="color: #000000;">1</span> <span style="color: #660033;">--arp-htype</span> <span style="color: #000000;">1</span> <span style="color: #660033;">--arp-ptype</span> 0x0800 \
<span style="color: #660033;">--arp-ip-dst</span> <span style="color: #007800;">$VRRP_IP</span> \
<span style="color: #660033;">-j</span> arpreply <span style="color: #660033;">--arpreply-mac</span> <span style="color: #007800;">$VRRP_MAC</span> <span style="color: #660033;">--arpreply-target</span> ACCEPT</pre></div></div>

<p>Ici on matche les ARP request pour VRRP_IP, et on génère avec <em>-j arpreply </em>un reply ARP avec la mac VRRP_MAC associée à VRRP_IP.</p>
<p>Maintenant que l&#8217;on contrôle les request/reply ARP, on veut aussi que les paquets sortant avec l&#8217;adresse IP virtuelle VRRP_IP possèdent l&#8217;adresse MAC virtuelle VRRP_MAC:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">$EBTABLES</span> <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> POSTROUTING \
<span style="color: #660033;">-p</span> 0x0800 <span style="color: #660033;">--logical-out</span> <span style="color: #007800;">$ROUTER_IF</span> \
<span style="color: #660033;">--ip-src</span> <span style="color: #007800;">$VRRP_IP</span> \
<span style="color: #660033;">-j</span> snat <span style="color: #660033;">--to-source</span> <span style="color: #007800;">$VRRP_MAC</span> <span style="color: #660033;">--snat-target</span> ACCEPT</pre></div></div>

<p>On veut faire l&#8217;inverse sur les paquets entrant, c&#8217;est à dire qu&#8217;on va changer l&#8217;adresse MAC virtuelle VRRP_MAC du paquet en adresse MAC ROUTER_MAC afin que le bridge ne le rejette pas:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">$EBTABLES</span> <span style="color: #660033;">-t</span> broute <span style="color: #660033;">-A</span> BROUTING \
<span style="color: #660033;">--logical-in</span> <span style="color: #007800;">$ROUTER_IF</span> <span style="color: #660033;">-p</span> 0x0800 <span style="color: #660033;">-d</span> <span style="color: #007800;">$VRRP_MAC</span> \
<span style="color: #660033;">-j</span> redirect</pre></div></div>

<p>En utilisant la table broute, on change au plus tôt l&#8217;adresse MAC.<br />
Le <em>redirect</em> signale au bridge de continuer le traitement du paquet après avoir changer l&#8217;adresse MAC.</p>
<p>Et voilà, on a toutes les règles qu&#8217;il nous faut, la magie est en place. On va pouvoir lancer plusieurs instances de VRRP indépendantes les unes des autres sur une interface de type bridge, en respectant la RFC et l&#8217;intégrité du niveau ethernet.</p>
<p>Pour que <strong>vrrpd</strong> applique ses règles automatiquement, on désactive sa gestion de l&#8217;adresse MAC virtuelle avec l&#8217;option &#8220;-n&#8221; et on place nos règles dans le script <em>/etc/vrrpd/vrrp_switch</em> dans le <em>case &#8220;$1&#8243;</em> en différenciant le cas <em>&#8220;master&#8221;</em> du cas <em>&#8220;slave&#8221;</em> (fonctionnalité rajouté par les contributeurs Debian, ce script est appelé à chaque changement d&#8217;état). Ne pas oublier d&#8217;effacer les règles dans le cas <em>&#8220;slave&#8221;</em>.</p>
<p>Alors certes cette méthode oblige à utiliser une interface de type bridge, mais on peut se dire que si on utilise VRRP sur une box, il y a de grandes chances que l&#8217;interface concernée soit déjà un bridge qui agrège plusieurs interfaces eth*. Sinon il existe sûrement une meilleure méthode qui permette les mêmes manipulations au niveau ARP, si quelqu&#8217;un a un lien je suis preneur.</p>
<p>Un autre avantage notable c&#8217;est que l&#8217;on ne tombe plus l&#8217;interface VRRP pour changer les adresses MAC (cf les deux fonctions plus haut) et on ne perd plus du coup les règles de routage liées à l&#8217;interface (alors oui il y a bien un patch pour ça mais bon&#8230;).</p>
<p>Il y aura sûrement d&#8217;autres articles sur <strong>vrrpd</strong>, il y a encore quelques trucs à bidouiller pour l&#8217;améliorer et je reviendrai sur l&#8217;illustration du bon fonctionnement de cette méthode, le post d&#8217;aujourd&#8217;hui est assez long comme ça <img src='http://aandre.evolix.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> &#8230;</p>
<p>NB : Pour aller plus loin avec ARP en général, je suis tombé récemment sur une <a href="http://sid.rstack.org/articles/arp/arp.html">page très interessante</a> et un petit <a href="http://sid.rstack.org/arp-sk/">utilitaire</a> du même auteur pour faire pleins de choses sympas avec ARP.</p>
]]></content:encoded>
			<wfw:commentRss>http://aandre.evolix.net/2009/02/12/vrrp-et-linux/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
