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.