BGP is the protocol that runs the internet. It’s also the protocol that can take down the internet — one misconfiguration, one missing filter, and you’re either leaking routes or accepting someone else’s garbage. Every major BGP incident (and there are many) comes down to the same thing: missing or inadequate filtering.
VyOS uses FRR (Free Range Routing) as its BGP implementation. It’s battle-tested and feature-complete. But FRR, like any BGP implementation, will happily accept and advertise whatever you tell it to. It’s your job to tell it the right things.
BGP Fundamentals
eBGP (External BGP): Between different Autonomous Systems (AS). Your connection to ISPs, IXPs, or other organizations.
iBGP (Internal BGP): Within the same AS. Distributes external routes internally.
Key difference: eBGP changes the AS path on advertisements. iBGP doesn’t — routes learned via iBGP keep their original AS path.
Basic eBGP Configuration
Typical scenario: You have AS 65000, connecting to an upstream provider (AS 12345).
configure
# Define your AS and router IDset protocols bgp system-as '65000'set protocols bgp parameters router-id '203.0.113.1'
# Define neighbor (your upstream)set protocols bgp neighbor 198.51.100.1 remote-as '12345'set protocols bgp neighbor 198.51.100.1 description 'Upstream Provider'set protocols bgp neighbor 198.51.100.1 update-source '203.0.113.1'
# Announce your prefixset protocols bgp address-family ipv4-unicast network 203.0.113.0/24
commitNever run this in production. This configuration has no filters — you’ll accept whatever your upstream sends (including their full table if they misconfigure) and potentially leak routes.
The Golden Rule: Always Filter
BGP without filters is an incident waiting to happen. Every BGP session needs:
- Inbound filter: What routes you accept
- Outbound filter: What routes you advertise
- max-prefix limit: Protection against route leaks from peers
No exceptions.
Prefix Lists
Prefix lists define which IP prefixes to match:
configure
# What you own and want to advertiseset policy prefix-list MY-PREFIXES rule 10 action 'permit'set policy prefix-list MY-PREFIXES rule 10 prefix '203.0.113.0/24'
# What you accept from upstream (example: allow all but filter specifics)set policy prefix-list UPSTREAM-IN rule 10 action 'deny'set policy prefix-list UPSTREAM-IN rule 10 prefix '0.0.0.0/0'set policy prefix-list UPSTREAM-IN rule 10 description 'Deny default unless explicitly wanted'
set policy prefix-list UPSTREAM-IN rule 20 action 'deny'set policy prefix-list UPSTREAM-IN rule 20 prefix '10.0.0.0/8'set policy prefix-list UPSTREAM-IN rule 20 le '32'set policy prefix-list UPSTREAM-IN rule 20 description 'Deny RFC1918'
set policy prefix-list UPSTREAM-IN rule 30 action 'deny'set policy prefix-list UPSTREAM-IN rule 30 prefix '172.16.0.0/12'set policy prefix-list UPSTREAM-IN rule 30 le '32'
set policy prefix-list UPSTREAM-IN rule 40 action 'deny'set policy prefix-list UPSTREAM-IN rule 40 prefix '192.168.0.0/16'set policy prefix-list UPSTREAM-IN rule 40 le '32'
set policy prefix-list UPSTREAM-IN rule 1000 action 'permit'set policy prefix-list UPSTREAM-IN rule 1000 prefix '0.0.0.0/0'set policy prefix-list UPSTREAM-IN rule 1000 le '24'set policy prefix-list UPSTREAM-IN rule 1000 description 'Accept /24 and larger'
commitPrefix List Syntax
- prefix: The IP prefix to match
- le (less than or equal): Match prefixes with length up to this value
- ge (greater than or equal): Match prefixes with length at least this value
Example: prefix 10.0.0.0/8 le 24 ge 16 matches any prefix within 10.0.0.0/8 that is /16 to /24.
Route Maps
Route maps combine conditions with actions. They’re the Swiss Army knife of BGP policy:
configure
# Outbound: Only advertise my prefixes, set correct attributesset policy route-map TO-UPSTREAM rule 10 action 'permit'set policy route-map TO-UPSTREAM rule 10 match ip address prefix-list 'MY-PREFIXES'set policy route-map TO-UPSTREAM rule 10 set local-preference '100'
set policy route-map TO-UPSTREAM rule 1000 action 'deny'set policy route-map TO-UPSTREAM rule 1000 description 'Deny everything else'
# Inbound: Filter bad routes, set local-pref based on sourceset policy route-map FROM-UPSTREAM rule 10 action 'deny'set policy route-map FROM-UPSTREAM rule 10 match ip address prefix-list 'BOGONS'set policy route-map FROM-UPSTREAM rule 10 description 'Drop bogons'
set policy route-map FROM-UPSTREAM rule 100 action 'permit'set policy route-map FROM-UPSTREAM rule 100 match ip address prefix-list 'UPSTREAM-IN'set policy route-map FROM-UPSTREAM rule 100 set local-preference '200'
set policy route-map FROM-UPSTREAM rule 1000 action 'deny'
commitApply Route Maps to Neighbors
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map import 'FROM-UPSTREAM'set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map export 'TO-UPSTREAM'Max-Prefix Protection
This is your safety valve. If a peer sends more prefixes than expected, the session tears down:
# Expect ~10 prefixes, warn at 8, shut down at 10set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix '10'set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix threshold '80'
# For full table peers (~900k prefixes as of 2024)set protocols bgp neighbor 198.51.100.2 address-family ipv4-unicast maximum-prefix '1000000'set protocols bgp neighbor 198.51.100.2 address-family ipv4-unicast maximum-prefix threshold '90'When max-prefix triggers:
- Session goes down
- Log entry created
- Manual intervention required (or restart-timer)
# Auto-restart after 30 minutes (use carefully)set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix restart '30'BGP Communities
Communities are tags attached to routes. Use them to:
- Signal intent to upstreams (traffic engineering)
- Control route propagation
- Implement policy at scale
Standard Communities
configure
# Define community listset policy community-list BLACKHOLE rule 10 action 'permit'set policy community-list BLACKHOLE rule 10 regex '65000:666'
# Set community in route-mapset policy route-map SET-COMMUNITY rule 10 action 'permit'set policy route-map SET-COMMUNITY rule 10 set community '65000:100'
# Match community in route-mapset policy route-map MATCH-COMMUNITY rule 10 action 'permit'set policy route-map MATCH-COMMUNITY rule 10 match community 'BLACKHOLE'
commitWell-Known Communities
| Community | Meaning |
|---|---|
| no-export | Don’t advertise outside the AS |
| no-advertise | Don’t advertise to any peer |
| local-as | Don’t advertise outside the local confederation |
| no-peer | Don’t advertise to eBGP peers (RFC 3765) |
# Example: Mark routes as no-exportset policy route-map INTERNAL-ONLY rule 10 set community 'no-export'Blackhole Communities
Most transit providers support blackhole communities. When you’re under DDoS attack:
# Advertise the attacked IP with blackhole community# (community varies by provider — check their documentation)set policy route-map BLACKHOLE-ANNOUNCE rule 10 action 'permit'set policy route-map BLACKHOLE-ANNOUNCE rule 10 match ip address prefix-list 'ATTACKED-IP'set policy route-map BLACKHOLE-ANNOUNCE rule 10 set community '12345:666'The upstream drops traffic to that prefix at their edge. You stop receiving the DDoS.
iBGP Configuration
iBGP distributes routes within your AS. Different rules apply:
- No AS path modification
- Full mesh required (or use route reflectors)
- Next-hop often needs adjustment
Basic iBGP
configure
set protocols bgp neighbor 10.0.0.2 remote-as '65000'set protocols bgp neighbor 10.0.0.2 description 'iBGP peer - Router 2'set protocols bgp neighbor 10.0.0.2 update-source 'lo'
# Next-hop-self for eBGP routes advertised via iBGPset protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast nexthop-self
commitWhy Next-Hop-Self?
When you learn a route via eBGP, the next-hop is the eBGP peer’s IP. If you advertise this to iBGP neighbors, they need a route to that external IP — which they might not have.
next-hop-self rewrites the next-hop to your own address, which iBGP peers definitely can reach.
Route Reflectors
Full mesh iBGP doesn’t scale. With N routers, you need N*(N-1)/2 sessions. Route reflectors solve this:
# On route reflectorset protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast route-reflector-clientset protocols bgp neighbor 10.0.0.3 address-family ipv4-unicast route-reflector-clientset protocols bgp neighbor 10.0.0.4 address-family ipv4-unicast route-reflector-client
# Clients just peer with reflector, not each otherRoute reflector modifies the normal iBGP advertisement rules to re-advertise routes to other iBGP peers.
Local Preference
Local preference determines which path to use when you have multiple options. Higher is preferred.
# Prefer primary upstream (local-pref 200) over backup (local-pref 100)set policy route-map FROM-PRIMARY rule 10 set local-preference '200'set policy route-map FROM-BACKUP rule 10 set local-preference '100'Local preference is only meaningful within your AS — it’s not advertised to eBGP peers.
AS Path Prepending
Make your routes less attractive to specific upstreams (traffic engineering):
# Prepend your AS twice when advertising to backup upstreamset policy route-map TO-BACKUP rule 10 action 'permit'set policy route-map TO-BACKUP rule 10 match ip address prefix-list 'MY-PREFIXES'set policy route-map TO-BACKUP rule 10 set as-path prepend '65000 65000'The longer AS path makes this route less preferred. Traffic should prefer the primary path.
Warning: Prepending more than 3x is usually pointless. Some networks filter very long AS paths.
BGP Timers
# Keepalive every 30 seconds, hold time 90 secondsset protocols bgp neighbor 198.51.100.1 timers keepalive '30'set protocols bgp neighbor 198.51.100.1 timers holdtime '90'
# For faster failover (aggressive)set protocols bgp neighbor 198.51.100.1 timers keepalive '10'set protocols bgp neighbor 198.51.100.1 timers holdtime '30'For sub-second failover, use BFD instead of aggressive BGP timers:
set protocols bgp neighbor 198.51.100.1 bfdBogon Filtering
Always filter bogons — prefixes that should never appear in the global routing table:
configure
# IPv4 Bogons (not exhaustive — use a maintained list)set policy prefix-list BOGONS-V4 rule 10 action 'permit'set policy prefix-list BOGONS-V4 rule 10 prefix '0.0.0.0/8'set policy prefix-list BOGONS-V4 rule 10 le '32'
set policy prefix-list BOGONS-V4 rule 20 action 'permit'set policy prefix-list BOGONS-V4 rule 20 prefix '10.0.0.0/8'set policy prefix-list BOGONS-V4 rule 20 le '32'
set policy prefix-list BOGONS-V4 rule 30 action 'permit'set policy prefix-list BOGONS-V4 rule 30 prefix '100.64.0.0/10'set policy prefix-list BOGONS-V4 rule 30 le '32'
set policy prefix-list BOGONS-V4 rule 40 action 'permit'set policy prefix-list BOGONS-V4 rule 40 prefix '127.0.0.0/8'set policy prefix-list BOGONS-V4 rule 40 le '32'
set policy prefix-list BOGONS-V4 rule 50 action 'permit'set policy prefix-list BOGONS-V4 rule 50 prefix '169.254.0.0/16'set policy prefix-list BOGONS-V4 rule 50 le '32'
set policy prefix-list BOGONS-V4 rule 60 action 'permit'set policy prefix-list BOGONS-V4 rule 60 prefix '172.16.0.0/12'set policy prefix-list BOGONS-V4 rule 60 le '32'
set policy prefix-list BOGONS-V4 rule 70 action 'permit'set policy prefix-list BOGONS-V4 rule 70 prefix '192.0.0.0/24'set policy prefix-list BOGONS-V4 rule 70 le '32'
set policy prefix-list BOGONS-V4 rule 80 action 'permit'set policy prefix-list BOGONS-V4 rule 80 prefix '192.0.2.0/24'set policy prefix-list BOGONS-V4 rule 80 le '32'
set policy prefix-list BOGONS-V4 rule 90 action 'permit'set policy prefix-list BOGONS-V4 rule 90 prefix '192.168.0.0/16'set policy prefix-list BOGONS-V4 rule 90 le '32'
set policy prefix-list BOGONS-V4 rule 100 action 'permit'set policy prefix-list BOGONS-V4 rule 100 prefix '198.18.0.0/15'set policy prefix-list BOGONS-V4 rule 100 le '32'
set policy prefix-list BOGONS-V4 rule 110 action 'permit'set policy prefix-list BOGONS-V4 rule 110 prefix '198.51.100.0/24'set policy prefix-list BOGONS-V4 rule 110 le '32'
set policy prefix-list BOGONS-V4 rule 120 action 'permit'set policy prefix-list BOGONS-V4 rule 120 prefix '203.0.113.0/24'set policy prefix-list BOGONS-V4 rule 120 le '32'
set policy prefix-list BOGONS-V4 rule 130 action 'permit'set policy prefix-list BOGONS-V4 rule 130 prefix '224.0.0.0/3'set policy prefix-list BOGONS-V4 rule 130 le '32'
# Apply in route-mapset policy route-map FROM-PEER rule 10 action 'deny'set policy route-map FROM-PEER rule 10 match ip address prefix-list 'BOGONS-V4'
commitFor production, use Team Cymru’s bogon reference or automate prefix list updates from IRR.
Debugging BGP
Check BGP Status
# Summary of all BGP neighborsshow ip bgp summary
# Detailed neighbor infoshow ip bgp neighbors 198.51.100.1
# Advertised routesshow ip bgp neighbors 198.51.100.1 advertised-routes
# Received routesshow ip bgp neighbors 198.51.100.1 received-routes
# Routes in BGP tableshow ip bgpCommon Issues
| Symptom | Cause | Fix |
|---|---|---|
| State: Idle | No route to peer, firewall | Check connectivity, allow TCP 179 |
| State: Active | TCP connect failing | Firewall, wrong IP, peer not configured |
| State: OpenSent | Waiting for peer’s OPEN | Peer might be filtering, AS mismatch |
| No routes received | Inbound filter too strict | Check route-map, prefix-list |
| Routes not advertised | Outbound filter, route not in BGP | Check network statement, route-map |
BGP Messages
# Enable BGP debugging (careful in production)debug bgp neighbor-eventsdebug bgp updates
# View logsshow log | match bgpComplete eBGP Configuration
# === BGP Core ===set protocols bgp system-as '65000'set protocols bgp parameters router-id '203.0.113.1'set protocols bgp parameters log-neighbor-changes
# === Prefix Lists ===set policy prefix-list MY-PREFIXES rule 10 action 'permit'set policy prefix-list MY-PREFIXES rule 10 prefix '203.0.113.0/24'
set policy prefix-list BOGONS-V4 rule 10 action 'permit'set policy prefix-list BOGONS-V4 rule 10 prefix '10.0.0.0/8'set policy prefix-list BOGONS-V4 rule 10 le '32'# ... (other bogon entries)
set policy prefix-list INBOUND-FILTER rule 10 action 'deny'set policy prefix-list INBOUND-FILTER rule 10 prefix '0.0.0.0/0'set policy prefix-list INBOUND-FILTER rule 10 ge '25'set policy prefix-list INBOUND-FILTER rule 10 description 'Deny too-specific prefixes'
set policy prefix-list INBOUND-FILTER rule 1000 action 'permit'set policy prefix-list INBOUND-FILTER rule 1000 prefix '0.0.0.0/0'set policy prefix-list INBOUND-FILTER rule 1000 le '24'
# === Route Maps ===set policy route-map TO-UPSTREAM rule 10 action 'permit'set policy route-map TO-UPSTREAM rule 10 match ip address prefix-list 'MY-PREFIXES'set policy route-map TO-UPSTREAM rule 1000 action 'deny'
set policy route-map FROM-UPSTREAM rule 10 action 'deny'set policy route-map FROM-UPSTREAM rule 10 match ip address prefix-list 'BOGONS-V4'set policy route-map FROM-UPSTREAM rule 100 action 'permit'set policy route-map FROM-UPSTREAM rule 100 match ip address prefix-list 'INBOUND-FILTER'set policy route-map FROM-UPSTREAM rule 100 set local-preference '200'set policy route-map FROM-UPSTREAM rule 1000 action 'deny'
# === Neighbor Configuration ===set protocols bgp neighbor 198.51.100.1 remote-as '12345'set protocols bgp neighbor 198.51.100.1 description 'Primary Upstream'set protocols bgp neighbor 198.51.100.1 update-source '203.0.113.1'set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map import 'FROM-UPSTREAM'set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map export 'TO-UPSTREAM'set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix '1000000'set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast soft-reconfiguration inbound
# === Networks to Advertise ===set protocols bgp address-family ipv4-unicast network 203.0.113.0/24The Lesson
BGP without filters is an incident waiting to happen. Every route leak, every hijack, every accidental full-table advertisement — they all trace back to missing or inadequate filtering.
The essentials:
- Prefix lists: Define exactly what you advertise and accept
- Route maps: Apply policy consistently
- Max-prefix: Protect against route leaks from peers
- Bogon filtering: Never accept or announce garbage prefixes
- Community discipline: Use communities for consistent policy
The internet runs on trust and filtering. BGP peers trust that you advertise only what you should. Filters ensure that even when mistakes happen, damage is limited.
Before any BGP session goes live, ask: “What’s the worst that happens if I misconfigure this?” Then add filters to prevent that worst case.