Catégorie : Administration système     Tags : , ,      

    Avertissement

    Il faut toujours faire attention quand on manie des objets pointus ou tranchants, donc ne courez pas avec cet article dans les mains et ne le laissez pas à la portée des enfants en bas âge. Ah, et une dernière chose, surtout ne nourrissez jamais cet article après minuit, on ne sait pas ce qu'il pourrait advenir.
    Il est préférable d'avoir une certaine connaissance des protocoles de routage dynamique OSPF [1] et BGP [2] et une bonne maîtrise d'OpenBSD. La lecture de l'article précédent "Répartition de charge et Haute disponibilité sur les OS *BSD (Partie 1)" est conseillée. Nous aborderons des concepts qui y sont brillamment expliqués </prosel>. Ayant travaillé avec des routeurs sensibles, j'ai modifié les IP, AS et noms des machines publiques.

    1. Introduction

    Ah, te voilà Gérard, c'était bien ton cours précédent ? Je vois que tu as encore des étoiles plein les yeux et un sourire béat sur le visage. Tu en veux encore j'ai l'impression, j'ai tout de suite senti que tu étais un goulu. On va rassasier cette faim d'apprendre avec un peu plus de haute disponibilité. Il ne faut jamais contrarier le curieux, tu le sais ça, mon petit Gérard.
    Donc, nous allons nous pencher, mais pas trop, sur les notions de multihoming [3] et de protocoles de routage dynamique. On va y aller pas à pas, comme si on apprenait le vélo avec les petites roues d'abord. On va commencer par parler rapidement d'OSPF et BGP et ensuite on installera un environnement propice à la mise en place de notre système de haute disponibilité. Tu m'écoutes Gérard ?
    Les aspects de sécurisation de ces protocoles ne seront pas abordés, donc on ne parlera pas de chiffrement des sessions ou de règles firewall pour protéger les accès aux sessions BGP.

    1.1 OSPF

    L'OSPF (Open Shortest Path First) est un protocole IGP (Interior Gateway Protocol) [4] d'annonce de route qui permet de transmettre les états des interfaces (link-state) d'un routeur à d'autres routeurs. La transmission se fait en multicast et uniquement sur changement de topologie. Les routeurs connectés en OSPF peuvent donc se faire une représentation du réseau sous forme d'un graphe et choisir le chemin le moins coûteux en utilisant l'algorithme de Dijkstra.

    1.2 BGP

    Le BGP (Border Gateway Protocol) permet d'échanger des routes agrégées (adresse + netmask) entre routeurs. Cet échange se fait en TCP sur le port 179. L'échange se fait généralement entre AS (Autonomous System) et uniquement de voisin à voisin. On parle d’eBGP lorsque l'échange se fait entre AS différents et d’iBGP au sein d'un même AS. Les tables de routes échangées permettent ensuite de créer la table de routage du routeur BGP grâce à un algorithme décisionnel.

    1.3 OpenBGPd et OpenOSPFd

    Le projet OpenBSD [7] nous gratifie de 2 excellents daemons implémentant les protocoles de routage OSPF [5] et BGP-4 [6] [10] tels que décrits dans leurs RFC. Ces services assurent donc la collecte et l'algorithme de décision qui permet de construire la table de routage du kernel. La base de connaissance des routes apprises via ces 2 protocoles est appelée RIB (Routing Information Base) et la table de routage est appelée FIB (Forwarding Information Base). Ces 2 serveurs tournent avec séparation de privilège. Le processus root servant uniquement à ouvrir le port privilégié en BGP et à modifier la table de routage du noyau. Pour une présentation exhaustive du projet, tu peux consulter l'excellente présentation de Henning Brauer [11], mon petit Gérard.

    2. Installation de base

    Pour commencer, Gérard, il te faut 2 systèmes OpenBSD fraîchement installés. Je te fais confiance. Moi, j'ai fait le choix d'OpenBSD 4.0 que tu trouveras dans toutes les bonnes crémeries.
    Ces 2 serveurs doivent avoir 3 interfaces réseau physiques chacun. Nous allons les configurer comme sur le schéma 1,
    page suivante.
    Il y a donc plusieurs choses à configurer sur chaque serveur :

    • une adresse vers le domaine public ;
    • une adresse vers le domaine privé que l'on utilise comme adresse dite "d'administration" ;

    /img-articles/lmhs/29/cc-art-routageHA/fig-1.jpg

    schéma 1

    • une adresse "flottante" qui sera associée aux 2 interfaces privées grâce à CARP [8] ;
    • une adresse de back-to-back qui connectera les 2 serveurs ;
    • une loopback ;

    Les 2 serveurs s'appellent "openbgp01" et "openbgp02". Les adresses choisies sont les suivantes :

    • openbgp01 :
      • adresse publique : 10.0.1.1/30 ;
      • adresse privée : 172.16.0.1/24 ;
      • adresse de loopback : 192.168.1.1/32 ;
      • adresse de back-to-back : 192.168.3.1/24 ;
      • passerelle par défaut : 10.0.1.2/30.
    • openbgp02 :
      • adresse publique : 10.0.2.1/30 ;
      • adresse privée : 172.16.0.2/24 ;
      • adresse de loopback : 192.168.2.1/32 ;
      • adresse de back-to-back : 192.168.3.2/24 ;
      • passerelle par défaut : 10.0.2.2/30.

    L'adresse flottante utilisée sera 172.16.0.3/24. C'est un peu long tout ça, mais plus c'est long, ben… plus c'est long à configurer.

    2.1 Matériel

    Les machines utilisées comme routeurs dans cet article sont des PC équipés de 2 processeurs PIII 800 et de 2 Go de RAM sur une carte mère ASUS CUR-DLS. Les interfaces réseau sont le contrôleur Ethernet de type Intel EtherExpress PRO/100 intégré à la carte mère et une carte 4 ports Ethernet D-LINK DFE-570TX.

    2.2 Réseau

    Cela donne une configuration de ce type :

     openbgp01# # ifconfig
    fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet 172.16.0.1 netmask 0xffffff00 broadcast 172.16.0.255
    dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet 10.0.1.1 netmask 0xfffffffc broadcast 10.0.1.3
    dc1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet 192.168.3.1 netmask 0xffffff00 broadcast 192.168.3.255
    lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33224
            groups: lo
            inet 192.168.1.1 netmask 0xffffffff
    openbgp02# ifconfig
    lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33224
            inet 127.0.0.1 netmask 0xff000000
    fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet 172.16.0.2 netmask 0xffffff00 broadcast 172.16.0.255
    dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet 10.0.2.1 netmask 0xfffffffc broadcast 10.0.2.3
    dc1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet 192.168.3.2 netmask 0xffffff00 broadcast 192.168.3.255
    lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33224
            groups: lo
            inet 192.168.2.1 netmask 0xffffffff

    2.3 Routage

    Il faut que nos serveurs se comportent comme des routeurs, il faut donc activer le forwarding IP via sysctl et faire en sorte que la configuration soit présente en cas de redémarrage en la mettant dans /etc/sysctl.conf.

    # sysctl -w net.inet.ip.forwarding=1

    2.4 CARP et ça flotte

    On met en place l'adresse flottante sur nos 2 serveurs grâce à CARP. On décide qu’openbgp01 sera master et devra récupérer ce rôle en cas de retour après panne. Vérifions que carp est bien activé sur nos serveurs :

    # sysctl net.inet.carp.allow
    net.inet.carp.allow=1

    On peut aussi éventuellement activer les logs d'erreurs via la variable net.inet.carp.log.

    openbgp01# ifconfig carp0 create
    openbgp01# ifconfig carp0 vhid 1 advskew 1 pass \
      _0p3nBGP carpdev fxp0 172.16.0.3 netmask 255.255.255.0
    openbgp02# ifconfig carp0 create
    openbgp02# ifconfig carp0 vhid 1 advskew 100 pass \
      _0p3nBGP carpdev fxp0 172.16.0.3 netmask 255.255.255.0
    openbgp01# ifconfig carp0           
    
    carp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            lladdr 00:00:5e:00:01:01
            carp: MASTER carpdev fxp0 vhid 1 advbase 1 advskew 1
            groups: carp
            inet6 fe80::200:5eff:fe00:101%carp0 prefixlen 64 scopeid 0xb
            inet 172.16.0.3 netmask 0xffffff00 broadcast 172.16.0.255
    openbgp02# ifconfig carp0 
    
    carp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            lladdr 00:00:5e:00:01:01
            carp: BACKUP carpdev fxp0 vhid 1 advbase 1 advskew 100
            groups: carp
            inet6 fe80::200:5eff:fe00:101%carp0 prefixlen 64 scopeid 0xb
            inet 172.16.0.3 netmask 0xffffff00 broadcast 172.16.0.255

    openbgp01 est bien master dès le départ, donc tout est ok. On fait en sorte que cette machine récupère toujours le statut de master grâce à la variable net.inet.carp.preempt.

    openbgp01# sysctl -w net.inet.carp.preempt=1

    Si tout fonctionne correctement, on colle tout ça dans /etc/sysctl.conf et /etc/hostname.carp0.

    2.5 ifstated

    On pourrait associer ifstated [9] à cette configuration pour faire basculer l'adresse flottante sur openbgp02 lorsque des problèmes se posent sur l'interface publique d'openbgp01, mais c'est exactement le résultat que nous allons obtenir par la suite avec OSPF et BGP.

    2.6 Un instant kodak

    Comme le but ici est quand même de s'intéresser au routage, on va prendre une jolie photo des tables de routage. Mets-toi juste à côté Gérard.

     openbgp01# netstat -nrf inet
    Routing tables
    
    Internet:
    Destination  Gateway           Flags Refs  Use   Mtu Interface
    default      10.0.1.2          UGS      1  831     -  dc0
    10.0.1.0/30  link#2            UC       1    0     -  dc0
    10.0.1.2     00:10:db:ff:20:80 UHLc     1    0     -  dc0
    127/8        127.0.0.1         UGRS     0    0 33224  lo0
    127.0.0.1    127.0.0.1         UH       0    0 33224  lo0
    192.168.1.1  192.168.1.1       UH       0    0 33224  lo1
    192.168.3/24 link#3            UC       0    0     -  dc1
    172.16.0/24  link#1            UC       0    0     -  fxp0
    172.16.0.3   172.16.0.3        UH       0    0     -  carp0
    224/4        127.0.0.1         URS      0    0 33224  lo0
    openbgp02# netstat -nrf inet
    Routing tables
    
    Internet:
    Destination  Gateway           Flags Refs  Use   Mtu Interface
    default      10.0.2.2          UGS      1  831     -  dc0
    10.0.2.0/30  link#2            UC       1    0     -  dc0
    10.0.2.2     00:10:db:ff:20:80 UHLc     1    0     -  dc0
    127/8        127.0.0.1         UGRS     0    0 33224  lo0
    127.0.0.1    127.0.0.1         UH       0    0 33224  lo0
    192.168.2.1  192.168.2.1       UH       0    0 33224  lo1
    192.168.3/24 link#3            UC       0    0     -  dc1
    172.16.0/24  link#1            UC       0    0     -  fxp0
    172.16.0.3   172.16.0.3        UH       0    0     -  carp0
    224/4        127.0.0.1         URS      0    0 33224  lo0

    Pour information, la commande route -n show -inet donne exactement le même résultat sous OpenBSD.

    3. Venez-en au fait mon vieux !

    Eh oui, c'est vrai, on tourne autour du pot, hein, et à force de tourner, eh bien, on en perd l'équilibre, c'est assez désolant. Donc, on y va, on installe les daemons qui nous intéressent et on se lance dans la bataille. Gérard, c'est pas parce que tu apprends que tu peux te permettre de rester à me regarder comme un flan, on se bouge mon vieux.

    3.1 Installation

    On installe donc les 2 daemons qui vont nous permettre de mettre en place notre routage dynamique. Cette installation se fait sur les 2 routeurs. Sur un OpenBSD 4.0, openbgpd et openospfd sont déjà installés dans le système de base. On reproduit la manipulation d'installation au cas où ils ne seraient pas installés sur votre système.

     # mkdir src
    # cd src
    # wget ftp://ftp.crans.org/pub/OpenBSD/OpenBGPD/openbgpd-4.0.tgz
    # tar zxf openbgpd-4.0.tgz
    # cd bgpd
    # make && make install
    [...]
    # cd ../bgpctl
    # make && make install
    [...]
    # wget ftp://ftp.crans.org/pub/OpenBSD/OpenBGPD/openospfd-4.0.tgz
    # tar zxf openospfd-4.0.tgz
    # cd ospfd
    # make && make install
    [...]
    # cd ../ospfctl
    # make && make install
    [...]

    Et c'est fini. C'est d'une simplicité déconcertante mon ami. Je vous sens tout baba.

    3.2 Il faut toujours commencer tranquille : OSPF et iBGP

    Là, bien solide sur ses appuis, tu vois Gérard, la souplesse du cuisseau. C'est très important ça, la souplesse, donc tranquille, détendu et souple, mais vif tout de même, on n'est pas des fruits de mer voyons. On va commencer par monter une session OSPF pour annoncer les interfaces locales connectées et les nexthops connectés. Cette annonce permettra de construire une table de routage comprenant la loopback de chaque routeur, ce qui est important pour la suite. Ensuite, la session iBGP rentre en piste et nous permet de redistribuer les routes existant sur un routeur vers son voisin. Celui-ci décidera ensuite de la table de routage qu'il doit appliquer en connaissance de cause.

    /img-articles/lmhs/29/cc-art-routageHA/fig-2.jpg

    3.2.1 OSPF

    Le protocole OSPF servi par le fameux ospfd est configuré par /etc/ospfd.conf :

     loopback="192.168.1.1"
    router-id $loopback
    area 0.0.0.1 {
            interface dc1
            interface lo1
            interface dc0 {
                    passive
            }
    }

    La macro loopback doit avoir pour valeur l'adresse IP de la loopback du serveur concerné. On crée une area avec un identifiant quelconque (ici 0.0.0.1) et on demande à ce bloc d'annoncer l'interface publique, l'interface privée et la loopback. En outre, on précise que l'interface publique ne doit ni émettre, ni recevoir de paquets OSPF, grâce à l'option passive. La configuration doit être identique sur les 2 routeurs.
    Je lance le daemon ospfd en mode non détaché et verbeux pour voir ce qu'il se passe et éventuellement détecter des erreurs. Au lancement sur openbgp01, on obtient :

     openbgp01# ospfd -d -v
    loopback = "192.168.1.1"
    startup
    orig_asext_lsa: 10.0.1.2/32 age 0
    start_spf_timer: IDLE -> DELAY
    orig_rtr_lsa: area 0.0.0.1
    orig_rtr_lsa: stub net, interface dc0
    orig_rtr_lsa: stub net, interface dc1
    if_fsm: event UP resulted in action START and changing
      state for interface dc0 from DOWN to DOWN
    if_fsm: interface lo1, event UP not expected in state LOOP
    orig_rtr_lsa: area 0.0.0.1
    orig_rtr_lsa: stub net, interface dc0
    orig_rtr_lsa: stub net, interface dc1
    if_fsm: event UP resulted in action START and changing
      state for interface dc1 from DOWN to WAIT
    spf_calc: calculation started, area ID 0.0.0.1
    spf_calc: calculation ended, area ID 0.0.0.1
    spf_start_holdtimer: DELAY -> HOLD
    spf_timer: state HOLD -> IDLE

    Quand on lance le daemon sur openbgp02, voici ce qu'ospfd nous dit sur openbgp01 :

     openbgp01nbr_fsm: event HELLO_RECEIVED
      resulted in action START_INACTIVITY_TIMER and changing
      state for neighbor ID 192.168.2.1 from DOWN to INIT
    nbr_fsm: event 2_WAY_RECEIVED resulted in action EVAL
      and changing state for neighbor ID 192.168.2.1
      from INIT to EXSTA
    if_act_elect: interface dc1 old dr 192.168.3.1 new dr
      192.168.3.1, old bdr none new bdr 192.168.3.2
    orig_rtr_lsa: area 0.0.0.1
    orig_rtr_lsa: stub net, interface dc0
    orig_rtr_lsa: stub net, interface dc1
    if_fsm: event NEIGHBORCHANGE resulted in action ELECT and
      changing state for interface dc1 from DR to DR

    La session est d'abord négociée entre les 2 routeurs. Ensuite, on observe que le routeur apprend les interfaces que son voisin lui annonce. Il annonce d'ailleurs que l'interface dc0 est dans un statut "stub", ce qui signifie qu'elle n'est pas considérée comme connectée. Le serveur finit par calculer l'arbre des chemins pour ensuite prendre ses décisions de routage. La convergence est tout de même un peu lente, mais ça prend effet en 20 secondes environ. Il convient aussi de remarquer que les développeurs d'OpenOSPFd sont de grossiers personnages qui traitent mes interfaces de moignons (stub).

     openbgp01# ospfctl show database                                                        
    
                    Router Link States (Area 0.0.0.1)
    
    Link ID         Adv Router      Age  Seq#       Checksum
    192.168.1.1     192.168.1.1     79   0x80000002 0x886a
    192.168.2.1     192.168.2.1     80   0x80000002 0xbc31
    
                    Net Link States (Area 0.0.0.1)
    
    Link ID         Adv Router      Age  Seq#       Checksum
    192.168.3.2     192.168.2.1     80   0x80000001 0x9011
    
                    Type-5 AS External Link States
    
    Link ID         Adv Router      Age  Seq#       Checksum
    10.0.1.2        192.168.1.1     123  0x80000001 0xb088
    10.0.2.2        192.168.2.1     120  0x80000001 0x9f97
    openbgp01# ospfctl show rib
    Destination    Nexthop     Path Type  Type    Cost Uptime
    192.168.2.1    192.168.3.2 Intra-Area Router  10   01:58:40
    10.0.2.0/30    192.168.3.2 Intra-Area Network 20   01:58:40
    192.168.2.1/32 192.168.3.2 Intra-Area Network 10   01:58:40
    192.168.3.0/24 192.168.3.1 Intra-Area Network 10   01:58:47
    
    openbgp01# netstat -nrf inet
    Routing tables
    
    Internet:
    Destination    Gateway           Flags Refs Use   Mtu Interface
    default        10.0.1.2          UGS      2 831     -  dc0
    10.0.1.0/30    link#2            UC       1   0     -  dc0
    10.0.1.2       00:10:db:ff:20:80 UHLc     1   0     -  dc0
    10.0.2.0/30    192.168.3.2       UG2      1   0     -  dc1
    127/8          127.0.0.1         UGRS     0   0 33224  lo0
    127.0.0.1      127.0.0.1         UH       0   0 33224  lo0
    192.168.1.1    192.168.1.1       UH       0   0 33224  lo1
    192.168.2.1/32 192.168.3.2       UG2      0   0     -  dc1
    192.168.3/24   link#3            UC       1   0     -  dc1
    192.168.3.2    00:80:c8:c9:9a:72 UHLc     2  28     -  dc1
    172.16.0/24    link#1            UC       0   0     -  fxp0
    172.16.0.3     172.16.0.3        UH       0   0     -  carp0
    224/4          127.0.0.1         URS      0   0 33224  lo0

    Mais regardez-moi ça, vous savez ce que c'est ? Ce sont de belles routes vers openbgp02 :

    • une route pour 10.0.2.0/30 via le back-to-back ;
    • une route pour 192.168.2.1/32 toujours via le back-to-back ;
    • la correspondance IP/adresse mac pour cette adresse de back-to-back.

    Maintenant qu'on est sûr que le protocole a correctement négocié, on peut relancer ospfd en mode détaché sur les 2 routeurs et le rajouter dans le /etc/rc.conf.

    ospfd=YES
    ospfd_flags=NO

    3.2.2 iBGP

    Allez Gérard, on s'attaque à l'iBGP maintenant. Tu vas voir, c'est beau tout plein ! Maintenant qu'on connaît les loopbacks du routeur d'à côté, on va monter la session iBGP qui nous permettra en cas de problème de rediriger le trafic via le back-to-back. C'est un premier pas vers un système sécurisé en réseau. La configuration de bgpd via le fichier /etc/bgpd.conf est la suivante :

     peer_ibgp="192.168.2.1"
    loopback="192.168.1.1"
    as_ibgp="65001"
    
    # global configuration
    AS 65001
    listen on $loopback
    network connected
    # iBGP
    group "IBGP" {
            remote-as $as_ibgp
            neighbor $peer_ibgp {
                    descr "lo openbgp02"
                    local-address $loopback
            }
            announce all
    }

    Tu vas voir, on va faire exactement comme tout à l'heure. On lance d'abord bgpd en mode non détaché et verbeux sur openbgp01 :

     openbgp01# bgpd -d -v
    peer_ibgp = "192.168.2.1"
    loopback = "192.168.1.1"
    as_ibgp = "65001"
    startup
    route decision engine ready
    listening on 192.168.1.1
    session engine ready
    neighbor 192.168.2.1 (lo openbgp02):
      state change None -> Idle, reason: None
    neighbor 192.168.2.1 (lo openbgp02):
      state change Idle -> Connect, reason: Start
    neighbor 192.168.2.1 (lo openbgp02):
      socket error: Connection refused
    neighbor 192.168.2.1 (lo openbgp02):
      state change Connect -> Active, reason:
      Connection open failed

    Et maintenant, on le lance sur openbgp02 et on attend qu'ils se mettent d'accord et qu'ils soient vraiment contents :

     neighbor 192.168.2.1 (lo openbgp02):
      state change Active -> OpenSent,
      reason: Connection opened
    neighbor 192.168.2.1 (lo openbgp02):
      state change OpenSent -> OpenConfirm,
      reason: OPEN message received
    neighbor 192.168.2.1 (lo openbgp02):
      state change OpenConfirm -> Established,
      reason: KEEPALIVE message received
    nexthop 192.168.2.1 now valid: via 192.168.3.2

    Le serveur BGP sur openbgp01 confirme qu'il connaît le voisin openbgp02 et qu'il reçoit les informations via le back-to-back. Voyons maintenant tout ce que ça a pu générer sur les 2 routeurs. D'abord l'état des sessions BGP :

    openbgp01# bgpctl show summary
    Neighbor     AS    MsgRcvd MsgSent OutQ Up/Down  State/PrefixRcvd
    lo openbgp02 65001       6       5    0 00:01:18      1
    
    openbgp02# bgpctl show summary
    Neighbor     AS    MsgRcvd MsgSent OutQ Up/Down  State/PrefixRcvd
    lo openbgp01 65001      10       9    0 00:02:11      3

    Une seule route a été échangée avec openbgp02. Par contre, openbgp02 a appris des routes de la part d'openbgp01. Nous allons voir, par la suite, quelles sont ces routes et leur signification.
    Ensuite, les tables de routes apprises via BGP sur openbgp01 et openbgp02 :

    openbgp01# bgpctl show rib
    flags: * = Valid, > = Selected, I = via IBGP, A = Announced
    origin: i = IGP, e = EGP, ? = Incomplete
    
    flags destination    gateway     lpref   med aspath origin
    AI*>  10.0.1.0/30    0.0.0.0       100     0 i
    I*>   10.0.2.0/30    192.168.2.1   100     0 i
    AI*>  192.168.3.0/24 0.0.0.0       100     0 i
    AI*>  172.16.0.0/24  0.0.0.0       100     0 i

    Le routeur openbgp01 annonce (A) toutes ses routes apprises via OSPF (I), à l'exception de la route qui annonce le chemin vers internet via openbgp02.

     openbgp02# bgpctl show rib
    flags: * = Valid, > = Selected, I = via IBGP, A = Announced
    origin: i = IGP, e = EGP, ? = Incomplete
    
    flags destination    gateway     lpref   med aspath origin
    I*>   10.0.1.0/30    192.168.1.1   100     0 i
    AI*>  10.0.2.0/30    0.0.0.0       100     0 i
    I*>   192.168.3.0/24 192.168.1.1   100     0 i
    AI*   192.168.3.0/24 0.0.0.0       100     0 i
    I*>   172.16.0.0/24  192.168.1.1   100     0 i
    AI*   172.16.0.0/24  0.0.0.0       100     0 i

    La différence entre les 2 tables RIB est un choix fait par OpenBGPd, a priori basé sur le router-id de chaque routeur. Ne l'ayant pas spécifié, OpenBGPd a fait son choix seul. Le router-id constitue le dernier critère de décision dans l'algorithme de construction de la table de routage par BGP.

    openbgp01# netstat -nrf inet
    Routing tables
    
    Internet:
    Destination    Gateway           Flags Refs Use   Mtu  Interface
    default        10.0.1.2          UGS      2 831     -   dc0
    10.0.1.0/30    link#2            UC       1   0     -   dc0
    10.0.1.2       00:10:db:ff:20:80 UHLc     1   0     -   dc0
    10.0.2.0/30    192.168.3.2       UG2      0   0     -   dc1
    127/8          127.0.0.1         UGRS     0   0 33224   lo0
    127.0.0.1      127.0.0.1         UH       0   0 33224   lo0
    192.168.1.1    192.168.1.1       UH       0   0 33224   lo1
    192.168.2.1/32 192.168.3.2       UG2      1  28     -   dc1
    192.168.3/24   link#3            UC       1   0     -   dc1
    192.168.3.2    00:80:c8:c9:9a:72 UHLc     2  15     -   dc1
    172.16.0/24    link#1            UC       0   0     -   fxp0
    172.16.0.3     172.16.0.3        UH       0   0     -   carp0
    224/4          127.0.0.1         URS      0   0 33224   lo0

    Aucune modification de la table de routage sur openbgp01, puisque toutes les routes locales sont "connected". Si un problème survenait, de nouvelles décisions de routage seraient prises sur la base des routes connues. Il est à noter que la route vers le sous-réseau public 10.0.2.0/30 est connue à la fois via OSPF et via BGP.
    Le résultat est satisfaisant, donc on peut prévoir le lancement de bgpd au démarrage via /etc/rc.conf.

    bgpd=YES
    bgpd_flags=NO

    Gérard, mon petit, je sens que tu veux crier victoire. Tu te dis qu´il n´y a rien de tel que d´aller chez Azzedine Alaia ou même de s´acheter des sous-pulls chez Yohji Yamamoto.

    3.3 Et là on est chaud, alors on se lance : OSPF, iBGP et eBGP

    Excuse-moi de te dire ça, mon pauvre Gérard, mais tu confonds un peu tout, tu fais un amalgame entre la coquetterie et la classe. Tu es fou ! La vraie classe, c'est de monter une session BGP avec un autre AS et d'apprendre Internet.

    /img-articles/lmhs/29/cc-art-routageHA/fig-3.jpg

    On rajoute maintenant une session eBGP avec un routeur d'un autre AS. La configuration du daemon bgpd, sur openbgp01 uniquement pour le moment, donne :

    peer_ebgp="10.0.1.2"
    public="10.0.1.1"
    as_ebgp="65002"
    
    listen on $public
    network connected
    
    # eBGP
    group "EBGP" {
            remote-as $as_ebgp
            neighbor $peer_ebgp {
                    descr "peer eBGP"
                    local-address $public
            }
            announce none
    }

    Ce rajout au fichier de configuration /etc/bgpd.conf est à peu de chose près identique à la configuration iBGP. La grande différence est que le numéro d'AS du voisin est différent du numéro d'AS d'openbgp01. Il est également précisé qu'on ne va annoncer aucune route vers le routeur BGP voisin. On ne fera qu'apprendre les routes qu'il veut bien nous envoyer.
    On peut recharger le fichier de configuration via la commande bgpctl reload et on ne va pas s'en priver.

    [...openbgp01...]
    rereading config
    peer_ibgp = "192.168.2.1"
    peer_ebgp = "10.0.1.2"
    loopback = "192.168.1.1"
    public = "10.0.1.1"
    as_ibgp = "65001"
    as_ebgp = "65002"
    nexthop 192.168.2.1 now valid: via 192.168.3.2
    RDE reconfigured
    listening on 10.0.1.1
    SE reconfigured
    neighbor 10.0.1.2 (peer eBGP):
      state change None -> Idle,
      reason: None
    neighbor 10.0.1.2 (peer eBGP):
      state change Idle -> Connect,
      reason: Start
    neighbor 10.0.1.2 (peer eBGP):
      state change Connect -> OpenSent,
      reason: Connection opened
    neighbor 10.0.1.2 (peer eBGP):
      state change OpenSent -> OpenConfirm,
      reason: OPEN message received
    neighbor 10.0.1.2 (peer eBGP):
      received notification: error in OPEN message,
      unsupported capability
    neighbor 10.0.1.2 (peer eBGP):
      received "unsupported capability"
      notification without data part,
      disabling capability announcements altogether
    neighbor 10.0.1.2 (peer eBGP):
      state change OpenConfirm -> Idle,
      reason: NOTIFICATION received
    neighbor 10.0.1.2 (peer eBGP):
      state change Idle -> Connect,
      reason: Start
    neighbor 10.0.1.2 (peer eBGP):
      state change Connect -> OpenSent,
      reason: Connection opened
    neighbor 10.0.1.2 (peer eBGP):
      state change OpenSent -> OpenConfirm,
      reason: OPEN message received
    neighbor 10.0.1.2 (peer eBGP):
      state change OpenConfirm -> Established,
      reason: KEEPALIVE message received

    Le peer eBGP envoie des messages de confirmation. Les deux routeurs se mettent d'accord sur les options qu'ils supportent l'un et l'autre et ouvrent la session.

    [...openbgp02...]
    nexthop 10.0.1.2 now valid: via 192.168.3.1

    Le serveur openbgp02 nous signale, quant à lui, qu'il a appris un nouveau nexthop via le back-to-back.

    openbgp01# bgpctl show summary
    Neighbor AS MsgRcvd MsgSent OutQ Up/Down State/PrefixRcvd
    peer eBGP 65002 56068 10 0 00:02:42 203179
    lo openbgp02 65001 45 55779 0 00:20:58 1

    Les routes de l'AS 65002 ont bien été apprises par openbgp01 via la session eBGP. Ici le routeur a récupéré une table de 203179 routes. Il est normal de constater des fluctuations dans ce nombre de routes. C'est le grand Ternet, ça vit.

    openbgp02# bgpctl show summary
    Neighbor     AS    MsgRcvd MsgSent OutQ Up/Down  State/PrefixRcvd
    lo openbgp01 65001   55774      47    0 00:21:49 203182

    Et ces routes ont bien été propagées à openbgp02 via la session iBGP entre les deux routeurs OpenBGPd. Openbgp02 se retrouve avec 3 routes de plus dans sa table. Ce sont les routes qui ont été propagées entre les 2 routeurs en iBGP dans le chapitre précédent.
    On va maintenant activer la même configuration sur openbgp02 pour le connecter à son peer eBGP. On force la relecture du fichier de configuration et on observe le résultat.

    [...openbgp02...]
    rereading config
    peer_ibgp = "192.168.1.1"
    peer_ebgp = "10.0.2.2"
    loopback = "192.168.2.1"
    public = "10.0.2.1"
    as_ibgp = "65001"
    as_ebgp = "65002"
    nexthop 10.0.1.2 now valid: via 192.168.3.1
    nexthop 192.168.1.1 now valid: via 192.168.3.1
    SE reconfigured
    RDE reconfigured
    neighbor 10.0.2.2 (peer eBGP):
      state change Idle -> Connect,
      reason: Start
    neighbor 10.0.2.2 (peer eBGP):
      state change Connect -> OpenSent,
      reason: Connection opened
    neighbor 10.0.2.2 (peer eBGP):
      state change OpenSent -> OpenConfirm,
      reason: OPEN message received
    neighbor 10.0.2.2 (peer eBGP):
      received notification: error in OPEN message,
      unsupported capability
    neighbor 10.0.2.2 (peer eBGP):
      received "unsupported capability"
      notification without data part,
      disabling capability announcements altogether
    neighbor 10.0.2.2 (peer eBGP):
      state change OpenConfirm -> Idle,
      reason: NOTIFICATION received
    neighbor 10.0.2.2 (peer eBGP):
      state change Idle -> Active,
      reason: Start
    neighbor 10.0.2.2 (peer eBGP):
      state change Active -> OpenSent,
      reason: Connection opened
    neighbor 10.0.2.2 (peer eBGP):
      state change OpenSent -> OpenConfirm,
      reason: OPEN message received
    neighbor 10.0.2.2 (peer eBGP):
      state change OpenConfirm -> Established,
      reason: KEEPALIVE message received

    La session est négociée entre openbgp02 et son point de peering BGP. On remarque que le routeur openbgp02 se connecte au même AS qu'openbgp01. Il aurait été possible de mettre en place une configuration de multihoming avec connexion à 2 AS différents.

    [...openbgp01...]
    nexthop 10.0.2.2 now valid: via 192.168.3.2

    Le routeur openbgp01 voit bien un nouveau nexthop via le back-to-back d'openbgp02.

    openbgp02# bgpctl show summary
    Neighbor AS MsgRcvd MsgSent OutQ Up/Down State/PrefixRcvd
    peer eBGP 65002 59538 33 0 00:11:05 203136
    lo openbgp01 65001 58682 59145 0 00:59:14 203138
    openbgp02# bgpctl show summary
    Neighbor AS MsgRcvd MsgSent OutQ Up/Down State/PrefixRcvd
    peer eBGP 65002 59538 33 0 00:11:05 203136
    lo openbgp01 65001 58682 59145 0 00:59:14 203138

    Un certain nombre de routes ont été apprises par openbgp02 en eBGP et ces routes ont été propagées à openbgp01 via la session iBGP.

    openbgp01# bgpctl show rib | head
    flags: * = Valid, > = Selected, I = via IBGP, A = Announced
    origin: i = IGP, e = EGP, ? = Incomplete
    
    flags destination gateway  lpref med aspath origin
    *>    3.0.0.0/8   10.0.1.2   100   0 65002 xASx xASx xASx xASx xASx xASx i
    I*    3.0.0.0/8   10.0.2.2   100   0 65002 xASx xASx xASx xASx xASx xASx i
    *>    4.0.0.0/8   10.0.1.2   100   0 65002 xASx xASx xASx i
    I*    4.0.0.0/8   10.0.2.2   100   0 65002 xASx xASx xASx i
    *>    4.0.0.0/9   10.0.1.2   100   0 65002 xASx xASx xASx i
    I*    4.0.0.0/9   10.0.2.2   100   0 65002 xASx xASx xASx i

    Le routeur openbgp01 connaît maintenant un certain nombre de routes vers Internet. Ces routes passent par l'un des deux routeurs BGP de l'AS 65002 avec lesquels nous nous sommes connectés. La table de routage déduite de cette table d'apprentissage fait état des décisions de routage qui ont été prises.

    openbgp01# netstat -nrf inet | head
    Routing tables
    
    Internet:
    Destination Gateway  Flags  Refs   Use    Mtu  Interface
    default     10.0.1.2   UGS     3  1444      -   dc0
    3/8         10.0.1.2   UG1     0     0      -   dc0
    4.0/9       10.0.1.2   UG1     0     0      -   dc0
    4/8         10.0.1.2   UG1     0     0      -   dc0
    4.21.41/24  10.0.1.2   UG1     0     0      -   dc0
    4.23.112/24 10.0.1.2   UG1     0     0      -   dc0

    Toutes les routes que l'on observe passent par le routeur BGP de l'AS avec lequel on est connecté. En fait, ce sont toutes les routes que l'on a apprises de ce routeur BGP.
    Vois-tu Gérard, maintenant que tu connais Internet et que tu l'as appris, il te faut changer de comportement.
    Tu es devenu un homme, maintenant, et tu ne verras plus le monde avec les mêmes yeux. Le jour où ça m'est arrivé, je me suis exclamé : "Mais je suis pas super fort, je suis mieux que ça même, je suis surpuissant."

    3.4 Et ça, c'est pour moi

    C'est pour ma pomme, ouais, tu me plais bien Gérard et j'avoue que j'ai bien envie de faire un petit quelque chose pour toi. Alors je vais te parler de Juniper Networks [12] [13], une marque de routeurs. Pourquoi Juniper ? Tout simplement parce que le système de base qui fait tourner ces machines est dérivé de FreeBSD, et là tu vois où je veux en venir.
    Très rapidement, nous allons considérer que les routeurs en face de nos serveur OpenBGPd sont des routeurs Juniper (type M7i ou M10i), respectivement jun1 comme peer BGP d'openbgp01 et jun2 connecté avec openbgp02. La configuration des sessions BGP se fait de la façon suivante :

     hr@jun1> configure
    Entering configuration mode
    
    [edit]
    hr@jun1# edit routing-options
    
    [edit routing-options]
    hr@jun1# set autonomous-system 65002
    
    [edit routing-options]
    hr@jun1# top
    
    [edit]
    hr@jun1# edit protocols bgp group OPENBGP01
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set local-as 65002 
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set peer-as 65001 
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set local-address 10.0.1.2
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set neighbor 10.0.1.1
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set import REJECT
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set type external 
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set family inet unicast
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# set export [ OPENBGP REJECT ]
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# show
    type external;
    local-address 10.0.1.2;
    import REJECT;
    family inet {
        unicast;
    }
    export [ OPENBGP REJECT ];
    peer-as 65001;
    local-as 65002;
    neighbor 10.0.1.1;
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# commit check
    configuration check succeeds
    
    [edit protocols bgp group OPENBGP01]
    hr@jun1# commit
    commit complete

    OPENBGP correspond à un policy-statement (edit policy-options policy-statement OPENBGP) qui ne permet que l'envoi des routes agrégées et dont l'AS-path contient notre AS (65002). On remarque également qu'on peut définir l'AS du routeur de façon globale ou pour chaque groupe BGP.

    [edit]
    hr@jun2# load merge terminal
    [Type ^D at a new line to end input]
    protocols {
        bgp {
            group OPENBGP02 {
                type external;
                local-address 10.0.2.2;
                import REJECT;
                family inet {
                    unicast;
                }
                export [ OPENBGP REJECT ];
                peer-as 65001;
                local-as 65002;
                neighbor 10.0.2.1;
            }
        }
    }
    load complete
    
    [edit]
    hr@jun2#

    Une fois que les 2 routeurs sont configurés, et que les configurations sont validées, on peut monter les sessions eBGP avec leurs voisins de l'AS 65001 Les sessions une fois montées, les routeurs Juniper vont émettre leurs tables de routes. La connexion peut mettre un certain temps à s'initialiser (on n'apprend pas 200000 routes en un battement de paupière), d'où les deux états de la commande suivante :

    hr@jun1> show bgp summary
    Groups: 3 Peers: 3 Down peers: 1
    Table    Tot Paths Act Paths Suppr History Damp State Pending
    inet.0      406022    202986     0       0          0       0
    bgp.l3vpn.0      0         0     0       0          0       0
    
    Peer               AS    InPkt    OutPkt OutQ Flaps Last Up/Dwn State|#Active/Received/Damped...
    aaa.bbb.ccc.ddd  xASx    83872      2837    0    13    23:35:24
    202986/203000/0      0/0/0
    eee.fff.ggg.hhh 65002 11125157  14254540    0     0     50w3d6h Establ
      inet.0: 0/203022/0
      bgp.l3vpn.0: 0/0/0
    10.0.1.1        65001        0         0    0     0       14:29 Active
    
    sbe@CLB-JUN3> show bgp summary
    Groups: 3 Peers: 3 Down peers: 0
    Table    Tot Paths  Act Paths Suppr History Damp State Pending
    inet.0      405989     202968     0       0          0       0
    bgp.l3vpn.0      0          0     0       0          0       0
    
    Peer               AS    InPkt   OutPkt OutQ Flaps Last Up/Dwn State|#Active/Received/Damped...
    aaa.bbb.ccc.ddd  xASx    84026     2844    0    13    23:39:20 202968/202982/0      0/0/0
    eee.fff.ggg.hhh 65002 11125275 14254681    0     0     50w3d6h Establ
      inet.0: 0/203004/0
      bgp.l3vpn.0: 0/0/0
    10.0.1.1        65001        2    51126    0     0          51 0/3/0                0/0/0

    On peut obtenir des informations sur les voisins BGP via la commande bgpctl show neighbor <adresse_voisin>. Ici, on utiliserait 10.0.1.2 sur openbgp01 par exemple.

    openbgp01# bgpctl show neighbor 10.0.1.2
    BGP neighbor is 10.0.1.2, remote AS 65002
     Description: peer eBGP
      BGP version 4, remote router-id 10.0.1.2
      BGP state = Established, up for 01:29:51
      Last read 00:00:01, holdtime 90s, keepalive interval 30s
      Neighbor capabilities:
        Multiprotocol extensions: IPv4 Unicast
        Route Refresh
    
      Message statistics:
                      Sent       Received
      Opens                    2          2
      Notifications            0          1
      Updates                  1      61784
      Keepalives             181         13
      Route Refresh            0          0
      Total                  184      61800
    
      Local host:              10.0.1.1, Local port:  43697
      Remote host:             10.0.1.2, Remote port:   179

    3.5 Quelle jouissance de détruire un château de sable !

    Maintenant qu'on a monté toute cette superbe mécanique, on va en casser un petit bout, juste pour voir. Gérard, tu m'as l'air intéressé, allez, tiens, regarde, je mets ma clé et tu mets la tienne. On tourne ensemble à 3, 1, 2, 3, click.
    Nous allons maintenant voir comment se comporte notre routage lorsqu'une des sessions eBGP tombe, on va faire tomber la session du routeur openbgp01 et observer comment les tables de routage sont recalculées.

    openbgp01# bgpctl neighbor 10.0.1.2 down
    request processed
    openbgp01# bgpctl show summary
    Neighbor     AS    MsgRcvd MsgSent OutQ  Up/Down  State/PrefixRcvd
    peer eBGP    65002   62023     202    0  00:00:47 Idle
    lo openbgp02 65001   61584   61633    0  01:57:13 203152
    [...openbgp01...]
    neighbor 10.0.1.2 (peer eBGP):
      state change Established -> Idle,
      reason: Stop
    Connection attempt from neighbor 10.0.1.2
      (peer eBGP) while session is in state Idle

    La session est bien tombée, les logs nous le disent. La commande bgp show summary donne aussi des informations sur l'état de la session qui est notée comme en attente.

    openbgp01# bgpctl show rib | head
    flags: * = Valid, > = Selected, I = via IBGP, A = Announced
    origin: i = IGP, e = EGP, ? = Incomplete
    
    flags destination   gateway  lpref med aspath origin
    I*>   3.0.0.0/8     10.0.2.2   100   0 65002 xASx xASx xASx xASx xASx xASx i
    I*>   4.0.0.0/8     10.0.2.2   100   0 65002 xASx xASx xASx i
    I*>   4.0.0.0/9     10.0.2.2   100   0 65002 xASx xASx xASx i
    I*>   4.21.41.0/24  10.0.2.2   100   0 65002 xASx xASx xASx xASx xASx i
    I*>   4.23.112.0/24 10.0.2.2   100   0 65002 xASx xASx xASx xASx xASx i
    I*>   4.23.113.0/24 10.0.2.2   100   0 65002 xASx xASx xASx xASx xASx i
    openbgp01# netstat -nrf inet | head
    Routing tables
    
    Internet:
    Destination Gateway     Flags  Refs   Use    Mtu  Interface
    default     10.0.1.2      UGS     3  6332      -   dc0
    3/8         192.168.3.2   UG1     0     0      -   dc1
    4.0/9       192.168.3.2   UG1     0     0      -   dc1
    4/8         192.168.3.2   UG1     0     0      -   dc1
    4.21.41/24  192.168.3.2   UG1     0     0      -   dc1
    4.23.112/24 192.168.3.2   UG1     0     0      -   dc1

    La table d'apprentissage BGP et la table de routage nous signalent que tout le trafic doit maintenant transiter par openbgp02.

    openbgp02# bgpctl show rib | head
    flags: * = Valid, > = Selected, I = via IBGP, A = Announced
    origin: i = IGP, e = EGP, ? = Incomplete
    
    flags destination   gateway lpref med aspath origin
    *>    3.0.0.0/8     10.0.2.2  100   0 65002 xASx xASx xASx xASx xASx xASx i
    *>    4.0.0.0/8     10.0.2.2  100   0 65002 xASx xASx xASx i
    *>    4.0.0.0/9     10.0.2.2  100   0 65002 xASx xASx xASx i
    *>    4.21.41.0/24  10.0.2.2  100   0 65002 xASx xASx xASx xASx xASx i
    *>    4.23.112.0/24 10.0.2.2  100   0 65002 xASx xASx xASx xASx xASx i
    *>    4.23.113.0/24 10.0.2.2  100   0 65002 xASx xASx xASx xASx xASx i

    Le routeur openbgp02 ne connaît plus que les routes apprises par la session eBGP. Les routes apprises en eBGP par openbgp01 et transmises via l'iBGP n'apparaissent plus dans la table d'apprentissage BGP. Nous avons bien obtenu une sécurité en cas de panne d'un des liens vers Internet. Cette sécurité se déclenche même lorsque c'est simplement la session eBGP qui est perdue.
    On peut remonter le lien eBGP sur openbgp01 et observer que les routes sont bien, de nouveau, apprises.

    openbgp01# bgpctl neighbor 10.0.1.2 up
    request processed
    openbgp01# bgpctl show summary
    Neighbor     AS    MsgRcvd MsgSent OutQ  Up/Down  State/PrefixRcvd
    peer eBGP    65002  116972     208    0 00:00:44 203194
    lo openbgp02 65001   61769  116320    0 02:11:28 203195

    Conclusion

    Nous sommes maintenant dans une situation de service en multihoming. Cette plate-forme est dorénavant tolérante à la panne d'un de ses liens vers internet. Ca rassure dans les chaumières. Gérard, je te colle un cigare au bec et tu me dis : "j'adore quand un plan se déroule sans accroc". Si tu n'as pas compris quelque chose, n'hésite pas à te démerder tout seul et à consulter les documents cités en référence.

    Références
    [1] http://fr.wikipedia.org/wiki/OSPF
    [2] http://fr.wikipedia.org/wiki/BGP
    [3] http://en.wikipedia.org/wiki/Multihoming
    [4] http://fr.wikipedia.org/wiki/Interior_Gateway_Protocol
    [5] http://www.ietf.org/rfc/rfc1771.txt
    [6] http://www.ietf.org/rfc/rfc2328.txt
    [7] http://www.openbsd.org/
    [8] http://www.openbsd.org/faq/faq6.html#CARP
    [9] http://www.openbsd.org/cgi-bin/man.cgi?query=ifstated
    [10] http://www.openbgpd.org/
    [11] http://unduli.bsws.de/papers/euroBSDCon2004/
    [12] http://fr.wikipedia.org/wiki/Juniper_Networks
    [13] http://www.juniper.net
    [14] http://www.bonz.org/glmf_hs0207/bgp_ospf_bsd.tar.gz

    Remerciements

    Merci à Laurent "Cariboo" Guinchard pour la précieuse aide franc-comtoise qu'il m'a apportée dans la rédaction de cet article.
    Merci aussi à George Abitbol dont l'esprit a toujours guidé mes pas.

    Posté par Stefan Berder (hr) | Signature : Stefan « hr » Berder (GCU) | Article paru dans Creative Commons License

    Laissez une réponse

    Vous devez avoir ouvert une session pour écrire un commentaire.


    • Il y a actuellement

    • 627 articles/billets en ligne.