Let packets from different BGP go to different routing tables

Brandon Zhi Brandon at huize.asia
Wed Jul 13 14:32:58 CEST 2022


The message below is the configuration for bird that I have written.

router id 103.147.22.92;

roa4 table r4;
roa6 table r6;
ipv6 table bgp_v6; #For allowed to carry downstream
ipv6 table bgp_v6_own; #For not allowed to carry downstream

log syslog all;


define LOCAL_ASN = 141011;



protocol static BGP_Prefix{
ipv6;
route 2a0c:e640:1019::/48 reject;
#route 2a0c:e640:1011::/48 via 2a0c:e640:1011::1;
}

protocol kernel { # For bgp that allow downstream
kernel table 147;
ipv6 {
table bgp_v6;
export filter {
krt_realm = 3;
accept;
};
import all;
};
}

protocol kernel { # For bgp that don't allow downstream
kernel table 247;
ipv6 {
table bgp_v6_own;
export filter {
krt_realm = 1;
accept;
};
import all;
};
}

protocol kernel {
learn;
# persist;
ipv6 {
import all;
export filter {
#krt_prefsrc = 2a0c:e640:101a::1;
accept;
};
};
}


protocol device {
scan time 60;
}

protocol direct {
#interface "dummy*";
ipv6 {
import all;
export all;
};
}

