VyOSXXXIV · Route RedistributionKernel redistribution
Redistributing kernel routes — what `redistribute kernel` really carries, and why it is rarely the right answer
What you'll learn
- Configure `redistribute kernel` with a route-map under the BGP address family on VyOS 1.5
- Explain what zebra classifies as a kernel route, and how that differs from static and connected
- Choose the VyOS-native alternative — static, blackhole, RTBH community — when it exists
- Recognise the production risk of a route nobody configured being advertised to a peer
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-19
redistribute kernel takes routes that zebra learned from the
Linux kernel and originates them into BGP. It is the only
redistribution source on a VyOS router whose contents are not
described anywhere in the configuration tree — which is exactly
what makes it useful in the two or three cases where it is
justified, and dangerous everywhere else.
This lesson establishes what a kernel route actually is on a 1.5 router, when redistributing one is defensible, what VyOS gives you instead in the cases where it is not, and the failure mode where a router advertises a prefix that nobody configured.
What zebra calls a kernel route
Two route tables are in play and they are not the same thing.
- The kernel FIB is what forwards packets.
ip route showreads it. - Zebra’s RIB is FRR’s view: every route it has learned, from
every source, whether or not it won selection.
show ip routereads it, throughvtysh.
Zebra installs routes into the kernel FIB and also listens to
the kernel over netlink. When a route appears in the kernel that
zebra did not put there, zebra records it in its own RIB and tags
it K — kernel. That is the whole definition: a kernel route
is one zebra learned from the kernel rather than from a routing
protocol or from its own configuration. It does not matter which
program created it; ip route add from a shell, a container
runtime, a VPN client and a bespoke daemon calling netlink all
produce the same thing.
vyos@r1:~$ sudo ip route add 192.0.2.0/24 via 198.51.100.1 dev eth0Look at the two views afterwards. The kernel FIB:
ip route show 192.0.2.0/24
And zebra’s RIB, from operational mode — the route code in the first column is the point:
vyos@r1:~$ show ip route 192.0.2.0/24K>* 192.0.2.0/24 [0/0] via 198.51.100.1, eth0, 00:00:12Illustrative output
K is kernel. S would be a static route configured under
set protocols static route ..., C connected, B BGP, O
OSPF. The > means zebra selected this route and the * means
it is installed in the FIB. A VyOS-configured static route and a
shell-added route are visibly different in this output, and that
distinction is the one the redistribution acts on.
When redistributing kernel routes is defensible
The honest list is short:
- A control system outside VyOS installs routes by design. A telemetry-driven daemon, a scrubbing-centre controller, or an SDN agent that programs the FIB via netlink. Its routes are meant to be advertised, and there is no VyOS node that represents them because they change faster than a commit cycle.
- You are integrating something that only speaks netlink, and
a wrapper that converts its output into VyOS
setcommands is genuinely not available.
That is close to the whole list. In particular, note two cases that are commonly cited and are not on it, because VyOS already has a first-class answer.
A blackhole for DDoS mitigation. VyOS originates a blackhole route natively:
set protocols static route 203.0.113.0/24 blackhole
That is a configured object: it survives a reboot, appears in
compare, is in the config archive, and is redistributable with
redistribute static — where the filter and the community
tagging are the ordinary, reviewable ones. To signal remote
triggered black hole to an upstream, tag it on the way out rather
than trusting the route’s origin:
set policy route-map RTBH-OUT rule 10 action 'permit'
set policy route-map RTBH-OUT rule 10 match ip address prefix-list 'RTBH-PFX'
set policy route-map RTBH-OUT rule 10 set community add '65535:666'
The community your upstream honours comes from their documentation, not from this lesson — check it, because sending the wrong one achieves nothing and sending the right one to the wrong peer blackholes traffic you wanted.
An operator’s temporary route. If it is worth having, it is
worth a set protocols static route ... and a commit. If it is
not worth a commit, it is not worth advertising to a peer.
flowchart TB
SH["ip route add<br/>(shell, ad hoc)"] --> FIB["Linux kernel FIB"]
DAEMON["external controller<br/>via netlink"] --> FIB
FIB -->|netlink notification| Z["zebra RIB<br/>tagged K"]
Z -->|"redistribute kernel<br/>+ route-map"| BGP["BGP Loc-RIB"]
CFG["set protocols static route"] --> Z2["zebra RIB<br/>tagged S"]
Z2 -->|"redistribute static<br/>+ route-map"| BGP
BGP --> PEER["Peer"]
Both paths reach the peer. Only the lower one is described by the configuration, and that is the entire argument for preferring it.
The configuration
The redistribution lives under the BGP address family in 1.5, not
directly under protocols bgp:
set policy prefix-list KERNEL-OK rule 10 action 'permit'
set policy prefix-list KERNEL-OK rule 10 prefix '192.0.2.0/24'
set policy route-map KERNEL-TO-BGP rule 10 action 'permit'
set policy route-map KERNEL-TO-BGP rule 10 match ip address prefix-list 'KERNEL-OK'
set policy route-map KERNEL-TO-BGP rule 10 set metric '100'
set policy route-map KERNEL-TO-BGP rule 10 set community add '64512:600'
set policy route-map KERNEL-TO-BGP rule 999 action 'deny'
set protocols bgp system-as 64512
set protocols bgp address-family ipv4-unicast redistribute kernel route-map 'KERNEL-TO-BGP'
Four things worth reading carefully:
- The route-map is not optional in practice. Without it,
redistribute kerneladvertises every kernel route zebra knows about — including ones added by software you did not think about. - Rule 999 is a deny with no match, so it denies everything that did not match rule 10. A route-map already ends in an implicit deny; writing it out means the next person does not have to remember that, and it gives the deny a counter.
set community addis the 1.4+ spelling of what older documentation writes asset community X additive. The bareset community replaceform discards whatever the route already carried, which on a redistributed route is usually harmless and on a re-advertised one is not.- The prefix-list is an allow-list of specific prefixes, not a
range.
redistribute kernelwith a permissive filter is barely better than no filter at all.
Kernel, static and connected
All three end up in the kernel FIB, and they are three different redistribution sources:
| Zebra code | Source | Persists a reboot | In show configuration commands |
|---|---|---|---|
C | An address configured on an up interface | Yes, via the interface config | Yes |
S | set protocols static route ... | Yes, once saved | Yes |
K | The kernel, from anything zebra did not install | No | No |
Read them apart with the operational commands:
show ip route kernel
show ip route static
show ip route connected
show ip route kernel is the audit command for this feature. Any
prefix in that output is a prefix whose existence is recorded
nowhere but in a running kernel — and if redistribute kernel is
configured, potentially in a peer’s routing table too.
Failure modes
A route nobody configured is being advertised
The characteristic incident: a peer reports receiving a prefix that appears in no configuration, no change record and no backup.
Diagnostic, in order:
show ip bgp neighbors 10.0.0.2 advertised-routes— confirm the router really is the source rather than a downstream one.show ip bgp 10.99.0.0/16— the BGP table entry names the origin. A redistributed route shows as locally originated.show ip route 10.99.0.0/16— the route code says which redistribution is responsible.Kpoints at this feature;S,CorOpoints somewhere else entirely.show configuration commands | match redistribute— list every redistribution the router is doing, not just the one you were thinking about.
Only step 3 actually identifies the source. Steps 1 and 2 confirm
the symptom and step 4 tells you what else could have caused it —
which matters, because “we have redistribute kernel configured”
is a hypothesis, not a diagnosis.
Fix:
# Remove the stray route from the kernel.
sudo ip route del 10.99.0.0/16
Then tighten the route-map so the next one cannot leak, and tell the peer to expect the withdrawal. Removing the kernel route withdraws the prefix; it does not undo whatever the peer did with it in the meantime.
The kernel route does not reach BGP
The route is present with ip route show and does not appear in
show ip bgp.
- The route-map denied it.
show policy route-map KERNEL-TO-BGPto read the map, andvtysh -c 'show ip prefix-list KERNEL-OK 192.0.2.0/24'to test the prefix-list against the exact prefix. An entry for192.0.2.0/24does not match192.0.2.0/25. - Wrong address family. The redistribution sits under
address-family ipv4-unicast; an IPv6 kernel route needs the statement repeating underaddress-family ipv6-unicast. - Wrong VRF. A route in the kernel table for a VRF is redistributed by the BGP instance for that VRF, not by the default one.
- Zebra never saw it as
K. Checkshow ip route <prefix>and read the code. If it saysS, it is a configured static route andredistribute staticis the statement that carries it.
Do not add “wait for the redistribution cycle” to that list. There is no cycle.
The route disappears after a reboot or a config reload
Expected behaviour, not a fault. A kernel route added outside the
configuration tree is gone after a reboot, and with it the BGP
advertisement. If the prefix needs to survive, it needs to be a
configured object — which is the case for choosing
set protocols static route ... over ip route add for anything
that is not genuinely transient.
Rollback
delete protocols bgp address-family ipv4-unicast redistribute kernel
commit
That stops the advertisement of every kernel route at once, which
is the right emergency lever: it is one command, it is in the
configuration, and it is reversible with rollback 1. Narrower
options:
delete protocols bgp address-family ipv4-unicast redistribute kernel route-mapremoves only the filter — which makes the redistribution wider, not narrower. It is almost never what you want during an incident.set policy route-map KERNEL-TO-BGP rule 999 action denyis already there if you followed the configuration above; tightening rule 10’s prefix-list is the surgical fix.sudo ip route del <prefix>removes the offending route itself, from the shell. It is not a VyOS command, it is not in the configuration, and nothing records that you ran it — note it in the incident log yourself.
Use commit-confirm 10 for any of these on a router you are
reaching over the routes in question.
Production discipline
Cross-course references
vyos-xxv-03-bgp-redistribute-staticcovers the same pattern with a configured source, which is the alternative this lesson keeps pointing at.XXXV-VyOS-Summarisationcovers blackhole routes and the aggregation context.vyos-xxxiv-06-redist-anti-patternscovers the broader redistribution failure modes, including mutual redistribution loops.vyos-xxxiii-05-route-map-compositioncovers the route-map and prefix-list mechanics used for the filter here.
Quiz
Knowledge check · 4 questions
Q1. Which routes does `redistribute kernel` actually carry into BGP?
Q2. With `redistribute kernel` enabled, a route added by `ip route add` from the shell can be advertised to a BGP peer even though it appears nowhere in the VyOS configuration.
Q3. An upstream reports that R1 is advertising 10.99.0.0/16, which appears in no configuration. R1 has `redistribute kernel` with a prefix-list allowing only 192.0.2.0/24. Where do you look, and in what order?
R1 carries `set protocols bgp address-family ipv4-unicast redistribute kernel route-map KERNEL-TO-BGP`, and KERNEL-TO-BGP permits only 192.0.2.0/24 before a terminal deny. The upstream at 10.0.0.2 says it is receiving 10.99.0.0/16 from R1. Nobody recognises the prefix and it is in no change record.
Q4. A monitoring script blackholes a DDoS target by running `ip route add blackhole 203.0.113.0/24` on R1, which has unfiltered `redistribute kernel`. The upstream now drops all traffic to that prefix. Assess the design.
R1 carries `set protocols bgp address-family ipv4-unicast redistribute kernel` with no route-map. A monitoring script adds a kernel blackhole route for 203.0.113.0/24 during an attack. The blackhole is redistributed and the upstream provider stops delivering traffic to the prefix.
Passing score: 75%. Answers are checked in this browser.