# {{ ansible_managed }} include "/etc/bird/clear_defines.conf"; include "/etc/bird/clear_functions.conf"; define CLEARNET_PREFIP = {{ uvok_bird_opts.preferred_ip }}; # trs=transit ipv6 table t_myas_unfiltered; ipv6 table t_myas_trs; ipv6 table t_myas_babel; roa6 table clear_roa_v6; protocol rpki roa_clearnet1 { roa6 { table clear_roa_v6; }; remote 10.2.0.1; port 8282; refresh 3600; retry 600; expire 7200; } protocol rpki roa_clearnet2 { roa6 { table clear_roa_v6; }; remote 10.2.0.12; port 8282; refresh 3600; retry 600; expire 7200; } define BOGON_ASNS = [ 0, # RFC 7607 23456, # RFC 4893 AS_TRANS 64496..64511, # RFC 5398 and documentation/example ASNs 64512..65534, # RFC 6996 Private ASNs 65535, # RFC 7300 Last 16 bit ASN 65536..65551, # RFC 5398 and documentation/example ASNs 65552..131071, # RFC IANA reserved ASNs 4200000000..4294967294, # RFC 6996 Private ASNs 4294967295 ]; # RFC 7300 Last 32 bit ASN define BOGON_PREFIXES = [ ::/0, # Default route ::/8+, # RFC 4291 IPv4-compatible, loopback, et al 0100::/64+, # RFC 6666 Discard-Only 2001:2::/48+, # RFC 5180 BMWG 2001:10::/28+, # RFC 4843 ORCHID 2001:db8::/32+, # RFC 3849 documentation 2002::/16+, # RFC 7526 6to4 anycast relay 3ffe::/16+, # RFC 3701 old 6bone fc00::/7+, # RFC 4193 unique local unicast fe80::/10+, # RFC 4291 link local unicast fec0::/10+, # RFC 3879 old site local unicast ff00::/8+ # RFC 4291 multicast ]; function reject_bogon_asns() int set bogon_asns; { bogon_asns = BOGON_ASNS; if ( bgp_path ~ bogon_asns ) then { print "Reject: bogon AS_PATH: ", net, " ", bgp_path; clearnet_add_filter(FILTER_BOGON_ASN); } } function reject_bogon_prefixes() prefix set bogon_prefixes; { bogon_prefixes = BOGON_PREFIXES; if (net ~ bogon_prefixes) then { print "Reject: Bogon prefix: ", net, " ", bgp_path; clearnet_add_filter(FILTER_BOGON_PREFIX); } } define PROBLEM_PREFIXES = [ ]; function reject_problem_prefixes() prefix set problem_prefixes; { problem_prefixes = PROBLEM_PREFIXES; if (net ~ problem_prefixes) then { print "Reject: Problematic prefix: ", net, " ", bgp_path; clearnet_add_filter(FILTER_PROBLEM_PREFIX); } } function reject_long_aspaths() { if ( bgp_path.len > 50 ) then { clearnet_add_filter(FILTER_LONG_ASPATH); } } function reject_small_prefixes() { if (net.len > 55 && net.type = NET_IP6) then { print "Reject: Too small prefix: ", net, " ", bgp_path; clearnet_add_filter(FILTER_SMALL_V6_PREFIX); } } function reject_roa_rpki() { if ( roa_check(clear_roa_v6, net, bgp_path.last_nonaggregated) = ROA_INVALID ) then { clearnet_add_filter(FILTER_ROA_RPKI); } } function prefer_direct_neighbor() { if (bgp_path.len = 1) then bgp_local_pref = bgp_local_pref + 700; } function clearnet_common_import() { reject_bogon_asns(); reject_bogon_prefixes(); reject_long_aspaths(); reject_small_prefixes(); reject_problem_prefixes(); reject_roa_rpki(); prefer_direct_neighbor(); honor_graceful_shutdown(); } filter myas_export { if (proto = "myprefix") then { accept; } reject; } # route collector filter myas_f_rc { # export IXP routes after all # if ( clearnet_is_ixp() ) then reject; if (source = RTS_BGP) then accept; if (proto = "myprefix") then accept; reject; }; protocol static myprefix { {% for prefix in uvok_bird_opts.clear_prefixes %} route {{ prefix }} reject; {% endfor %}; ipv6 { # needs to be in unfiltered - because that's where I'm exporting from table t_myas_unfiltered; import all; export none; }; } protocol direct { ipv6 { table t_myas_babel; }; interface "myas_int"; }; template bgp pt_clearnet { local as CLEARNET_ASN; graceful restart on; long lived graceful restart on; prefer older on; # Neighbor as must be first route as enforce first as on; # faster updates enable extended messages on; # defaults anyway enable route refresh on; interpret communities on; direct; # higher better default bgp_local_pref 100; # my value - lower better default bgp_med 100; ipv6 { # start by importing into the unfiltered table table t_myas_unfiltered; # for inspection who's evil import keep filtered; # for RPKI / ROA import table on; import filter { clearnet_import_transit(); clearnet_common_import(); accept; }; export filter myas_export; }; } # route collector template bgp pt_rc from pt_clearnet { multihop; # yes, use unfiltered table for export ipv6 { add paths tx; import none; export filter myas_f_rc; }; } {% if uvok_bird_opts.babel_if_name %} protocol babel p_myas_babel { ipv6 { table t_myas_babel; import where source ~ [RTS_DEVICE, RTS_BABEL]; export where source ~ [RTS_DEVICE, RTS_BABEL]; }; interface "{{ uvok_bird_opts.babel_if_name }}" { }; } {% endif %} # pipe babel table => bgp table for next-hop resolution? protocol pipe { table t_myas_babel; peer table t_myas_trs; import none; export where source ~ [RTS_BABEL]; } # EXPORT FROM unfilteed TO filtered trs table protocol pipe { table t_myas_unfiltered; peer table t_myas_trs; import none; export filter { if ( bgp_large_community ~ [(CLEARNET_ASN, LC_FILTERED, *)] ) then { reject; } accept; }; } protocol kernel p_myas_i { # scan time 20; kernel table 150; ipv6 { table t_myas_babel; import none; export filter { if (source != RTS_BABEL) then { print "SHOULD NOT HAPPEN: export babel to kernel: ", net, " from", source; reject; } krt_prefsrc = CLEARNET_PREFIP; accept; }; }; }; protocol kernel pk_myas_out { kernel table 100; ipv6 { table t_myas_trs; import none; export filter { krt_prefsrc = CLEARNET_PREFIP; if (source = RTS_BGP) then { accept; } {% if uvok_bird_opts.use_fallback %} if (proto = "myas_def_fallb") then { accept; } {% endif %} reject; }; }; }; include "/etc/bird/clear_peers/*.conf"; {% if uvok_bird_opts.use_fallback %} include "clear_fallback.conf"; {% endif %}