function net_len_too_long(){
case net.type {
NET_IP4: return net.len > 24; # IPv4 CIDR 大于 /24 为太长
NET_IP6: return net.len > 48; # IPv6 CIDR 大于 /48 为太长
else: print "net_len_too_long: unexpected net.type ", net.type, " ", net;
return false;
}
}

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_V4 = [
0.0.0.0/8+, # RFC 1122 'this' network
10.0.0.0/8+, # RFC 1918 private space
100.64.0.0/10+, # RFC 6598 Carrier grade nat space
127.0.0.0/8+, # RFC 1122 localhost
169.254.0.0/16+, # RFC 3927 link local
172.16.0.0/12+, # RFC 1918 private space
192.0.2.0/24+, # RFC 5737 TEST-NET-1
192.88.99.0/24+, # RFC 7526 deprecated 6to4 relay anycast. If you wish to
allow this, change `24+` to `24{25,32}`(no more specific)
192.168.0.0/16+, # RFC 1918 private space
198.18.0.0/15+, # RFC 2544 benchmarking
198.51.100.0/24+, # RFC 5737 TEST-NET-2
203.0.113.0/24+, # RFC 5737 TEST-NET-3
224.0.0.0/4+, # multicast
240.0.0.0/4+ # reserved
];
define BOGON_PREFIXES_V6 = [
::/8+, # RFC 4291 IPv4-compatible, loopback, et al
0100::/64+, # RFC 6666 Discard-Only
2001::/32{33,128}, # RFC 4380 Teredo, no more specific
2001:2::/48+, # RFC 5180 BMWG
2001:10::/28+, # RFC 4843 ORCHID
2001:db8::/32+, # RFC 3849 documentation
2002::/16+, # RFC 7526 deprecated 6to4 relay anycast. If you wish to allow
this, change `16+` to `16{17,128}`(no more specific)
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 is_bogon_prefix() {
case net.type {
NET_IP4: return net ~ BOGON_PREFIXES_V4;
NET_IP6: return net ~ BOGON_PREFIXES_V6;
else: print "is_bogon_prefix: unexpected net.type ", net.type, " ", net;
return false;
}
}

function is_bogon_asn() {
if bgp_path ~ BOGON_ASNS then return true;
return false;
}

protocol rpki {
# debug all;

roa4 { table r4; };
roa6 { table r6; };

# Please, do not use rpki-validator.realmv6.org in production
remote "rtr.rpki.cloudflare.com" port 8282;

retry keep 5;
refresh keep 30;
expire 600;
}

filter peer_in_v6 {
if is_bogon_asn() then {
print "is bogon asn", net, " for ASN ", bgp_path.last;
reject;
}
if is_bogon_prefix() then {
print "is bogon prefix", net, " for ASN ", bgp_path.last;
reject;
}
if (roa_check(r6, net, bgp_path.last) = ROA_INVALID) then
{
print "Ignore RPKI invalid ", net, " for ASN ", bgp_path.last;
reject;
}
accept;
}

function my_opt_prefix()
prefix set allowed_prefix;
int set allowed_prefix_origins;
{
include "/etc/bird/filters/allowed_prefix.conf";
if net ~ allowed_prefix then return true;
else return false;
}

function is_bogon() {
if is_bogon_asn() then return true;
if is_bogon_prefix() then return true;
if net_len_too_long() then return true;
return false;
}

function bgp_export()
prefix set allowed_prefix;
int set allowed_prefix_origins;
{
include "/etc/bird/filters/allowed_prefix.conf";
# print AS_HUIZE;
if net !~ allowed_prefix then {
# if net ~ OUR_PREFIXES then print " net",net," is not echo to AS_HUIZE";
return false;
}
if is_bogon() then return false;
if bgp_large_community ~ [(141011, 4, 23000)] then return false;
if proto = "BGP_Prefix" then return true;
if source != RTS_BGP then return false;
if bgp_large_community !~ [(141011, 2, 1)] then return false;
return true;
}

function bgp_export_all() {
if bgp_export() then return true;
if is_bogon_asn() then return false;
if is_bogon_prefix() then return false;
if source != RTS_BGP then return false;
return true;
}

function bgp_export_downstream() {
if is_bogon_asn() then return false;
if is_bogon_prefix() then return false;
if source != RTS_BGP then return false;
if bgp_large_community ~ [(141011, 4, 31000)] then return false;
if bgp_large_community !~ [(141011, 2, 100)] then return false;
return true;
}

template bgp tpl_bgp {
allow bgp_local_pref on;
graceful restart on;
local as LOCAL_ASN;
ipv6 {
table bgp_v6;
preference 110;
next hop self;
import filter{
if is_bogon_asn() then {
print "is bogon asn", net, " for ASN ", bgp_path.last;
reject;
}
if is_bogon_prefix() then {
print "is bogon prefix", net, " for ASN ", bgp_path.last;
reject;
}
if (roa_check(r6, net, bgp_path.last) = ROA_INVALID) then
{
print "Ignore RPKI invalid ", net, " for ASN ", bgp_path.last;
reject;
}
bgp_large_community.delete([(141011, 2, *)]);
bgp_large_community.delete([(141011, 1, *)]);
bgp_large_community.delete([(141011, 3, *)]);
bgp_large_community.add((141011, 3, 31000));
accept;
};

export filter{
#if my_opt_prefix() then bgp_path.prepend(LOCAL_ASN);
if bgp_export() then accept;
if bgp_export_downstream() then accept;
else reject;
};
};
}
template bgp tpl_bgp_own {
allow bgp_local_pref on;
graceful restart on;
local as LOCAL_ASN;
ipv6 {
table bgp_v6_own;
preference 110;
next hop self;
import filter{
if is_bogon_asn() then {
print "is bogon asn", net, " for ASN ", bgp_path.last;
reject;
}
if is_bogon_prefix() then {
print "is bogon prefix", net, " for ASN ", bgp_path.last;
reject;
}
if (roa_check(r6, net, bgp_path.last) = ROA_INVALID) then
{
print "Ignore RPKI invalid ", net, " for ASN ", bgp_path.last;
reject;
}
bgp_large_community.delete([(141011, 2, *)]);
bgp_large_community.delete([(141011, 1, *)]);
bgp_large_community.delete([(141011, 3, *)]);
bgp_large_community.add((141011, 1, 31000));
accept;
};

export filter{
#if my_opt_prefix() then bgp_path.prepend(LOCAL_ASN);
if bgp_export() then accept;
#if bgp_export_downstream() then accept;
else reject;
};
};
}

template bgp tpl_ibgp {
local as LOCAL_ASN;
graceful restart;
rr client;
direct;
ipv6 {
table bgp_v6;
next hop self;
import filter {
#if bgp_path ~ [= 141011 =] then bgp_path.delete(141011);
if is_bogon_asn() then {
print "is bogon asn", net, " for ASN ", bgp_path.last;
reject;
}
if is_bogon_prefix() then {
print "is bogon prefix", net, " for ASN ", bgp_path.last;
reject;
}
# if bgp_path ~ [= =] then {
# #bgp_path.prepend(LOCAL_ASN);
# if my_opt_prefix() then bgp_path.prepend(LOCAL_ASN);
# }
accept;
};
export filter {
if net ~ 2a0c:e640:1011::/48 then bgp_large_community.add((141011, 4,
27000));
if net ~ 2a0c:e640:1011::/48 then bgp_large_community.add((141011, 4,
24000));
if net ~ 2a0c:e640:1011::/48 then bgp_large_community.add((141011, 4,
21000));
#if net ~ 2a0c:e640:101a::/48 then bgp_large_community.add((141011, 4,
24000));
#if net ~ 2a0c:e640:101a::/48 then bgp_large_community.add((141011, 4,
21000));
#if net ~ 2a0c:e640:101a::/48 then bgp_large_community.add((141011, 4,
27000));
#if net ~ 2a0c:e640:101a::/48 then bgp_large_community.add((141011, 2, 1));
if proto = "BGP_Prefix" then bgp_large_community.add((141011, 2, 1));
# if my_opt_prefix() then bgp_path.prepend(LOCAL_ASN);
if bgp_export_all() then accept;
reject;
};
};
}


