Le routage sur le réseau de Grenode est géré par :

  • le protocole OSPFv2 et OSPFv3 pour le routage interne (IGP);
  • le protocole BGP pour routage externe (EGP).

Depuis le CA du 6 décembre 2014 (cf. ?20141206), Grenode utilise exclusivement Bird. Avant, nous utilisions Quagga.

Filtres Bird

Les filtres Bird utilisés sur tous les routeurs, à la fois pour OSPF et BGP, sont les suivants.

Attention, quand on écrit une fonction, c'est mieux de ne pas mettre systématiquement un "accept" ou "reject" à la fin : ça permet de composer des fonctions dans un filtre.

Filtres IPv4

function reject_rfc1918()
prefix set rfc1918;
{
    rfc1918 = [ 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+ ];
    if net ~ rfc1918 then reject;
}

# This function excludes weird networks
#  rfc1918, class D, class E
# Note: this also exclude the default route.
function reject_martians()
prefix set martians;
{
    martians = [ 169.254.0.0/16+, 224.0.0.0/4+, 240.0.0.0/4+, 0.0.0.0/32- ];
    if net ~ martians then reject;
}

# Reject weird prefix lengths
function reject_prefixlen()
prefix set invalid;
{
    invalid = [ 0.0.0.0/0{25,32}, 0.0.0.0/0{0,7} ];
    if net ~ invalid then reject;
}


function accept_connected_except_rfc1918() {
    if ( source ~ [ RTS_DEVICE, RTS_STATIC] ) then {
        reject_rfc1918();
        print "ospf net (device connected) accepted:", net;
        accept;
    }
}

# Rejette toutes les routes de Grenode, même spécifique.
function reject_within_grenode()
prefix set grenode;
{
    grenode = [ 91.216.110.0/24+, 193.33.56.0/23+, 89.234.140.0/24+ ];
    if net ~ grenode then reject;
}

# Accepte toutes les routes de Grenode, même spécifique.
function accept_within_grenode()
prefix set grenode;
{
    grenode = [ 91.216.110.0/24+, 193.33.56.0/23+, 89.234.140.0/24+ ];
    if net ~ grenode then accept;
}

# Accepte les routes agrégées de Grenode.
function accept_grenode()
prefix set grenode;
{
    grenode = [ 91.216.110.0/24, 193.33.56.0/23, 89.234.140.0/24 ];
    if net ~ grenode then accept;
}

function accept_default()
{
    if net ~ [0.0.0.0/0] then accept;
}

function reject_default()
{
    if net ~ [0.0.0.0/0] then reject;
}

Filtres IPv6

function reject_rfc1918()
prefix set martians;
{
    martians = [ FC00::/7+ ];
    if net ~ martians then reject;
}

# This function excludes weird networks
#  rfc1918, class D, class E
function reject_martians()
prefix set martians;
{
    martians = [ FE80::/10+, fec0::/10+, FF00::/8+, ::/96+, 0100::/64+,
                 2001:10::/28+, 2001:0db8::/32+, fc00::/7+ ];
    if net ~ martians then reject;
}

# Reject weird prefix lengths
function reject_prefixlen()
prefix set martians;
{
    martians = [ ::/0{49,128} ];
    if net ~ martians then reject;
}

function reject_ipsec()
prefix set net_ipsec;
{
    net_ipsec = [ 2001:912:0:FF00::0/56+ ];
    if ( net ~ net_ipsec ) then {
        reject;
    }
}

function accept_connected_except_ipsec()
{
    if ( source ~ [ RTS_DEVICE, RTS_STATIC] ) then
    {
        reject_ipsec();
        accept;
    }
}

function reject_within_grenode()
prefix set grenode;
{
    grenode = [ 2001:912:0::/36+, 2001:912:1000::/36+, 2a00:5881:4000::/40+,
                2a00:5881:c000::/40+ ];
    if net ~ grenode then reject;
}

function accept_within_grenode()
prefix set grenode;
{
    grenode = [ 2001:912:0::/36+, 2001:912:1000::/36+, 2a00:5881:4000::/40+,
    2a00:5881:c000::/40+  ];
    if net ~ grenode then accept;
}

function accept_grenode()
prefix set grenode;
{
    grenode = [ 2001:912:0::/36, 2001:912:1000::/36, 2a00:5881:4000::/40,
                2a00:5881:c000::/40 ];
    if net ~ grenode then accept;
}

function accept_default()
{
    if net ~ [ ::/0 ] then accept;
}

function reject_default()
{
    if net ~ [ ::/0 ] then reject;
}

IGP

Les aires de routage OSPF

  • aire 0.0.0.0 : batture/dummy0, safran/dummy0, lien batture-safran, et transits/peering

  • aire 0.0.0.1 : tunnels soupirail/safran et soupirail/batture

  • aire 0.0.0.8 : tunnels radeau/safran et radeau/batture

  • aire 0.0.0.9 : tunnels gaffe/safran et gaffe/batture

