====== eBGP (A METTRE A JOUR) ====== Tout l’eBGP se fait sur [[machines:grifon:nominoe]]. \\ Implémentation utilisée : bird 1.5.0_1 La configuration pour l’IPv4 se fait dans ''/usr/local/etc/bird.conf'' et la configuration pour l’IPv6 se fait dans ''/usr/local/etc/bird6.conf''. ===== IPv4 ===== Il faut commencer par les options de base, router-id, politique de gestion des routes, routes statiques, ce que l’on journalise, etc. # Configure logging log syslog { warning, error, fatal, bug }; # Turn on global debugging of all protocols # debug protocols all; # Override router ID and store ASN router id 89.234.186.1; define myasn = 204092; ##################### # GENERAL PROTOCOLS # ##################### # This pseudo-protocol watches all interface up/down events. protocol device { # Scan interfaces every 5 seconds scan time 5; } # test by glucas - 2016-09-13 for ibgp VPN nh # get ibgp nh protocol direct { # Restrict network interfaces we work on interface "em1"; } # This pseudo-protocol performs synchronization between BIRD's routing tables and the kernel. protocol kernel { # Don't remove routes on BIRD shutdown persist; import none; # Export to the kernel. # FreeBSD doesn't support "krt_prefsrc" :'( export all; } # Static routes # Used to announce our IP allocations and drop traffic for non-allocated IPs # (if we don't have a more specific route). Without it, traffic for our allocations go out of our AS. protocol static static_grifon_allocations { import all; route 89.234.186.0/24 unreachable; } Ensuite, on définit les filtres d’entrée. Notons que nous utilisons des templates afin de factoriser le code dans les fonctions de filtrage. Nous avons un filtre spécifique pour le VPN afin de s’assurer que ce ne soit que des /32 IPv4 qui soient annoncés (pas de route de par défaut ou du /27 réservé aux VPNs), et qu’ils soient bien dans le /25 normalement utilisable. ############### # BGP FILTERS # ############### function check_import(int peeras; ip nexthop) prefix set martians; int set reserved_asn; prefix set our_prefixes; { martians = [ 10.0.0.0/8+, 100.64.0.0/10+, 127.0.0.0/8+, 169.254.0.0/16+, 172.16.0.0/12+, 192.0.0.0/24+, 192.0.2.0/24+, 192.168.0.0/16+, 198.18.0.0/15+, 198.51.100.0/24+, 203.0.113.0/24+, 224.0.0.0/4+, 240.0.0.0/4+, 255.255.255.255/32 ]; reserved_asn = [ 0, 64297..131071, 4200000000..4294967294, 4294967295 ]; our_prefixes = [ 89.234.186.0/24+, 149.6.72.96/29+, 89.234.141.142/31+, 89.234.186.13/32, 89.234.186.14/32 ]; # Avoid too short and too long prefixes if (net.len < 8) || (net.len > 24) then return false; # Avoid 0.0.0.0/X (default route + 0.0.0.0/8) if net.ip = 0.0.0.0 then return false; # Avoid reserved networks if net ~ martians then return false; # Remove our prefixes. Only us can announce them # Remove also our interconnection prefixes. We are directly connected. if net ~ our_prefixes then return false; # Check that the next AS is our neighbour's. # Same for next-hop if bgp_path.first != peeras then return false; if bgp_next_hop != nexthop then return false; # AS_PATH too long (max seen in real life = 54) if bgp_path.len > 64 then return false; # Don't accept if path contains a reserved AS # Disabled because it removes legit prefixes # if bgp_path ~ reserved_asn then return false; return true; } function check_vpn_import() { if ! (net.len = 32 ) then return false; if ! (net ~ [ 89.234.186.0/25+ ]) then return false; else return true; } filter bgp_filter_cogent_in { if (check_import(174, 149.6.72.97)) then { # Here we can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN Cogent"; } } filter bgp_filter_arn_hwhost1_in { if (check_import(60630, 89.234.141.142)) then { # Here we can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN ARN hwhost1"; } } filter bgp_filter_arn_hwhost2_in { if (check_import(60630, 89.234.186.13)) then { # Here we can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN ARN hwhost2"; } } # For VPN filter ibgp_filter_vpn_in { if (check_vpn_import()) then accept; else reject "Prefix filtered for iBGP VPN"; } Puis les filtres de sortie. Nous remarquons que c’est ici que l’on définit l’AS prepending afin d’influer (un peu) sur le choix des routes. L’AS prepending ne fonctionne pas forcément car il est de poids plus faible que le localpref, donc si un autre AS favorise interoute par rapport à cogent, il passera par interoute même si l’AS path est plus long. # For ARN filter bgp_filter_backup_upstream_out { # Export only our IP allocations if (proto = "static_grifon_allocations") then { # Here you can set community or do AS-prepending # AS-prepending bgp_path.prepend(204092); bgp_path.prepend(204092); accept; } else { reject "Prefix filtered OUT backup upstream"; } } Pour finir, on définit nos peers BGP. Attention, il faut impérativement avoir définit les filtres avant. \\ Chaque peer est sous la même forme : « protocol bgp $peer { options; } ». Si vous ne nommez pas vos peers ($peer), il va y avoir des conflits entre eux. ################## # eBGP NEIGHBORS # # UPSTREAMS # ################## template bgp UPSTREAM { local as myasn; # Be able to see filtered routes with "sh route filtered" command import keep filtered; # Protect ourselves from massive routes leaks receive limit 620000 action block; # Announce only our IP allocations export where proto = "static_grifon_allocations"; export limit 1 action disable; } template bgp BACKUP_UPSTREAM from UPSTREAM { # Do AS-prepending here export filter bgp_filter_backup_upstream_out; # We forward traffic to ARN when we have no other choice. # BIRD preference is like Cisco weight. # With several routers, we will need to use local_pref instead. preference 50; } protocol bgp bgp_cogent from UPSTREAM { description "Cogent"; neighbor 149.6.72.97 as 174; # Local address we use to establish the BGP session source address 149.6.72.98; # We cannot use TCP-MD5 auth because we use a poorly designed OS ;) # password='' # Accept all routes from Cogent except bogons and other bad stuff import filter bgp_filter_cogent_in; } protocol bgp bgp_arn_hwhost1 from BACKUP_UPSTREAM { description "ARN-hwhost1"; neighbor 89.234.141.142 as 60630; source address 89.234.141.143; import filter bgp_filter_arn_hwhost1_in; } protocol bgp bgp_arn_hwhost2 from BACKUP_UPSTREAM { description "ARN-hwhost2"; neighbor 89.234.186.13 as 60630; source address 89.234.186.14; import filter bgp_filter_arn_hwhost2_in; } Nous avons un peer spécifique pour le VPN où nous présisons un adresse source sidd ===== IPv6 ===== Le schéma de la conf est le même qu’en IPv4. \\ On commence par les options de base, router-id, politique de gestion des routes, routes statiques, ce que l’on journalise, etc. # Configure logging log syslog { warning, error, fatal, bug }; # Turn on global debugging of all protocos # debug protocols all; # Override router ID router id 89.234.186.1; # This pseudo-protocol watches all interface up/down events. protocol device { scan time 5; # Scan interfaces every 5 seconds } # This pseudo-protocol performs synchronization between BIRD's routing tables and the kernel. protocol kernel { persist; # Don't remove routes on bird shutdown import none; # Export to kernel. This host must use that IP as source IP to initiate connections with the world export filter { # pas supporté FreeBSD # krt_prefsrc = 2a00:5881:8100::131; accept; }; } # Static routes protocol static static_grifon_allocations { import all; route 2a00:5884::/32 unreachable; } Ensuite, on définit les filtres d’entrée : ############### # BGP FILTERS # ############### function check_import(int peeras; ip nexthop) prefix set martians; int set reserved_asn; prefix set our_prefixes; { # 2001::/23 contains for example 2001:4:112::/48, belonging to AS112 # so we mustn't filter more specific # 3FFE::/16 et 5F00::/8 = formerly 6bone (IPv6 tests) martians = [ ::1/128, ::/128, ::ffff:0:0/96+, 100::/64+, 2001:db8::/32+, 2001::/23, 2001:2::/48+, 2001:10::/28+, 2002::/17+, fc00::/7, fe80::/10, ff00::/8+, 3FFE::/16+, 5F00::/8+ ]; reserved_asn = [ 0, 64297..131071, 4200000000..4294967294, 4294967295 ]; our_prefixes = [ 2a00:5884::/32+, 2001:978:2:4e::5:0/112+, 2001:470:11:cf::/64+, 2a00:5881:8100:ff00::/112+, 2a00:5884:ff::/112+ ]; # Avoid too short and too long prefixes if (net.len < 16) || (net.len > 48) then return false; # Remove default route if net = ::/0 then return false; # Avoid reserved networks if net ~ martians then return false; # Avoid bogons. IANA didn't allocate outside of 2000::/3 # but there are already announces there if ! (net.ip ~ 2000::/3) then return false; # Remove our prefixes. Only us can announce them # Remove our interconnection prefixes. We are directly connected if net ~ our_prefixes then return false; # Check that the next AS is our neighbour's. # Same for next-hop if bgp_path.first != peeras then return false; if bgp_next_hop != nexthop then return false; # AS_PATH too long (max seen in real life = 54) if bgp_path.len > 64 then return false; # Don't accept if path contains a reserved AS # Disabled because it removes legit prefixes # if bgp_path ~ reserved_asn then return false; return true; } filter bgp_filter_cogent_in { if (check_import(174, 2001:978:2:4e::5:1)) then { # Here you can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN Cogent"; } } filter bgp_filter_hurricane_electric_in { if (check_import(6939, 2001:470:11:cf::1)) then { # Here you can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN HE"; } } filter bgp_filter_arn_hwhost1_in { if (check_import(60630, 2a00:5881:8100:ff00::142)) then { # Here you can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN ARN hwhost1"; } } filter bgp_filter_arn_hwhost2_in { if (check_import(60630, 2a00:5884:ff::13)) then { # Here you can set localpref or remove a prefix, for example accept; } else { reject "Prefix filtered IN ARN hwhost2"; } } # For HE and AND filter bgp_filter_backup_upstream_out { # Export only our IP allocations if (proto = "static_grifon_allocations") then { # Here you can set community or do AS-prepending # AS-prepending bgp_path.prepend(204092); bgp_path.prepend(204092); accept; } else { reject "Prefix filtered OUT backup upstream"; } } Et pour finir, nos peers BGP. ################## # eBGP NEIGHBORS # # UPSTREAMS # ################## template bgp UPSTREAM { local as myasn; # Be able to see filtered routes with "sh route filtered" command import keep filtered; # Protect ourselves from massive routes leaks receive limit 50000 action block; # Announce only our IP allocations export where proto = "static_grifon_allocations"; export limit 1 action disable; } template bgp BACKUP_UPSTREAM from UPSTREAM { # AS-prepending + export only ARN's IP allocations export filter bgp_filter_backup_upstream_out; # We forward traffic to ARN when we have no other choice. # BIRD preference is like Cisco weight. # With several routers, we will need to use local_pref instead. preference 50; } protocol bgp bgp_cogent from UPSTREAM { description "Cogent"; neighbor 2001:978:2:4e::5:1 as 174; # Local address we use to establish the BGP session source address 2001:978:2:4e::5:2; # We cannot use TCP-MD5 auth because we use a poorly designed OS ;) # password='' # Accept all routes from Cogent except bogons and other bad stuff import filter bgp_filter_cogent_in; } protocol bgp bgp_hurricane_electric from BACKUP_UPSTREAM { description "Hurricane_Electric"; neighbor 2001:470:11:cf::1 as 6939; source address 2001:470:11:cf::2; import filter bgp_filter_hurricane_electric_in; } protocol bgp bgp_arn_hwhost1 from BACKUP_UPSTREAM { description "ARN-hwhost1"; neighbor 2a00:5881:8100:ff00::142 as 60630; source address 2a00:5881:8100:ff00::143; import filter bgp_filter_arn_hwhost1_in; } protocol bgp bgp_arn_hwhost2 from BACKUP_UPSTREAM { description "ARN-hwhost2"; neighbor 2a00:5884:ff::13 as 60630; source address 2a00:5884:ff::14; import filter bgp_filter_arn_hwhost2_in; }