template bgp tpl_ibgp_own {
# ibgp transfer table which cannot have downstream
local as LOCAL_ASN;
graceful restart;
rr client;
direct;
ipv6 {
table bgp_v6_own;
next hop self;
import filter {
#if bgp_path ~ [= 141011 =] then bgp_path.delete(141011);
if is_bogon_asn() then {
print "is bogon asn", net, " for ASN ", bgp_path.last;
reject;
}
if is_bogon_prefix() then {
print "is bogon prefix", net, " for ASN ", bgp_path.last;
reject;
}
# if bgp_path ~ [= =] then {
# #bgp_path.prepend(LOCAL_ASN);
# if my_opt_prefix() then bgp_path.prepend(LOCAL_ASN);
# }
accept;
};
export filter {
if proto = "BGP_Prefix" then bgp_large_community.add((141011, 2, 1));
if bgp_export_all() then accept;
reject;
};
};
}

protocol pipe { # Synchronize the routing table that can carry downstream
and cannot be written to the main routing table
table bgp_v6;
peer table master6;
export all;
import where proto = "BGP_Prefix" ; #Synchronize the prefixes that the
local machine needs to announce into 2 tables for BGP
}

protocol pipe {
table bgp_v6_own;
peer table master6;
export all;
import where proto = "BGP_Prefix";
}



include "/etc/bird/peers/*";

Brandon Zhi <Brandon at huize.asia> 於 2022年7月13日週三 下午1:20寫道:

> Hi Vincent,
>
> Thanks for helping.
>
> Well, I have already done it.
>
> Our real problem is how to get the packets from downstream to the routing
> table I need.
>
> Because bird is just a software for importing or exporting routing tables,
> it is the Linux kernel that is really responsible for forwarding packets.
>
> In the case where I don't set any ip rule, all packets will use a routing
> table called main.
>
> Is there any way I can achieve this?
>
>
> We have only one interface for BGP:      ens18
> And our IP Address is:  2a0f:5707:ffe3::57 AS141011
> Our customers assume is: 2a0f:5707:ffe3::1 AS1
> Our upstream which allowed downstream:2a0f:5707:ffe3::30 AS6939
>
> Therefore we have a BGP session with AS1 and a BGP session with AS6939
> AS6939 > Table 147
>
> How should I make the traffic from AS1 (2a0f:5707:ffe3::1) use table 147?
>
>
>
> Vincent Bernat <bernat at luffy.cx> 於 2022年7月13日週三 上午8:03寫道:
>
>> On 2022-07-13 08:08, Brandon Zhi wrote:
>>
>> > We created a bgp_v6 (IBGP) session on tunnel1 that allows downstream
>> BGP
>> > sessions like HE(Hurricane Electric) and put the routing table into
>> > table 147.
>> >
>> > Create bgp_v6_own(IBGP) on tunnel2 to transmit those routing tables
>> from
>> > BGP that cannot carry downstream to Table 247
>>
>> You can use the pipe protocol to copy some routes from one table to the
>> other. So, you'll need one table to receive routes from BGP, then you
>> can have two "pipe" protocols to copy them on table 147 and table 247.
>>
>
>
> --
> *Brandon Zhi*
> HUIZE LTD
>
> www.huize.asia  <https://huize.asia/>| www.ixp.su | Twitter
> <https://twitter.com/zhihuiyuze>
>
>
> This e-mail and any attachments or any reproduction of this e-mail in
> whatever manner are confidential and for the use of the addressee(s) only.
> HUIZE LTD can’t take any liability and guarantee of the text of the email
> message and virus.
>


-- 
*Brandon Zhi*
HUIZE LTD

www.huize.asia  <https://huize.asia/>| www.ixp.su | Twitter
<https://twitter.com/zhihuiyuze>


This e-mail and any attachments or any reproduction of this e-mail in
whatever manner are confidential and for the use of the addressee(s) only.
HUIZE LTD can’t take any liability and guarantee of the text of the email
message and virus.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://trubka.network.cz/pipermail/bird-users/attachments/20220713/e97b26c0/attachment.htm>


More information about the Bird-users mailing list