BGP: how the world's networks agree on the road
Lesson 4 of 4
4BGP: how the world's networks agree on the road
The big pictureThe OSPF you learned runs inside one network owned by one party. But who joins STC's network to Google's to a university in Japan? Nobody owns the whole internet, so each network tells its neighbours "I can reach these addresses", and the neighbours pass the news on. That is BGP, the protocol holding the internet together, and one mistake in it can hide a whole company from the world.
What the picture shows: Each AS puts its own number in front of the path before passing the announcement on. That is how the receiver knows where the road came from, and it refuses any road that already holds its own number (loop prevention).
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
Picture shipping companies between cities. Each tells its neighbours: "I deliver to Riyadh, and the road through me crosses two companies". The neighbour picks not always the fastest but the cheapest for it or the one with the better contract. BGP is that conversation between autonomous systems: each AS (a provider, a big company, a university) has a number, announces its addresses and picks roads by its policies. If a company wrongly announces "I deliver to YouTube's addresses" and the neighbours believe it, the world's traffic goes there.
BGP-4 (RFC 4271) is a path vector protocol on TCP 179 between neighbours configured by hand. eBGP runs between different ASes (administrative distance 20 on Cisco), iBGP inside one AS (200) and needs a full mesh or route reflectors. AS numbers are 16 or 32 bits (RFC 6793), with private ranges 64512–65534 and 4200000000–4294967294. Cisco's best-path order in short: highest weight, then highest Local Preference, then locally originated, then shortest AS_PATH, then origin, then lowest MED, then eBGP over iBGP, then the nearest next hop by IGP metric, then oldest path and lowest router ID. Steering outbound: Local Preference. Inbound: AS_PATH prepending and MED. Security: prefix filters and RPKI, where the address holder signs a ROA and routers validate (RFC 6811), dropping announcements from an AS that is not authorised.
Before You Start
🗺️Routing and OSPF
You know the routing table, longest match and OSPF.
6️⃣IPv6 in practice
You know /48 and /32 prefixes.
The Core Idea
1The autonomous system and the session
An AS is a network under one administration with one routing policy, and a number from a regional registry (for our region, RIPE NCC). Two BGP neighbours open a TCP session on port 179, swap their tables once, then send only updates and keepalives. There is no auto-discovery like OSPF: every neighbour is written by hand, because a link between two networks is a business contract, not an accident.
router bgp 64500 neighbor 203.0.113.1 remote-as 65001 ! provider A neighbor 198.51.100.1 remote-as 65002 ! provider B address-family ipv4 network 192.0.2.0 mask 255.255.255.0 ! announce ONLY your own prefix neighbor 203.0.113.1 prefix-list OURS out neighbor 198.51.100.1 prefix-list OURS out ip prefix-list OURS permit 192.0.2.0/24
2How does BGP pick the road?
BGP does not look at link speed. It walks a list of attributes in order, and the first one that decides ends the comparison. The three to remember: Local Preference (highest wins; you set it inside your network to decide where you exit), AS_PATH (shortest wins), and MED (lowest wins; a neighbour's hint about the best door into it).
In the first case A and C tie on path length and the lower MED decides for A. Then policy beats length, then A lengthens its path and loses.
routes = [ # three ways to reach 8.8.8.0/24 as seen by your edge routers
{"via": "provider A", "local_pref": 100, "as_path": [65001, 15169], "med": 0, "ebgp": True},
{"via": "provider B", "local_pref": 100, "as_path": [65002, 3356, 15169], "med": 0, "ebgp": True},
{"via": "partner C", "local_pref": 100, "as_path": [65003, 15169], "med": 50, "ebgp": True},
]
def best(routes):
# local pref (higher), AS path (shorter), MED (lower), eBGP over iBGP
return min(routes, key=lambda r: (-r["local_pref"], len(r["as_path"]), r["med"], not r["ebgp"]))
print("default choice:", best(routes)["via"])
routes[1]["local_pref"] = 200 # policy: provider B is cheaper, prefer it outbound
print("after policy :", best(routes)["via"])
routes[1]["local_pref"] = 100
routes[0]["as_path"] = [65001, 65001, 65001, 15169] # A prepends to push traffic away
print("after prepend :", best(routes)["via"])3iBGP inside your network
With more than one edge router, every router must know what the others learned from outside, and that is iBGP's job. A key rule: an iBGP router does not pass on what it learned from one iBGP peer to another (to avoid loops inside an AS where AS_PATH does not change), so you need a full mesh: n(n-1)/2 sessions. With 20 routers that is 190 sessions, which is why large networks use a route reflector.
This is why you never see a full mesh in big provider networks.
for n in (3, 5, 10, 20, 50):
mesh = n * (n - 1) // 2
with_rr = n - 1 # every router peers only with one reflector
print(f"{n:>3} routers: full mesh {mesh:>5} sessions | one route reflector {with_rr:>3}")4When BGP goes wrong: hijacks and RPKI
BGP was built on trust: whoever announces addresses is believed. In February 2008 Pakistan Telecom announced a more specific prefix than YouTube's to block it locally; it leaked to the world and YouTube vanished for about two hours, because the longest match always wins. On 4 October 2021 a maintenance command at Facebook withdrew the BGP routes to its own DNS servers, and Facebook, Instagram and WhatsApp disappeared for about six hours. The defence: strict filters on what you announce and accept, and RPKI: the address holder publishes a signed ROA saying "only this AS announces this prefix at this length", and routers drop anything else. And join MANRS, which bundles these practices.
This is RFC 6811 origin validation in miniature: the more specific prefix from a stranger AS is dropped.
import ipaddress
roas = [("192.0.2.0/24", 24, 64500)] # prefix, max length, authorised origin AS
def validate(prefix, origin):
net = ipaddress.ip_network(prefix)
covering = [r for r in roas if net.subnet_of(ipaddress.ip_network(r[0]))]
if not covering:
return "not-found"
ok = any(net.prefixlen <= maxlen and origin == asn for _, maxlen, asn in covering)
return "valid" if ok else "INVALID -> drop"
print("192.0.2.0/24 from AS64500:", validate("192.0.2.0/24", 64500))
print("192.0.2.0/25 from AS64999:", validate("192.0.2.0/25", 64999)) # a hijack
print("192.0.2.0/24 from AS64999:", validate("192.0.2.0/24", 64999)) # wrong origin
print("203.0.113.0/24 from AS65010:", validate("203.0.113.0/24", 65010))Worked example
The task: your company (AS 64500) connects to provider A (a cheap 1 Gbps link) and provider B (an expensive 10 Gbps one). Management wants: exit via A, entry via A, and B as backup both ways.
The answer: Outbound: set Local Preference 200 on routes from A and 100 (the default) on routes from B, so all your routers prefer A. Inbound: lengthen your path towards B by repeating your number three times (64500 64500 64500) so the world sees it as longer and prefers A. Safety: a prefix-list announcing only 192.0.2.0/24, a filter refusing your own prefixes from outside, and a ROA at RIPE for your prefix. Check: show ip bgp 0.0.0.0 must show A marked >, and a public looking glass must show your path through B as longer.
Myth vs Reality
| Myth | Reality |
|---|---|
| BGP picks the fastest road. | It picks by policy and path length in ASes; it knows nothing of link speed or congestion. |
| BGP is for providers only; company engineers never need it. | Any company with two providers, a data centre or a hybrid cloud deals with BGP. Modern data centre fabrics use it inside too. |
| Route hijacks are theoretical. | Leaks and hijacks happen almost every week, and some have hidden global services for hours. |
Where you meet it at work
🏦A dual-homed company
BGP keeps the internet working if one provider fails.
☁️Hybrid cloud
Dedicated links to AWS and Azure exchange routes over BGP.
🛰️Internet provider
Runs sessions with hundreds of neighbours and exchange points.
Test your understanding
Which port does a BGP session run on?
BGP relies on TCP for reliable delivery, on port 179.
You want all your company's traffic to exit via provider A. What do you change?
Local Preference is set inside your network and steers the exit; highest wins.
Why did YouTube vanish in 2008 even though its original announcement stayed up?
A router always prefers the longer prefix, whatever its source.
What is RPKI for?
A signed ROA ties the prefix to its allowed origin, and the router drops anything else.
How many iBGP sessions do 10 routers need in a full mesh?
n(n-1)/2 = 10×9/2 = 45.
Quick review cards
Check Your Understanding
Why does BGP not discover neighbours automatically like OSPF?
Because every session is an agreed relationship between two parties; opening one automatically is a security and business risk.
How do you make the internet come in through one particular provider?
Lengthen your AS_PATH in announcements to the other provider, or send a lower MED to the same neighbour. Remember: it is a suggestion, not an order.
What is wrong with re-announcing one provider's routes to another?
You become a transit path (a route leak) for traffic that is not yours, choking your link and possibly harming the internet.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Done with this lesson?
Sign in to save your progress.