Let packets from different BGP go to different routing tables
Hello fellow birdies, I'm having some difficulty connecting the nodes. Our network provides free IP Transit service so we need to carry downstream. We use OpenVPN/Wireguard connection between our nodes. We plan to use VLAN on OpenVPN or use GRE on Wireguard. This way, we have 2 interfaces tunnel1 and tunnel2 between each node. 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 Then we use ip rule Direct traffic to the correct routing table based on the interface. My English is not very good so I drew a picture for a description. link : https://i.postimg.cc/dtBDC4kh/photo-2022-07-12-12-54-28.jpg [image: image.png] The problem I'm having is that in IXP all BGP sessions differ only by IP or MAC. For instance: 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 we get traffic from our downstream AS1 into Table 147? We have discussed using VLANs, but VLANs are usually not allowed in IXPs. The second solution is to use the ip rule to put every prefix from the downstream into Table 147, which is very inefficient. Do you have a better solution? Thanks -- *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 the text of the email message and virus.
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.
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@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.
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@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@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.
participants (2)
-
Brandon Zhi -
Vincent Bernat