Remarques :

  • Il est fondamental d'inclure les interfaces de transit/peering dans l'aire 0, tout en désactivant les Hello OSPF ("stub yes" dans la conf d'interface dans Bird). Cela permet aux différents routeurs BGP (qui communiquent en iBGP) de connaître la distance vers les next-hop BGP dans l'aire 0.

Utilisation de BIRD

Routeur de bordure

Pour un routeur de bordure, type batture, on annonce la route par défaut dans OSPF. Également, on redistribue les subnets connectés (livraisons) pour que les autres routeurs de bordure y aient accès.

Configuration OSPFv2 :

# Routes envoyées dans OSPF
filter export_OSPF {
    accept_default();
    accept_within_grenode();
    accept_connected_except_rfc1918();
    reject;
}

# Routes acceptées depuis OSPF
filter import_OSPF {
    krt_prefsrc = my_krt_prefsrc;
    reject_martians();
    reject_rfc1918();
    accept;
}

protocol ospf {
    import filter import_OSPF;
    export filter export_OSPF;

    area 0.0.0.0 {
            interface "dummy0" {
                    cost 5;
                    type pointopoint;
                    hello 10; retransmit 5; wait 40; dead 40;
            };
            interface "eth0.200" {
                    cost 5;
                    type pointopoint;
                    hello 10; retransmit 5; wait 40; dead 40;
            };
            interface "eth1.116", "eth1.500", "eth1.606", "eth1.649", "eth1.945" {
                    stub yes;
            };
    };

    area 0.0.0.1 {
        ...
    };
}

Configuration OSPFv3 :

filter export_OSPF {
    accept_default();
    accept_within_grenode();
    accept_connected_except_ipsec();
    reject;
}

filter import_OSPF {
    krt_prefsrc = my_krt_prefsrc;
    reject_ipsec();
    reject_martians();
    reject_default();
    reject_rfc1918();
    accept;
}

protocol ospf {
    import filter import_OSPF;
    export filter export_OSPF;

    area 0.0.0.0 {
            interface "dummy0" {
                    cost 5;
                    type pointopoint;
                    hello 10; retransmit 5; wait 40; dead 40;
            };
            interface "eth0.200" {
                    cost 5;
                    type pointopoint;
                    hello 10; retransmit 5; wait 40; dead 40;
            };
            interface "eth1.116", "eth1.500", "eth1.606", "eth1.649", "eth1.945" {
                    stub yes;
            };
    };

    area 0.0.0.1 {
        ...
    };
}

Routeur satellite

La configuration est similaire, sauf qu'on n'annonce pas une route par défaut, et qu'on n'annonce pas les subnets connectés. Les subnets connectés sont probablement ceux de l'hébergeur de la machine (LDN, tetaneutral.net), et on n'a pas envie d'annoncer ça dans OSPF.

Configuration OSPFv2 :

# Routes
filter export_OSPF {
    accept_within_grenode();
    # Pas besoin d'annoncer les réseaux connectés (hébergeur de la machine)
    # dans OSPF
    #accept_connected_except_rfc1918();
    reject;
}

filter import_OSPF {
    krt_prefsrc = my_krt_prefsrc;
    accept_default();
    reject_martians();
    reject_rfc1918();
    accept;
}

protocol ospf {
    import filter import_OSPF;
    export filter export_OSPF;
    ...
}

EGP

Utilisation de BIRD

Depuis décembre 2014, Grenode utilise désormais Bird pour ses interconnexions externes. Pour l'instant, nous avons un seul routeur de bordure, il n'y a donc pas d'iBGP, mais il ne devrait pas y avoir grand chose à changer.

Configuration simple sur batture (pas d'iBGP) :

/* Routes a annoncer */
protocol static static_bgp {
    route 91.216.110.0/24 reject;
    route 193.33.56.0/23 reject;
    route 89.234.140.0/24 reject;   
}

/* Templates BGP */

function export_ebgp()
{
    reject_martians();
    accept_grenode();
    reject;
}

function import_ebgp()
{
    reject_martians();
    reject_within_grenode();
    accept;
}

template bgp ebgp_transit {
    local as my_as;
    preference 100;
    prefer older;
    import filter {
        krt_prefsrc = my_krt_prefsrc;
        import_ebgp();
    };
    export where export_ebgp();
}

template bgp ebgp_ix {
    local as my_as;
    preference 1000;
    prefer older;
    import filter {
        krt_prefsrc = my_krt_prefsrc;
        import_ebgp();
    };
    export where export_ebgp();
}

/* Sessions eBGP (transits) */

protocol bgp first_transit from ebgp_transit {
    description "Transit 1";
    neighbor XX.XX.XX.XX as YYYYY;
    export filter {
        bgp_path.prepend(my_as);
        bgp_path.prepend(my_as);
        export_ebgp();
    };
}

protocol bgp second_transit from ebgp_transit {
    description "Transit 2";
    neighbor XX.XX.XX.XX as YYYY;
    password "foo";
    export filter {
        bgp_path.prepend(my_as);
        bgp_path.prepend(my_as);
        export_ebgp();
    };
}

/* Sessions eBGP (peering) */

protocol bgp lyonix_rs1 from ebgp_ix {
    description "Lyonix RS1";
    neighbor 77.95.71.9 as 43100;
}

protocol bgp lyonix_rs2 from ebgp_ix {
    description "Lyonix RS2";
    neighbor 77.95.71.5 as 43100;
}

protocol bgp peering_foo from ebgp_ix {
    description "Peering foo";
    neighbor XX.XX.XX.XX as YYYY;
}