10.0.0.0/8
.10.0.0.0/8
, with path AS2 -> AS1
.AS2 -> AS2 -> AS1
. Meanwhile D tells C the same thing.AS2 -> AS2 -> AS2 -> AS1
.B -> C -> D -> B -> A
, where a loop is formed, and the packet will never reach its destination.To prevent such an accident from happening, there is an additional limitation of iBGP: If a route is announced from an router from the same AS, the route will not be announced to other routers in the same AS. Now:
But now a disaster strikes, and B and D are disconnected.
10.0.0.0/8
to D, D doesn't know how to reach the target anymore.In BGP Confederation, each router also gets a different ASN. But unlike 4, these internally-used ASNs does not have to be assigned from a NIC.
Then the ISP assigned a different internal ASN from the range to each router. While BGP routing only does bookkeeping on ASNs passed, since each router has a different ASN, it's the same as keeping the list of routers passed, and therefore a loop will not happen.
But these private ASNs aren't recognized by other networks, and may even conflict with them (when other ISPs are using them for testing, for example), so when sending the router information to another ISP, all private ASNs need to be removed, and replaced with the official ASN of the ISP assigned from NIC.
But since each router has a different ASN, how can they know if a router is "friendly" (within the same ISP) or "hostile" (from another ISP)? A common identifier can be assigned to all routers in the same ISP (called Confederation Identifier) to assist.
Suppose we have such a network topology:
10.0.0.0/8
, and when B, C, D receives that, they obtain the path:AS21 -> AS1
.AS22 -> AS21 -> AS1
or AS22 -> AS23 -> AS21 -> AS1
.AS23 -> AS21 -> AS1
or AS23 -> AS22 -> AS21 -> AS1
.AS2
, the identifier for the whole AS.AS3 -> AS2 -> AS1
.AS23 -> AS22 -> AS21 -> AS1
, and maintain normal packet forwarding.This solution preserves the decentralized nature of Internet and avoids single point failure, while also reducing the workload of NIC.。
But there is some problem when using Confederation in Bird:
A -> B -> C
and A -> B -> D -> C
at the same time, and they have the same priority. Now Bird thinks the two paths have equal length, and selects a route randomly, which may lead to unnecessary traffic detours.bgp_path.len
in Bird doesn't contain the length of Confederation, as stated above;bgp_aigp
variable is of void type. Dunno what developers are thinking.Next I will first introduce the configuration of native Confederation in Bird, then the emulation of Confederation.
I will take my DN42 network for example. Except the 4 nodes that I publically accept peerings, I have 14 other nodes that aren't open to peerings due to duplicated region, stability, or system configuration reasons. However all of them are still connected to DN42 and run Bird to exchange BGP routes.
Before I use Confederation, it's cumbersome to monitor and maintain BGP sessions between 18 nodes. The ZeroTier One VPN has stability issues from time to time, and a BGP session disconnection will occur, stopping nodes from obtaining full route information.
I had a configuration file similar to:
template bgp lantian_internal {
local as DN42_AS;
path metric 1;
direct;
enable extended messages on;
ipv4 {
next hop self yes;
import filter { ltnet_filter_v4(); };
export filter { ltnet_filter_v4(); };
};
ipv6 {
next hop self yes;
import filter { ltnet_filter_v6(); };
export filter { ltnet_filter_v6(); };
};
};
protocol bgp ltnet_other_server from lantian_internal {
neighbor NEIGHBOR_IP as DN42_AS;
};
This is a standard iBGP configuration (except that I enabled extended message and next hop self).
For Confederation I need to assign a private ASN to each node. Since my nodes are connected to both DN42 and NeoNetwork, which occupy 424242XXXX
and 420127XXXX
respectively, I chose 422547XXXX
as my private ASN range to avoid conflicts.
(No hobby network will take this range right? Right?)
Since I use ZeroTier One for my internal network, and each node gets an automatically assign IP in 172.18.0.0/24
, I simply format the ASN as 4225470000 + Last digits of IP
.
Next, let's modify Bird configuration. First set Confederation Identifier to identify friendlies:
confederation DN42_AS;
confederation member yes;
I simply used my DN42 ASN (4242422547) as Confederation Identifier, and enabled confederation member
option to tell bird that it's a friendly on the other side.
Then change the local ASN from what's assigned from DN42 into something in the private range:
local as LTNET_AS;
Next problem is deciding the ASN for the neighbor (the other side). Yes, I can fill in the neighbor ASNs one by one, but this is too much of a hassle. Luckily Bird supports setting a neighbor as "External" without specifying an ASN. Now as long as the neighbor ASN isn't the same as yours, a BGP session can be established:
neighbor NEIGHBOR_IP external;
The updated configuration file looks like:
template bgp lantian_internal {
local as LTNET_AS;
confederation DN42_AS;
confederation member yes;
path metric 1;
direct;
enable extended messages on;
ipv4 {
next hop self yes;
import filter { ltnet_filter_v4(); };
export filter { ltnet_filter_v4(); };
};
ipv6 {
next hop self yes;
import filter { ltnet_filter_v6(); };
export filter { ltnet_filter_v6(); };
};
};
protocol bgp ltnet_other_server from lantian_internal {
neighbor NEIGHBOR_IP external;
};
After modifying all configuration and running birdc configure
, check the route on one of the nodes:
# birdc show route for 172.23.0.53 all
# Only one route is kept to shorten the paragraph
BIRD 2.0.7 ready.
Table master4:
172.23.0.53/32 unicast [ltnet_hostdare 20:16:32.922 from fcf9:a876:eddd:c85a:8a93::1] * (100) [AS4242422601i]
via 172.18.0.65 on ztppir7etp
Type: BGP univ
BGP.origin: IGP
BGP.as_path: (4225470065) 4242422601
BGP.next_hop: 172.18.0.65
BGP.med: 0
BGP.local_pref: 9103
BGP.community: (64511,6) (64511,24) (64511,33) (64511,44)
BGP.large_community: (4242422601, 120, 26)
Now an ASN is put into prackets in BGP.as_path
, which is the private ASN in Confederation. From the perspective of another ASN, this route looks like:
# birdc show route for 172.23.0.53 all
# Only one route is kept to shorten the paragraph
BIRD 2.0.7 ready.
Table master4:
172.23.0.53/32 unicast [ltnet_gigsgigscloud 16:39:43.377 from fcf9:a876:ed8b:c606:ba01::1] * (100) [AS4242422601i]
via 172.18.0.1 on zt0
Type: BGP univ
BGP.origin: IGP
BGP.as_path: 4242422547 4242422601
BGP.next_hop: 172.18.0.1
BGP.local_pref: 9103
BGP.community: (64511,6) (64511,24) (64511,33) (64511,44)
BGP.large_community: (4242422601, 120, 26)
The private ASN previously in brackets is automatically replaced with 4242422547, the ASN assigned by DN42. Now when viewed from outside, the whole AS is still an whole AS.
The internal network configuration is mostly the same as Bird Confederation, assigning different ASNs and updating neighbor definitions:
# See Bird Confederation for details
local as LTNET_AS;
neighbor NEIGHBOR_IP external;
But do not add the following lines which enable Bird's own Confederation:
confederation DN42_AS;
confederation member yes;
Instead we modify all external BGP sessions and add this filter:=
export filter {
# Add this line which removes all internal ASNs
# Remember to change to your own range!
bgp_path.delete([4225470000..4225479999]);
# Other rules may exist here, but omitted
accept;
}
WARNING Again: Do not add this filter to internal peerings, or you will end up with a loop.
You need to make sure that every external BGP session is properly configured, or something interesting will happen.