-
Notifications
You must be signed in to change notification settings - Fork 0
Route Validation BIRD template
This template shows you how you can set up BIRD 1.6.3 Import filters which are commonly used on a Route Server. Obviously this is just an example, but it does show you which filters we think an IXP should filter for.
The bogon ASNs and bogon IP prefixes we use were sourced from: http://bgpfilterguide.nlnog.net/guides
The import filters which are discussed here are:
- Prefix length
- IP bogons
- AS bogons
- AS path Too Long
- The first ASN in AS_Path different then the advertising peer
- The next hop IP is different from the advertising peer IP
- The advertised prefix belongs to our Peering LAN
Usually you would like to define your constants somewhere at the beginning of your BIRD configuration so that you can easily turn the knobs of your BIRD configuration.
define RSasn = 65536;
define ipv4MaxPrefLen = 24; # RFC 7454 section 6.1.3. "Prefixes That Are Too Specific"
define ipv6MaxPrefLen = 48; # RFC 7454 section 6.1.3. "Prefixes That Are Too Specific"
define ASMaxPathLen = 64; # This number is not a universal truth, but we can assume that a path this long must be the result of a misconfiguration
You probably also want to define specific communities which you can add to a route just before you filter them. This enables you to easily identify why a route was filtered with show route filtered all
. This does mean that you need to keep filtered routes which is the following command in your peer configurations: import keep filtered on;
.
define filteredRoute = 1101; # (RSasn:1101:reason) This route was filtered
define prefixTooLong = 1; # Prefix is too long
define ipBogon = 3; # An IP Bogon was detected
define bogonASN = 4; # AS path contains a bogon AS
define pathTooLong = 5; # AS path length is longer than 64
define firstASNotPeer = 7; # First AS in path is not the same as the Peer AS
define nextHopNotPeerIp = 8; # advertised nexthop address is not the same as the peer
define IXPHijack = 101; # IXP prefix hijack
Normally you would not want anyone to advertise your peering LAN prefixes to the Internet, it might look a bit silly if you would not filter out your own Peering LAN prefixes when someone announces these to your own Route Server.
In the following example we create a list of all ECIX peering LAN prefixes which we will later use in the actual import filter.
IPv6: define IXP_net = [ 2001:7F8:8::/64, 2001:7f8:8:5::/64, 2001:7f8:8:10::/64, 2001:7f8:8:15::/64, 2001:7f8:8:20::/64, 2001:7f8:8:25::/64, 2001:748:2c:1000::/64 ];
IPv4: define IXP_net = [ 194.146.118.0/24, 194.9.117.0/24, 193.42.155.0/24, 62.69.144.0/23, 62.69.146.0/23, 194.59.190.0/24 ];
{% if bird6 %}
define ip_bogons = [
0000::/8+,
0100::/8+,
0200::/7+,
0400::/6+,
0800::/5+,
1000::/4+,
4000::/3+,
6000::/3+,
8000::/3+,
A000::/3+,
C000::/3+,
E000::/4+,
F000::/5+,
F800::/6+,
FC00::/7+,
FE00::/9+,
FE80::/10+,
FEC0::/10+,
FF00::/8+
];
{% else %}
define ip_bogons = [
0.0.0.0/0,
0.0.0.0/8+,
10.0.0.0/8+,
100.64.0.0/10,
127.0.0.0/8,
192.168.0.0/16+,
169.254.0.0/16+,
192.0.2.0/24+,
172.16.0.0/12+,
224.0.0.0/3+,
198.51.100.0/24+,
198.18.0.0/15+,
203.0.113.0/24+,
224.0.0.0/4,
240.0.0.0/4
];
define asn_bogons = [
0, # RFC 7607
23456, # RFC 4893 AS_TRANS
64496..64511, # RFC 5398 and documentation/example ASNs
64512..65534, # RFC 6996 Private ASNs
65535, # RFC 6996 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 6996 Last 32 bit ASN
];
function importScrub(int peeras) {
# Remove IP bogons
if (net ~ ip_bogons) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": Bogon prefix!";
bgp_large_community.add((RSasn,filteredRoute,ipBogon));
return false;
}
#remove prefixes longer then /24 or /64
{% if bird6 %}
if (net.len > ipv6MaxPrefLen) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": Prefix is to long: ",net.len,"!";
bgp_large_community.add((RSasn,filteredRoute,prefixTooLong));
return false;
}
{% else %}
if (net.len > ipv4MaxPrefLen) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": Prefix is to long: ",net.len,"!";
bgp_large_community.add((RSasn,filteredRoute,prefixTooLong));
return false;
}
{% endif %}
# Remove Bogon ASNs
if ( bgp_path ~ asn_bogons ) then {
print "REJECTING: ",net," received from ",from,": AS path contains a bogon AS: ",bgp_path,"!";
bgp_large_community.add((RSasn,filteredRoute,bogonASN));
return false;
}
# Make sure the AS path length is not ridiculously long
if (bgp_path.len > ASMaxPathLen) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": AS path length is ridiculously long: ",bgp_path.len,"!";
bgp_large_community.add((RSasn,filteredRoute,pathTooLong));
return false;
}
# Make sure the first AS in AS path is the customer one
if (bgp_path.first != peeras) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": First AS is not the same as Peer AS: advertised AS (",bgp_path.first,") Peer AS (",peeras,")!";
bgp_large_community.add((RSasn,filteredRoute,firstASNotPeer))
return false;
}
# Removes IXP prefixes annouced by someone else
if ((bgp_path.first != RSasn) && (net ~ ecix_net)) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": IXP prefix hijack! Peer AS (",peeras,")";
bgp_large_community.add((RSasn,filteredRoute,IXPHijack));
return false;
}
# Make sure BGP nexthop belongs to the router advertising the prefix.
if (bgp_next_hop != from) then {
print "REJECTING: ",net.ip,"/",net.len," received from ",from,": Next hop is not the same as Peer IP address: next hop (",bgp_next_hop,"), peer IP (",from,"), Peer AS (",peeras,")!";
bgp_large_community.add((RSasn,filteredRoute,nextHopNotPeerIp));
return false;
}
return true;
}
###Process incoming prefix advertisements
function importProcessing( int peeras; int set IRRDB_ASSet; int peerrtt ) {
if !(importScrub(peeras)) then reject;
#space for other filter functions such as RPKI and IRRDB filtering
accept;
}
protocol bgp 'AS1234' {
debug {events, states};
description "PEER AS65537 192.0.2.1 example_corp";
local as RSasn;
neighbor 1.2.3.4 as 65537;
rs client;
passive on;
enable route refresh on;
graceful restart on;
interpret communities off;
table master;
secondary;
export all;
import where importProcessing(65537);
import keep filtered on;
import limit 16000 action restart;
password "SuPeRSeCrEt";
}