BGP Routing with FRRouting on Linux
FRRouting (FRR) is a free, open-source routing software suite that brings BGP, OSPF, ISIS, and other protocols to Linux servers. This guide covers installing FRR, configuring BGP peering, announcing prefixes, filtering routes with prefix lists and communities, and setting up a looking glass for route inspection.
Prerequisites
- Ubuntu 20.04/22.04 or CentOS/Rocky Linux 8+
- Root or sudo access
- At least one BGP peer (upstream provider or another router)
- Your own Autonomous System Number (ASN) — for private use: 64512–65534
- IP prefixes you plan to announce
Install FRRouting
# Ubuntu/Debian — install from FRR repository
curl -s https://deb.frrouting.org/frr/keys.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/frr.gpg
FRRVER=frr-stable
echo "deb [signed-by=/usr/share/keyrings/frr.gpg] \
https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER" | \
sudo tee /etc/apt/sources.list.d/frr.list
sudo apt update
sudo apt install -y frr frr-pythontools
# CentOS/Rocky Linux
sudo dnf install -y https://rpm.frrouting.org/repo/frr-stable-repo-1-0.el9.noarch.rpm
sudo dnf install -y frr
# Enable and start FRR
sudo systemctl enable frr
sudo systemctl start frr
Enable BGP and Basic Configuration
FRR uses daemon configuration files to enable specific routing protocols:
# Enable BGP daemon
sudo sed -i 's/^bgpd=no/bgpd=yes/' /etc/frr/daemons
# Optionally enable other daemons
sudo sed -i 's/^ospfd=no/ospfd=yes/' /etc/frr/daemons
sudo sed -i 's/^staticd=no/staticd=yes/' /etc/frr/daemons
# Restart FRR to activate the daemons
sudo systemctl restart frr
# Verify running daemons
sudo systemctl status frr
Access the FRR configuration shell (vtysh):
# Open the FRR shell
sudo vtysh
# Show running configuration
show running-config
# Show BGP summary
show bgp summary
# Exit vtysh
exit
Configure BGP Peers
sudo vtysh
# Enter configuration mode
configure terminal
# Set the router hostname (optional but useful)
hostname my-router
# Configure BGP with your ASN
router bgp 65001
# Set your router ID (usually your primary IP)
bgp router-id 192.0.2.1
# Disable synchronized routing (standard for iBGP)
no bgp synchronization
# Log neighbor changes
bgp log-neighbor-changes
# Configure an eBGP peer (external BGP — different AS)
neighbor 198.51.100.1 remote-as 65002
neighbor 198.51.100.1 description "Upstream Provider A"
neighbor 198.51.100.1 update-source eth0
# Keep session alive (optional timers)
neighbor 198.51.100.1 timers 10 30
# Configure an iBGP peer (internal BGP — same AS)
neighbor 10.0.0.2 remote-as 65001
neighbor 10.0.0.2 description "Internal router 2"
neighbor 10.0.0.2 update-source lo
# Address family for IPv4 unicast
address-family ipv4 unicast
# Activate the peers
neighbor 198.51.100.1 activate
neighbor 10.0.0.2 activate
# Send the neighbor a default route
neighbor 198.51.100.1 default-originate
# iBGP: set next-hop to self so routes are reachable
neighbor 10.0.0.2 next-hop-self
exit-address-family
exit
# Save the configuration
write memory
end
Prefix Announcements and Route Filtering
sudo vtysh
configure terminal
# Define the prefix list for your address space
ip prefix-list MY-PREFIXES seq 10 permit 192.0.2.0/24
ip prefix-list MY-PREFIXES seq 20 permit 198.51.100.0/24
# Create a route map to control outbound announcements
route-map ANNOUNCE-OUT permit 10
match ip address prefix-list MY-PREFIXES
set local-preference 100
set origin igp
exit
# Create a route map to filter inbound routes (accept only specific prefixes)
ip prefix-list ACCEPT-FROM-UPSTREAM seq 5 deny 0.0.0.0/0 le 7
ip prefix-list ACCEPT-FROM-UPSTREAM seq 10 permit 0.0.0.0/0 ge 8 le 24
route-map FILTER-IN permit 10
match ip address prefix-list ACCEPT-FROM-UPSTREAM
exit
# Apply route maps to BGP neighbor
router bgp 65001
address-family ipv4 unicast
# Announce only our prefixes outbound
neighbor 198.51.100.1 route-map ANNOUNCE-OUT out
# Filter what we accept inbound
neighbor 198.51.100.1 route-map FILTER-IN in
# Advertise a network we originate (must exist in routing table)
network 192.0.2.0/24
network 198.51.100.0/24
exit-address-family
exit
write memory
end
BGP Communities
Communities enable policy-based routing and are widely used with upstream providers:
sudo vtysh
configure terminal
# Attach a community to outbound announcements
route-map ANNOUNCE-OUT permit 10
match ip address prefix-list MY-PREFIXES
# Add no-export community (don't export beyond AS boundary)
set community 65001:100 no-export
# Match incoming routes with specific communities
route-map FILTER-IN permit 10
match community BLACKHOLE-COMM
set local-preference 0
# Community list matching
ip community-list standard BLACKHOLE-COMM permit 65002:666
write memory
end
# Verify communities in the BGP table
show bgp ipv4 unicast community 65001:100
Multi-Homed Connectivity
Configure BGP to use multiple upstream providers with traffic engineering:
sudo vtysh
configure terminal
router bgp 65001
# Second upstream provider
neighbor 203.0.113.1 remote-as 65003
neighbor 203.0.113.1 description "Upstream Provider B"
address-family ipv4 unicast
neighbor 203.0.113.1 activate
# Prefer Provider A by setting higher local-preference on routes from A
neighbor 198.51.100.1 route-map PREFER-A in
neighbor 203.0.113.1 route-map PREFER-B in
neighbor 203.0.113.1 route-map ANNOUNCE-OUT out
exit-address-family
exit
# Route map to prefer Provider A (higher local-preference = preferred)
route-map PREFER-A permit 10
set local-preference 200
route-map PREFER-B permit 10
set local-preference 100
write memory
end
Looking Glass Setup
A looking glass lets you inspect BGP routes from your router via a web interface:
# Install lg.sh (simple looking glass)
sudo apt install -y apache2 php
# Or use Alice LG (modern looking glass for FRR)
# https://github.com/alice-lg/alice-lg
# Configure FRR's HTTP API for looking glass integration
sudo vtysh
configure terminal
# Enable the FRR HTTP API (requires frr-pythontools)
# Configure in /etc/frr/frr.conf
exit
# Alternatively, expose vtysh over SSH for remote queries:
# Allow show commands without entering enable mode
sudo vtysh -c "show bgp summary"
sudo vtysh -c "show bgp ipv4 unicast 192.0.2.0/24"
sudo vtysh -c "show ip route"
Troubleshooting
BGP session not establishing:
sudo vtysh -c "show bgp neighbors 198.51.100.1"
# Look for "BGP state" — should show "Established"
# "Idle" means no TCP connection; check firewall for port 179
sudo ss -tlnp | grep 179
sudo ufw allow 179/tcp
Routes not being received:
# Check received prefixes
sudo vtysh -c "show bgp ipv4 unicast neighbors 198.51.100.1 received-routes"
# Check filtered routes
sudo vtysh -c "show bgp ipv4 unicast neighbors 198.51.100.1 received-routes filtered"
Routes not being announced:
# Check what you're sending
sudo vtysh -c "show bgp ipv4 unicast neighbors 198.51.100.1 advertised-routes"
# The network must exist in the routing table to be announced
sudo vtysh -c "show ip route 192.0.2.0/24"
# If not present, add a static route:
sudo vtysh -c "conf t" -c "ip route 192.0.2.0/24 null0"
FRR daemon not starting:
sudo journalctl -u frr -n 50
# Check daemon enablement in /etc/frr/daemons
grep bgpd /etc/frr/daemons
Conclusion
FRRouting brings production-grade BGP routing to Linux servers, making it ideal for baremetal hosting providers, network appliances, and multi-homed connectivity scenarios. With prefix filtering, route maps, and BGP communities, you have fine-grained control over traffic engineering. The vtysh CLI follows Cisco-like syntax, making it accessible for network engineers familiar with traditional routing platforms.


