Created
September 6, 2024 08:10
-
-
Save tonusoo/005d9ae8fe24432c733be8f12785ee9c to your computer and use it in GitHub Desktop.
RTIX Route Servers configuration for lab usage with BIRD. Tested on BIRD version 2.15.1.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
log syslog all; | |
debug protocols all; | |
router id 213.184.52.1; | |
define rtix_rs_asn = 207800; | |
# BGP ipv4/ipv6 channel option "secondary" requires | |
# routing table to be sorted. | |
ipv4 table master4 sorted; | |
ipv6 table master6 sorted; | |
# Tables for RPKI ROAs. | |
roa4 table roa_v4; | |
roa6 table roa_v6; | |
roa4 table roa_rtbh_v4; | |
roa6 table roa_rtbh_v6; | |
function next_hop_valid(int peer_as) -> bool { | |
# Explicit braces are used to avoid | |
# ambiguous "else" statements. | |
# Elkdata | |
if peer_as = 61189 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.53, 213.184.52.54 ] then { | |
return true; | |
} | |
} | |
else { | |
if bgp_next_hop ~ [ 2001:7f8:50:1:0:ef05:0:53, 2001:7f8:50:1:0:ef05:0:54 ] then { | |
return true; | |
} | |
} | |
} | |
# EENet | |
if peer_as = 3221 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.18 ] then { | |
return true; | |
} | |
} | |
else { | |
if bgp_next_hop ~ [ 2001:7f8:50:1:0:c95:0:18 ] then { | |
return true; | |
} | |
} | |
} | |
# PCH | |
if peer_as = 42 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.130 ] then { | |
return true; | |
} | |
} | |
else { | |
if bgp_next_hop ~ [ 2001:7f8:50:1:0:2a:0:130 ] then { | |
return true; | |
} | |
} | |
} | |
# TEHIK | |
if peer_as = 213172 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.226 ] then { | |
return true; | |
} | |
} | |
} | |
# OIXIO (VÕRGUVARA) | |
if peer_as = 199800 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.9 ] then { | |
return true; | |
} | |
} | |
else { | |
if bgp_next_hop ~ [ 2001:7f8:50:1:0:c95:0:9 ] then { | |
return true; | |
} | |
} | |
} | |
# STV | |
if peer_as = 61307 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.230 ] then { | |
return true; | |
} | |
} | |
else { | |
if bgp_next_hop ~ [ 2001:7f8:50:1:0:2218:0:230 ] then { | |
return true; | |
} | |
} | |
} | |
# Infonet | |
if peer_as = 8728 then { | |
if bgp_next_hop.is_v4 then { | |
if bgp_next_hop ~ [ 213.184.52.81, 213.184.52.80 ] then { | |
return true; | |
} | |
} | |
else { | |
if bgp_next_hop ~ [ 2001:7f8:50:1:0:2218:0:81, 2001:7f8:50:1:0:2218:0:80 ] then { | |
return true; | |
} | |
} | |
} | |
return false; | |
}; | |
function martian() -> bool { | |
# Modified and extended list of prefixes compared to | |
# default martians list of Junos. | |
prefix set martians_v4 = [ | |
0.0.0.0/0, # Default route | |
0.0.0.0/8{8,32}, # IANA - Local Identification | |
10.0.0.0/8{8,32}, # RFC 1918 - Private Use | |
127.0.0.0/8{8,32}, # IANA - Loopback | |
169.254.0.0/16{16,32}, # RFC 3927 - Link Local | |
172.16.0.0/12{12,32}, # RFC 1918 - Private Use | |
192.0.0.0/24{24,32}, # IETF Protocol Assignments | |
192.0.2.0/24{24,32}, # RFC 5737 - TEST-NET-1 | |
192.88.99.0/24{24,32}, # RFC 3068 - 6to4 prefix | |
192.168.0.0/16{16,32}, # RFC 1918 - Private Use | |
198.18.0.0/15{15,32}, # RFC 2544 - Network Interconnect Device Benchmark Testing | |
198.51.100.0/24{24,32}, # RFC 5737 - TEST-NET-2 | |
203.0.113.0/24{24,32}, # RFC 5737 - TEST-NET-3 | |
224.0.0.0/3{3,32}, # RFC 5771 - Multcast (formerly Class D) | |
100.64.0.0/10{10,32} # RFC 6598 - Shared Address Space | |
]; | |
prefix set martians_v6 = [ | |
::/0, # Default route | |
::/8{8,128}, # loopback, unspecified, v4-mapped | |
64:ff9b::/96{96,128}, # RFC 6052 - IPv4-IPv6 Translation | |
100::/8{8,128}, # RFC 6666 - reserved for Discard-Only Address Block | |
200::/7{7,128}, # RFC 4048 - Reserved by IETF | |
400::/6{6,128}, # RFC 4291 - Reserved by IETF | |
800::/5{5,128}, # RFC 4291 - Reserved by IETF | |
1000::/4{4,128}, # RFC 4291 - Reserved by IETF | |
2001::/33{33,128}, # RFC 4380 - Teredo prefix | |
2001:0:8000::/33{33,128}, # RFC 4380 - Teredo prefix | |
2001:2::/48{48,128}, # RFC 5180 - Benchmarking | |
2001:3::/32{32,128}, # RFC 7450 - Automatic Multicast Tunneling | |
2001:10::/28{28,128}, # RFC 4843 - Deprecated ORCHID | |
2001:20::/28{28,128}, # RFC 7343 - ORCHIDv2 | |
2001:db8::/32{32,128}, # RFC 3849 - NON-ROUTABLE range to be used for documentation purpose | |
2002::/16{16,128}, # RFC 3068 - 6to4 prefix | |
3ffe::/16{16,128}, # RFC 5156 - used for the 6bone but was returned | |
4000::/3{3,128}, # RFC 4291 - Reserved by IETF | |
5f00::/8{8,128}, # RFC 5156 - used for the 6bone but was returned | |
6000::/3{3,128}, # RFC 4291 - Reserved by IETF | |
8000::/3{3,128}, # RFC 4291 - Reserved by IETF | |
a000::/3{3,128}, # RFC 4291 - Reserved by IETF | |
c000::/3{3,128}, # RFC 4291 - Reserved by IETF | |
e000::/4{4,128}, # RFC 4291 - Reserved by IETF | |
f000::/5{5,128}, # RFC 4291 - Reserved by IETF | |
f800::/6{6,128}, # RFC 4291 - Reserved by IETF | |
fc00::/7{7,128}, # RFC 4193 - Unique Local Unicast | |
fe80::/10{10,128}, # RFC 4291 - Link Local Unicast | |
fec0::/10{10,128}, # RFC 4291 - Reserved by IETF | |
ff00::/8{8,128} # RFC 4291 - Multicast | |
]; | |
case net.type { | |
NET_IP4: return net ~ martians_v4; | |
NET_IP6: return net ~ martians_v6; | |
} | |
}; | |
function invalid_asn() -> bool { | |
# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml | |
int set invalid_asns = [ | |
# 16-bit | |
0, # Reserved. RFC7607 | |
23456, # AS_TRANS. RFC6793 | |
64496..64511, # Reserved for use in documentation and sample code. RFC5398 | |
64512..65534, # Reserved for Private Use. RFC6996 | |
65535, # Reserved. RFC7300 | |
# 32-bit | |
65536..65551, # Reserved for use in documentation and sample code. RFC5398 | |
65552..131071, # Reserved. | |
4200000000..4294967294, # Reserved for Private Use. [RFC6996] | |
4294967295 # Reserved. RFC7300 | |
]; | |
return bgp_path ~ invalid_asns; | |
}; | |
function transit_free_asn() -> bool { | |
# https://en.wikipedia.org/wiki/Tier_1_network | |
int set tier1_asns = [ | |
701, # Verizon Enterprise Solutions | |
1299, # Arelion | |
2914, # NTT Communications | |
3257, # GTT Communications | |
3320, # Deutsche Telekom Global Carrier | |
3356, # Lumen Technologies | |
3491, # PCCW Global | |
5511, # Orange | |
6453, # Tata Communications | |
6461, # Zayo Group | |
6762, # Telecom Italia Sparkle | |
6830, # Liberty Global | |
7018, # AT&T | |
12956 # Telxius | |
]; | |
return bgp_path ~ tier1_asns; | |
}; | |
function never_via_rs_asn() -> bool { | |
# Included file below contains a list of AS numbers and is | |
# periodically generated by an external script using | |
# PeeringDB API "info_never_via_route_servers" query | |
# parameter. | |
return bgp_path ~ | |
include "/etc/bird/never-via-route-servers_as_numbers.conf"; | |
}; | |
function origin_as_in_asset(int peer_as) -> bool { | |
case peer_as { | |
# Included files below are periodically generated | |
# by an external script. Content of the files | |
# is following: | |
# | |
# root@rtix-rs1:~# cat /etc/bird/AS-EENET_as_numbers.conf | |
# [ | |
# 3221,62024,203311,208283,208338 | |
# ]; | |
# root@rtix-rs1:~# | |
# Elkdata | |
61189: return bgp_path.last ~ | |
include "/etc/bird/AS61189_as_numbers.conf"; | |
# EENet (as-set: AS-EENET) | |
3221: return bgp_path.last ~ | |
include "/etc/bird/AS-EENET_as_numbers.conf"; | |
# Packet Clearing House (as-set: AS-PCH) | |
42: return bgp_path.last ~ | |
include "/etc/bird/AS-PCH_as_numbers.conf"; | |
# TEHIK | |
213172: return bgp_path.last ~ | |
include "/etc/bird/AS213172_as_numbers.conf"; | |
# OIXIO | |
199800: return bgp_path.last ~ | |
include "/etc/bird/AS199800_as_numbers.conf"; | |
# STV | |
61307: return bgp_path.last ~ | |
include "/etc/bird/AS61307_as_numbers.conf"; | |
# Infonet (as-set: AS-INFONETDC) | |
8728: return bgp_path.last ~ | |
include "/etc/bird/AS-INFONETDC_as_numbers.conf"; | |
else: return false; | |
} | |
}; | |
function prefix_in_asset(int peer_as) -> bool { | |
case peer_as { | |
# Included files below are periodically generated | |
# by an external script. Content of the files | |
# is following: | |
# | |
# root@rtix-rs1:~# cat /etc/bird/AS-EENET_v6_prefixes.conf | |
# [ | |
# 2001:bb8::/32{32,128}, | |
# 2a01:a3e0::/32{32,128}, | |
# 2a07:1180::/29{29,128}, | |
# 2a0e:e740::/29{30,128} | |
# ]; | |
# root@rtix-rs1:~# | |
# Elkdata | |
61189: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS61189_v4_prefixes.conf"; | |
NET_IP6: return net ~ | |
include "/etc/bird/AS61189_v6_prefixes.conf"; | |
} | |
# EENet (as-set: AS-EENET) | |
3221: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS-EENET_v4_prefixes.conf"; | |
NET_IP6: return net ~ | |
include "/etc/bird/AS-EENET_v6_prefixes.conf"; | |
} | |
# Packet Clearing House (as-set: AS-PCH) | |
42: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS-PCH_v4_prefixes.conf"; | |
NET_IP6: return net ~ | |
include "/etc/bird/AS-PCH_v6_prefixes.conf"; | |
} | |
# TEHIK | |
213172: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS213172_v4_prefixes.conf"; | |
} | |
# OIXIO | |
199800: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS199800_v4_prefixes.conf"; | |
NET_IP6: return net ~ | |
include "/etc/bird/AS199800_v6_prefixes.conf"; | |
} | |
# STV | |
61307: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS61307_v4_prefixes.conf"; | |
NET_IP6: return net ~ | |
include "/etc/bird/AS61307_v6_prefixes.conf"; | |
} | |
# Infonet (as-set: AS-INFONETDC) | |
8728: | |
case net.type { | |
NET_IP4: return net ~ | |
include "/etc/bird/AS-INFONETDC_v4_prefixes.conf"; | |
NET_IP6: return net ~ | |
include "/etc/bird/AS-INFONETDC_v6_prefixes.conf"; | |
} | |
else: return false; | |
} | |
}; | |
function bgp_in_v4(int peer_as) -> bool { | |
string fname = "bgp_in_v4(): "; | |
# Next three sanity checks ensure that only the | |
# v4 prefixes with v4 next-hop via v4 BGP session | |
# are allowed. | |
# Prefix or BGP neighbor address type can be something | |
# other than v4 if the function is erroneously used | |
# under some other channel than ipv4. | |
if net.type != NET_IP4 then | |
reject fname, "Not a v4 prefix. Reject ", net; | |
# Attribute "from" has a data type of "ip", which | |
# means that "is_v4" can be used to check whether | |
# the address is IPv4 or IPv6. | |
if ! from.is_v4 then | |
reject fname, "Not a v4 neighbor. Reject ", net; | |
# v4 prefixes with v6 next-hop(RFC8950) would require | |
# route server side "extended next hop" configuration, | |
# but double-check. | |
if ! bgp_next_hop.is_v4 then | |
reject fname, "v4 prefix with v6 next hop. Reject ", net; | |
# Reject too long(RFC7454 6.1.3) prefixes except when the | |
# RFC 7999 BLACKHOLE community is attached. | |
if (65535, 666) !~ bgp_community && net.len > 24 then | |
reject fname, "Prefix len ", net.len, " > 24. Reject ", net; | |
# Reject unrealistically short prefixes. | |
if net.len < 8 then | |
reject fname, "Prefix len ", net.len, " < 8. Reject ", net; | |
if martian() then | |
reject fname, "Martian prefix. Reject ", net; | |
if net ~ [ 213.184.52.0/24{24,32} ] then | |
reject fname, "RTIX peering-LAN prefix. Reject ", net; | |
# RFC7948 4.8 | |
# | |
# In case of strict mode where next-hop rewrite is not allowed | |
# even for the clients in the same AS, then the condition below | |
# could be replaced with "if bgp_next_hop != from then" check. | |
if ! next_hop_valid(peer_as) then | |
reject fname, "BGP next hop ", bgp_next_hop, " for ASN ", peer_as, " is invalid. Reject ", net; | |
if bgp_path.first != peer_as then | |
reject fname, "Invalid left-most ASN ", bgp_path.first, ". Reject ", net; | |
if bgp_path.len > 32 then | |
reject fname, "AS_PATH length ", bgp_path.len ," longer than 32. Reject ", net; | |
if invalid_asn() then | |
reject fname, "AS_PATH ", bgp_path ," contains invalid ASN. Reject ", net; | |
if transit_free_asn() then | |
reject fname, "AS_PATH ", bgp_path ," contains transit-free ASN. Reject ", net; | |
if never_via_rs_asn() then | |
reject fname, "AS_PATH ", bgp_path ," contains never-via-route-servers ASN. Reject ", net; | |
if ! origin_as_in_asset(peer_as) then | |
reject fname, "Origin ASN of ", bgp_path.last, " is not in the AS set. Reject ", net; | |
if (65535, 666) ~ bgp_community then { | |
print fname, net, " has BLACKHOLE community attached"; | |
# Approach below is somewhat problematic because if the IXP | |
# member needs to blackhole, for example, its IP transit | |
# customer prefix, then it needs to be announced with AS_PATH | |
# where the source ASN is the customer ASN. | |
# "case" statement is used in order to avoid multiple roa_check() calls. | |
# Loose(origin only) RPKI validation filtering. | |
case roa_check(roa_rtbh_v4, net, bgp_path.last) { | |
ROA_INVALID: { | |
reject fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_INVALID. Reject ", net; | |
} | |
ROA_UNKNOWN: { | |
print fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_UNKNOWN. Check IRRDB."; | |
# Loose(more specific routes are allowed) filtering on IRR database route objects. | |
if ! prefix_in_asset(peer_as) then { | |
reject fname, "Route object in IRR database missing. Reject ", net; | |
} | |
} | |
} | |
# RFC 7999 3.2. | |
if (65535, 65281) !~ bgp_community then { | |
print fname, net, " has NO-EXPORT community missing. Adding the NO-EXPORT community."; | |
bgp_community.add((65535, 65281)); | |
} | |
# Soaking address. | |
bgp_next_hop = 213.184.52.200; | |
} | |
else { | |
# Strict(both origin and max-length) RPKI validation filtering. | |
case roa_check(roa_v4, net, bgp_path.last) { | |
ROA_INVALID: { | |
reject fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_INVALID. Reject ", net; | |
} | |
ROA_UNKNOWN: { | |
print fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_UNKNOWN. Check IRRDB."; | |
# Loose(more specific routes are allowed) filtering on IRR database route objects. | |
if ! prefix_in_asset(peer_as) then { | |
reject fname, "Route object in IRR database missing. Reject ", net; | |
} | |
} | |
} | |
# RFC 8326 | |
if (65535, 0) ~ bgp_community then { | |
print fname, net, " has GRACEFUL_SHUTDOWN community attached. Set LOCAL_PREF to 0."; | |
# Triggers route server to select another path if there is any. | |
bgp_local_pref = 0; | |
} | |
} | |
return true; | |
}; | |
function bgp_in_v6(int peer_as) -> bool { | |
string fname = "bgp_in_v6(): "; | |
# Next three sanity checks ensure that only the | |
# v6 prefixes with v6 next-hop via v6 BGP session | |
# are allowed. | |
if net.type != NET_IP6 then | |
reject fname, "Not a v6 prefix. Reject ", net; | |
if from.is_v4 then | |
reject fname, "Not a v6 neighbor. Reject ", net; | |
# v6 prefixes with v4 next-hop without explicit | |
# "extended next hop" configuration get rejected | |
# before ingress filtering because of next hop | |
# and associated network prefix address family | |
# mismatch, but double-check for erroneous "extended | |
# next hop" config. | |
if bgp_next_hop.is_v4 then | |
reject fname, "v6 prefix with v4 next hop. Reject ", net; | |
if net !~ [ 2000::/3{3,128} ] then | |
reject fname, "Not a v6 Global Unicast prefix. Reject ", net; | |
# Reject too long(RFC7454 6.1.3) prefixes except when the | |
# RFC 7999 BLACKHOLE community is attached. | |
if (65535, 666) !~ bgp_community && net.len > 48 then | |
reject fname, "Prefix len ", net.len, " > 48 range. Reject ", net; | |
# Reject unrealistically short prefixes. | |
if net.len < 16 then | |
reject fname, "Prefix len ", net.len, " < 16. Reject ", net; | |
if martian() then | |
reject fname, "Martian prefix. Reject ", net; | |
if net ~ [ 2001:7f8:50:1::/64{64,128} ] then | |
reject fname, "RTIX peering-LAN prefix. Reject ", net; | |
if ! next_hop_valid(peer_as) then | |
reject fname, "BGP next hop ", bgp_next_hop, " for ASN ", peer_as, " is invalid. Reject ", net; | |
if bgp_path.first != peer_as then | |
reject fname, "Invalid left-most ASN ", bgp_path.first, ". Reject ", net; | |
if bgp_path.len > 32 then | |
reject fname, "AS_PATH length ", bgp_path.len ," longer than 32. Reject ", net; | |
if invalid_asn() then | |
reject fname, "AS_PATH ", bgp_path ," contains invalid ASN. Reject ", net; | |
if transit_free_asn() then | |
reject fname, "AS_PATH ", bgp_path ," contains transit-free ASN. Reject ", net; | |
if never_via_rs_asn() then | |
reject fname, "AS_PATH ", bgp_path ," contains never-via-route-servers ASN. Reject ", net; | |
if ! origin_as_in_asset(peer_as) then | |
reject fname, "Origin ASN of ", bgp_path.last, " is not in the AS set. Reject ", net; | |
if (65535, 666) ~ bgp_community then { | |
print fname, net, " has BLACKHOLE community attached"; | |
case roa_check(roa_rtbh_v6, net, bgp_path.last) { | |
ROA_INVALID: { | |
reject fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_INVALID. Reject ", net; | |
} | |
ROA_UNKNOWN: { | |
print fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_UNKNOWN. Check IRRDB."; | |
if ! prefix_in_asset(peer_as) then { | |
reject fname, "Route object in IRR database missing. Reject ", net; | |
} | |
} | |
} | |
# RFC 7999 3.2. | |
if (65535, 65281) !~ bgp_community then { | |
print fname, net, " has NO-EXPORT community missing. Adding the NO-EXPORT community."; | |
bgp_community.add((65535, 65281)); | |
} | |
bgp_next_hop = 2001:7f8:50:1::dead; | |
} | |
else { | |
case roa_check(roa_v6, net, bgp_path.last) { | |
ROA_INVALID: { | |
reject fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_INVALID. Reject ", net; | |
} | |
ROA_UNKNOWN: { | |
print fname, net, " ROA check for ASN ", bgp_path.last, " returned ROA_UNKNOWN. Check IRRDB."; | |
if ! prefix_in_asset(peer_as) then { | |
reject fname, "Route object in IRR database missing. Reject ", net; | |
} | |
} | |
} | |
# RFC 8326 | |
if (65535, 0) ~ bgp_community then { | |
print fname, net, " has GRACEFUL_SHUTDOWN community attached. Set LOCAL_PREF to 0."; | |
bgp_local_pref = 0; | |
} | |
} | |
return true; | |
}; | |
function bgp_out(int peer_as) -> bool { | |
string fname = "bgp_out(): "; | |
if source != RTS_BGP then | |
reject "Prefix does not originate from BGP. Reject ", net; | |
# According to an example in RTIX documentation, to instruct the | |
# route servers to distribute a particular prefix only to AS64111 | |
# and AS64222, the prefix should be tagged with communities: 0:0, | |
# 1:64111 and 1:64222. Alternatively, to announce a prefix to all | |
# RTIX members, excluding AS64333, the prefix should be tagged | |
# with community 0:64333. | |
# Extended communities are not supported. If the peer ASN uses | |
# a 16 bit ASN, then the standard or large communities can be | |
# used. Standard communities are checked first. If the peer | |
# ASN uses 32 bit ASN, then only the large communities can be | |
# used. | |
if peer_as <= 65535 then { | |
# Check standard communities. | |
if (0, peer_as) ~ bgp_community then { | |
reject fname, net, " has a (0, ", peer_as, ") community attached. Do not announce to AS", peer_as; | |
} | |
if (0, 0) ~ bgp_community && (1, peer_as) !~ bgp_community then { | |
reject fname, net, " has a (0, 0) community attached. Do not announce to AS", peer_as; | |
} | |
} | |
# Check large communities. | |
if (rtix_rs_asn, 0, peer_as) ~ bgp_large_community then | |
reject fname, net, " has a (", rtix_rs_asn, ", 0, ", peer_as, ") community attached. Do not announce to AS", peer_as; | |
if (rtix_rs_asn, 0, 0) ~ bgp_large_community && (rtix_rs_asn, 1, peer_as) !~ bgp_large_community then | |
reject fname, net, " has a (", rtix_rs_asn, ", 0, 0) community attached. Do not announce to AS", peer_as; | |
return true; | |
}; | |
template bgp rs_clients_v4 { | |
local 213.184.52.1 as rtix_rs_asn; | |
# RFC 9234 | |
# | |
# If a neighbor has a role defined and it's anything other than RS-Client, | |
# then the connection is rejected with the Role Mismatch Notification. | |
# Both local and neighbor role can be seen in the output of "birdc show | |
# protocol all <name>". | |
# | |
# Regardless if the neighbor role is RS-Client or the neighbor role | |
# is absent, then the optional transitive Only to Customer(OTC) BGP | |
# attribute is attached which ensures that if a prefix is received | |
# by a router which has the RFC 9234 roles with its BGP neighbor(s) | |
# defined, then the prefix will be advertised only to neighbors in | |
# the customer role. | |
# OTC BGP attribute can be seen in the output of "birdc show route | |
# <prefix> all". | |
local role rs_server; | |
# Ensures that route-server AS number 207800 is not inserted to the AS path, | |
# MED attribute is kept, Next Hop attribute is not touched. | |
rs client; | |
# Ignore RFC 1997 no-export(65535, 65281) and no-advertise(65535, 65282) | |
# well-known communities. This means that prefixes with those communities | |
# attached are advertised to route server clients. | |
interpret communities off; | |
# RTIX Juniper routers initiate outgoing connections. | |
passive off; | |
# Generalized TTL security mechanism(GTSM; RFC 5082). Can be enabled | |
# on a client-by-client basis. | |
ttl security off; | |
# Bidirectional Forwarding Detection can be enabled on a | |
# client-by-client basis. Requires "protocol bfd .. { .. };" | |
# configuration. | |
bfd off; | |
ipv4 { | |
# Mitigation technique for path hiding(RFC 7947 2.3.1). | |
# | |
# Do no accept only a selected(i.e best) route, but the first route | |
# that is accepted by export filters. For example, if the route | |
# server clients AS 64496 and AS 64497 both announce their customer | |
# prefix 198.51.100.0/24, announcement from the AS 64496 is | |
# selected as best by the route server and AS 64496 decides to | |
# attach the (0, 64498) community to this prefix, then the third | |
# route server client AS 64498 no longer receives the 198.51.100.0/24 | |
# prefix if "secondary" is not configured. If the "secondary" is | |
# configured, then the AS 64498 gets the 198.51.100.0/24 from AS 64497 | |
# while rest of the route server clients receive the 198.51.100.0/24 | |
# from AS 64496. | |
secondary; | |
# Received v4 prefixes can be seen with "birdc show route import table <name>.ipv4". | |
# Similar feature to Junos "show route receive-protocol bgp <neigh_addr>". | |
import table on; | |
# Filtered prefixes can be seen with "birdc show route filtered". | |
import keep filtered on; | |
# Sanity check. If the threshold below is breached, then the route server | |
# client is likely accidentally announcing a full v4 table. Avoid processing | |
# all of those prefixes in the import route filters and storing them in | |
# memory. | |
# Wait time between the session restarts is automatically incremented. | |
# Receive limit configuration can be seen in the output of "birdc show | |
# protocols all <name>". | |
receive limit 50000 action restart; | |
}; | |
}; | |
template bgp rs_clients_v6 { | |
local 2001:7f8:50:1::1 as rtix_rs_asn; | |
# Settings below are basically identical to v4 config. | |
local role rs_server; | |
rs client; | |
interpret communities off; | |
passive off; | |
ttl security off; | |
bfd off; | |
ipv6 { | |
secondary; | |
import table on; | |
import keep filtered on; | |
receive limit 8000 action restart; | |
}; | |
}; | |
protocol device { | |
# On modern Linux, the interface status changes | |
# are notified asynchronously. Scanning of interfaces | |
# is needed only in order to avoid confusion by lost | |
# notification messages. | |
scan time 10; | |
}; | |
protocol rpki routinator1 { | |
# Local cache server(Routinator 3000). RPKI-to-Router | |
# (RTR) protocol receives and maintains a set of ROAs | |
# from a cache server. | |
remote "127.0.0.1" port 3323; | |
# Without "keep" the cache server can override the | |
# time periods below. Active "retry", "refresh" and | |
# "expire" timers can be seen in the output of | |
# "birdc show protocol all routinator1". | |
retry keep 5; | |
refresh keep 30; | |
expire keep 600; | |
roa4 { | |
table roa_v4; | |
}; | |
roa6 { | |
table roa_v6; | |
}; | |
}; | |
protocol rpki routinator1_rtbh { | |
remote "127.0.0.1" port 3323; | |
retry keep 5; | |
refresh keep 30; | |
expire keep 600; | |
ignore max length; | |
roa4 { | |
table roa_rtbh_v4; | |
}; | |
roa6 { | |
table roa_rtbh_v6; | |
}; | |
}; | |
protocol rpki routinator2 { | |
# Remote cache server(Routinator 3000). Remote validator | |
# has a SSH subsystem defined which acts as a proxy for | |
# locally running Routinator instance. | |
remote "10.10.52.215" port 22; | |
# BIRD needs to be compiled with libssh support. | |
transport ssh { | |
bird private key "/home/bird/.ssh/id_ed25519"; | |
remote public key "/home/bird/.ssh/known_hosts"; | |
user "rpki"; | |
}; | |
retry keep 5; | |
refresh keep 30; | |
expire keep 600; | |
roa4 { | |
table roa_v4; | |
}; | |
roa6 { | |
table roa_v6; | |
}; | |
}; | |
protocol rpki routinator2_rtbh { | |
remote "10.10.52.215" port 22; | |
transport ssh { | |
bird private key "/home/bird/.ssh/id_ed25519"; | |
remote public key "/home/bird/.ssh/known_hosts"; | |
user "rpki"; | |
}; | |
retry keep 5; | |
refresh keep 30; | |
expire keep 600; | |
ignore max length; | |
roa4 { | |
table roa_rtbh_v4; | |
}; | |
roa6 { | |
table roa_rtbh_v6; | |
}; | |
}; | |
# v4 sessions. | |
protocol bgp elkdata1_v4 from rs_clients_v4 { | |
description "Elkdata"; | |
neighbor 213.184.52.53 as 61189; | |
ipv4 { | |
# Import statement below is a | |
# shorthand for: | |
# | |
# import filter { | |
# if bgp_in_v4(61189) then | |
# accept; | |
# else | |
# reject; | |
# }; | |
import where bgp_in_v4(61189); | |
export where bgp_out(61189); | |
}; | |
}; | |
protocol bgp elkdata2_v4 from rs_clients_v4 { | |
description "Elkdata"; | |
neighbor 213.184.52.54 as 61189; | |
ipv4 { | |
import where bgp_in_v4(61189); | |
export where bgp_out(61189); | |
}; | |
}; | |
protocol bgp eenet1_v4 from rs_clients_v4 { | |
description "EENet"; | |
neighbor 213.184.52.18 as 3221; | |
# TCP MD5 authentication. RFC 2385. | |
password "5V28TQo7GS2tRrW4"; | |
ipv4 { | |
import where bgp_in_v4(3221); | |
export where bgp_out(3221); | |
}; | |
}; | |
protocol bgp pch1_v4 from rs_clients_v4 { | |
description "Packet Clearing House"; | |
neighbor 213.184.52.130 as 42; | |
ipv4 { | |
import where bgp_in_v4(42); | |
export where bgp_out(42); | |
}; | |
}; | |
protocol bgp tehik1_v4 from rs_clients_v4 { | |
description "TEHIK"; | |
neighbor 213.184.52.226 as 213172; | |
ipv4 { | |
import where bgp_in_v4(213172); | |
export where bgp_out(213172); | |
}; | |
}; | |
protocol bgp oixio1_v4 from rs_clients_v4 { | |
description "OIXIO (VORGUVARA)"; | |
neighbor 213.184.52.9 as 199800; | |
ipv4 { | |
import where bgp_in_v4(199800); | |
export where bgp_out(199800); | |
}; | |
}; | |
protocol bgp stv1_v4 from rs_clients_v4 { | |
description "STV"; | |
neighbor 213.184.52.230 as 61307; | |
ipv4 { | |
import where bgp_in_v4(61307); | |
export where bgp_out(61307); | |
}; | |
}; | |
protocol bgp infonet1_v4 from rs_clients_v4 { | |
description "Infonet"; | |
neighbor 213.184.52.81 as 8728; | |
ipv4 { | |
import where bgp_in_v4(8728); | |
export where bgp_out(8728); | |
}; | |
}; | |
protocol bgp infonet2_v4 from rs_clients_v4 { | |
description "Infonet"; | |
neighbor 213.184.52.80 as 8728; | |
ipv4 { | |
import where bgp_in_v4(8728); | |
export where bgp_out(8728); | |
}; | |
}; | |
# v6 sessions. | |
protocol bgp elkdata1_v6 from rs_clients_v6 { | |
description "Elkdata"; | |
neighbor 2001:7f8:50:1:0:ef05:0:53 as 61189; | |
ipv6 { | |
import where bgp_in_v6(61189); | |
export where bgp_out(61189); | |
}; | |
}; | |
protocol bgp elkdata2_v6 from rs_clients_v6 { | |
description "Elkdata"; | |
neighbor 2001:7f8:50:1:0:ef05:0:54 as 61189; | |
ipv6 { | |
import where bgp_in_v6(61189); | |
export where bgp_out(61189); | |
}; | |
}; | |
protocol bgp eenet1_v6 from rs_clients_v6 { | |
description "EENet"; | |
neighbor 2001:7f8:50:1:0:c95:0:18 as 3221; | |
password "5V28TQo7GS2tRrW4"; | |
ipv6 { | |
import where bgp_in_v6(3221); | |
export where bgp_out(3221); | |
}; | |
}; | |
protocol bgp pch1_v6 from rs_clients_v6 { | |
description "Packet Clearing House"; | |
neighbor 2001:7f8:50:1:0:2a:0:130 as 42; | |
ipv6 { | |
import where bgp_in_v6(42); | |
export where bgp_out(42); | |
}; | |
}; | |
protocol bgp oixio1_v6 from rs_clients_v6 { | |
description "OIXIO (VORGUVARA)"; | |
neighbor 2001:7f8:50:1:0:c95:0:9 as 199800; | |
ipv6 { | |
import where bgp_in_v6(199800); | |
export where bgp_out(199800); | |
}; | |
}; | |
protocol bgp stv1_v6 from rs_clients_v6 { | |
description "STV"; | |
neighbor 2001:7f8:50:1:0:2218:0:230 as 61307; | |
ipv6 { | |
import where bgp_in_v6(61307); | |
export where bgp_out(61307); | |
}; | |
}; | |
protocol bgp infonet1_v6 from rs_clients_v6 { | |
description "Infonet"; | |
neighbor 2001:7f8:50:1:0:2218:0:81 as 8728; | |
ipv6 { | |
import where bgp_in_v6(8728); | |
export where bgp_out(8728); | |
}; | |
}; | |
protocol bgp infonet2_v6 from rs_clients_v6 { | |
description "Infonet"; | |
neighbor 2001:7f8:50:1:0:2218:0:80 as 8728; | |
ipv6 { | |
import where bgp_in_v6(8728); | |
export where bgp_out(8728); | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment