External sessions and next-hop-self
Bring up the edges' external sessions now, using the same policy as the previous lesson: edge1 gets TRANSIT-IN/TRANSIT-OUT, and edge2 gets IX-IN/IX-OUT. Then look at what the rest of the network makes of the routes the edges learn.
When an edge passes an eBGP route to an iBGP peer, BGP doesn't change the next hop by default. The upstream's default route arrives at core1 with next hop 203.0.113.0, the upstream's end of edge1's transit link. That address isn't in OSPF (external links never are), so core1 has no way to reach it. The route is inaccessible: it sits in the BGP table but isn't used.
On the edges, it's worse. VyOS turns on FRR's resolve-via-default, which lets BGP resolve a next hop using the default route. edge1 learns the IX member's prefix from edge2 with next hop 192.0.2.40, finds no specific route to it, and resolves it via the default route. So edge1 would quietly send IX traffic to the upstream. Nothing is down and nothing warns you; the traffic just takes the expensive path.
The fix is one line on each edge: nexthop-self on the iBGP peer group. The edge then advertises itself (its loopback, the session's source address) as the next hop, which every router can reach via OSPF.
set policy prefix-list OUR-PREFIXES rule 10 action 'permit'
set policy prefix-list OUR-PREFIXES rule 10 prefix '198.51.100.0/24'
set policy prefix-list OUR-PREFIXES-ANY rule 10 action 'permit'
set policy prefix-list OUR-PREFIXES-ANY rule 10 prefix '198.51.100.0/24'
set policy prefix-list OUR-PREFIXES-ANY rule 10 le '32'
set policy prefix-list BOGONS rule 10 action 'permit'
set policy prefix-list BOGONS rule 10 prefix '0.0.0.0/8'
set policy prefix-list BOGONS rule 10 le '32'
set policy prefix-list BOGONS rule 20 action 'permit'
set policy prefix-list BOGONS rule 20 prefix '10.0.0.0/8'
set policy prefix-list BOGONS rule 20 le '32'
set policy prefix-list BOGONS rule 30 action 'permit'
set policy prefix-list BOGONS rule 30 prefix '100.64.0.0/10'
set policy prefix-list BOGONS rule 30 le '32'
set policy prefix-list BOGONS rule 40 action 'permit'
set policy prefix-list BOGONS rule 40 prefix '127.0.0.0/8'
set policy prefix-list BOGONS rule 40 le '32'
set policy prefix-list BOGONS rule 50 action 'permit'
set policy prefix-list BOGONS rule 50 prefix '169.254.0.0/16'
set policy prefix-list BOGONS rule 50 le '32'
set policy prefix-list BOGONS rule 60 action 'permit'
set policy prefix-list BOGONS rule 60 prefix '172.16.0.0/12'
set policy prefix-list BOGONS rule 60 le '32'
set policy prefix-list BOGONS rule 70 action 'permit'
set policy prefix-list BOGONS rule 70 prefix '192.168.0.0/16'
set policy prefix-list BOGONS rule 70 le '32'
set policy prefix-list BOGONS rule 80 action 'permit'
set policy prefix-list BOGONS rule 80 prefix '224.0.0.0/3'
set policy prefix-list BOGONS rule 80 le '32'
set policy route-map TRANSIT-OUT rule 10 action 'permit'
set policy route-map TRANSIT-OUT rule 10 match ip address prefix-list 'OUR-PREFIXES'
set policy route-map TRANSIT-OUT rule 100 action 'deny'
set policy route-map TRANSIT-IN rule 10 action 'deny'
set policy route-map TRANSIT-IN rule 10 match ip address prefix-list 'BOGONS'
set policy route-map TRANSIT-IN rule 20 action 'deny'
set policy route-map TRANSIT-IN rule 20 match ip address prefix-list 'OUR-PREFIXES-ANY'
set policy route-map TRANSIT-IN rule 30 action 'permit'
set policy route-map TRANSIT-IN rule 30 set local-preference '100'
set protocols bgp neighbor 203.0.113.0 remote-as '64496'
set protocols bgp neighbor 203.0.113.0 description 'UPSTREAM transit'
set protocols bgp neighbor 203.0.113.0 address-family ipv4-unicast route-map export 'TRANSIT-OUT'
set protocols bgp neighbor 203.0.113.0 address-family ipv4-unicast route-map import 'TRANSIT-IN'
set protocols bgp neighbor 203.0.113.0 address-family ipv4-unicast maximum-prefix '1000'
set protocols bgp neighbor 203.0.113.0 address-family ipv4-unicast soft-reconfiguration inbound- Lines 1–5: What we announce (exact) and what we must never accept (anything inside our space).
- Lines 6–29: Bogons, as before.
- Lines 30–32: Export: only the aggregate.
- Lines 33–38: Import: drop bogons and our own space, local preference 100. edge2 has the same with IX-IN at 150.
- Lines 39–44: The upstream session, now on edge1.
vyos@core1:~$ show ip bgp summary
IPv4 Unicast Summary:
BGP router identifier 198.51.100.241, local AS number 64500 VRF default vrf-id 0
BGP table version 2
RIB entries 5, using 800 bytes of memory
Peers 2, using 60 KiB of memory
Peer groups 1, using 72 bytes of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
198.51.100.242 4 64500 4 4 2 0 0 00:00:08 2 2 edge1
198.51.100.243 4 64500 4 4 2 0 0 00:00:08 1 2 edge2
Total number of neighbors 2
vyos@core1:~$ show ip bgp
BGP table version is 2, local router ID is 198.51.100.241, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
i 0.0.0.0/0 203.0.113.0 0 100 0 64496 i
*> 198.51.100.0/24 0.0.0.0 0 32768 i
*> 198.51.100.0/25 0.0.0.0 0 32768 i
i 203.0.113.64/26 192.0.2.40 0 150 0 64502 i
i 203.0.113.128/25 203.0.113.0 0 100 0 64496 i
Displayed 5 routes and 5 total paths
vyos@core1:~$ show bgp ipv4 0.0.0.0/0
BGP routing table entry for 0.0.0.0/0, version 0
Paths: (1 available, no best path)
Not advertised to any peer
64496
203.0.113.0 (inaccessible) from 198.51.100.242 (198.51.100.242)
Origin IGP, metric 0, localpref 100, invalid, internal
Last update: Fri Oct 16 23:35:53 2026- Lines 11–12: Both iBGP sessions up, routes received…
- Line 25: …but the external routes have no
*or>: not valid, not best, not used. - Line 28: The IX route's next hop is the member's address on the IX LAN, which core1 can't reach either.
- Lines 37–38:
inaccessible: core1 has no route to 203.0.113.0, the far end of edge1's transit link.
vyos@edge1:~$ show ip nht
VRF default:
Resolve via default: on
192.0.2.40
resolved via bgp, prefix 0.0.0.0/0
via 203.0.113.0, eth0 (vrf default), weight 1
Client list: bgp(fd 40)
198.51.100.241
resolved via ospf, prefix 198.51.100.241/32
via 198.51.100.225, eth1 (vrf default), weight 1
Client list: bgp(fd 40)
198.51.100.243
resolved via ospf, prefix 198.51.100.243/32
via 198.51.100.229, eth2 (vrf default), weight 1
Client list: bgp(fd 40)
203.0.113.0
resolved via connected, prefix 203.0.113.0/31
is directly connected, eth0 (vrf default), weight 1
Client list: bgp(fd 40)(Connected)- Line 3: VyOS lets BGP resolve next hops via a default route.
- Lines 4–6: So edge1 "reaches" the IX member's address via the default to the upstream. IX traffic arriving at edge1 would leave by transit.
- Lines 8–14: The loopbacks resolve via OSPF, as they should.
set protocols bgp peer-group IBGP address-family ipv4-unicast nexthop-self- Line 1: Advertise ourselves as the next hop for everything we send to iBGP peers.
vyos@core1:~$ show ip bgp
BGP table version is 6, local router ID is 198.51.100.241, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*>i 0.0.0.0/0 198.51.100.242 0 100 0 64496 i
*> 198.51.100.0/24 0.0.0.0 0 32768 i
*> 198.51.100.0/25 0.0.0.0 0 32768 i
*>i 203.0.113.64/26 198.51.100.243 0 150 0 64502 i
*>i 203.0.113.128/25 198.51.100.242 0 100 0 64496 i
Displayed 5 routes and 5 total paths
vyos@core1:~$ show ip route bgp
Codes: K - kernel route, C - connected, L - local, S - static,
R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
f - OpenFabric, t - Table-Direct,
> - selected route, * - FIB route, q - queued, r - rejected, b - backup
t - trapped, o - offload failure
IPv4 unicast VRF default:
B> 0.0.0.0/0 [200/0] via 198.51.100.242 (recursive), weight 1, 00:00:22
* via 198.51.100.224, eth0, weight 1, 00:00:22
B> 203.0.113.64/26 [200/0] via 198.51.100.243 (recursive), weight 1, 00:00:05
* via 198.51.100.226, eth1, weight 1, 00:00:05
B> 203.0.113.128/25 [200/0] via 198.51.100.242 (recursive), weight 1, 00:00:22
* via 198.51.100.224, eth0, weight 1, 00:00:22- Line 11: The default's next hop is now edge1's loopback…
- Line 14: …and the IX route's is edge2's, with local preference 150 carried over from edge2's import policy.
- Lines 27–28: Recursive resolution: BGP next hop 198.51.100.242, reached via OSPF on eth0.
vyos@edge1:~$ show bgp ipv4 203.0.113.64/26
BGP routing table entry for 203.0.113.64/26, version 6
Paths: (1 available, best #1, table default)
Not advertised to any peer
64502
198.51.100.243 (metric 1) from 198.51.100.243 (198.51.100.243)
Origin IGP, metric 0, localpref 150, valid, internal, best (First path received)
Last update: Fri Oct 16 23:36:42 2026
vyos@edge1:~$ show ip route 203.0.113.64/26
Routing entry for 203.0.113.64/26
Known via "bgp", distance 200, metric 0, best
Last update 00:00:07 ago
Flags: Recursion iBGP Selected
Status: Installed
198.51.100.243 (recursive), weight 1
* 198.51.100.229, via eth2, weight 1- Line 6:
(metric 1): the next hop is reached via the IGP, one link away. - Lines 15–16: IX traffic from edge1 now goes to edge2 over their direct link, not to the upstream.
Check your understanding
Why can't core1 use the default route before next-hop-self is configured?
- core1 hasn't been told to accept default routes
- Its next hop, 203.0.113.0, isn't reachable from core1
- iBGP routes always have a lower preference than OSPF
- The session to edge1 is down