Illustrative network lab with seated operator and a hub/spoke DEMO diagram.

WIUNIX ACADEMY

WireGuard hub and spoke with filtered BGP and FRRouting

Build two encrypted spoke links, exchange exact LAN prefixes with eBGP, observe kernel routes and rehearse withdrawal without losing the management path.

Advanced75 min readUpdated
Make this guide yours

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Ubuntu 24.04 LTSReviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment19 editable values

THE OUTCOME

What will you have at the end?

Route 10.71.10.0/24 ↔ 10.72.20.0/24 through AS65000 with explicit policies and observed withdrawal.

01A · AS6501010.71.10.0/24 → 10.254.1.2
02Hub · AS6500010.254.1.1 / 10.254.2.1 · eBGP over WireGuard
03B · AS6502010.254.2.2 → 10.72.20.0/24
Supported operating systems and versions

OS paths are documented; the isolated test evidence below has narrower scope.

Before you begin

  • Three fresh Linux VMs, sudo/Bash, independent console, existing connected LANs and authenticated public-key exchange.
  • No overlapping management/LAN/tunnel routes; existing firewall owner prepared for exact encrypted peers and selected services.

Route two spokes through one hub

For administrators familiar with Linux routing and WireGuard. Build two separate encrypted point-to-point links, then let eBGP advertise only each spoke’s connected LAN. This hub has no local LAN to advertise and is a single point of failure. It is an IPv4 lab, not a production migration, internet transit service or redundant VPN design.

Choose public values before copying

Open the settings, edit, Apply, then copy. The dedicated absolute root /srv/academy-wgbgp must not exist or be a symlink. Interface names wg-ac-a and wg-ac-b must be unused on the hub. LANs 10.71.10.0/24 and 10.72.20.0/24 and the two /30 tunnel subnets must not overlap any real routes, management network or each other. The form checks represented relationships, not ownership or reachability. Keep management outside BGP. Values and custom progress stay in sessionStorage for this tab/language/article/environment; default progress uses localStorage. Nothing is added to shared URLs or written to the server. Never enter keys/passwords. Custom values are not executed tests.

AllowedIPs is not a BGP routing table

The kernel FIB chooses an output interface. On that interface, WireGuard selects a peer by destination AllowedIPs and validates received inner source addresses against the same peer’s AllowedIPs. FRR bgpd selects BGP paths; zebra installs approved learned routes in the kernel. Table = off prevents wg-quick from adding LAN routes from AllowedIPs. Connected /30 routes still exist because Address assigns the interface prefix. Do not add static remote LAN routes: they would conceal BGP withdrawal.

Two tunnel interfaces, three private ASNs

Hub AS65000 uses 10.254.1.1/30 on wg-ac-a and 10.254.2.1/30 on wg-ac-b. A is AS65010, 10.254.1.2/30, owning 10.71.10.0/24 with gateway 10.71.10.1. B is AS65020, 10.254.2.2/30, owning 10.72.20.0/24 with gateway 10.72.20.1. Unique private ASNs avoid same-AS rejection; this is eBGP, not a route reflector. Hub next-hop-self makes the other spoke use its directly reachable hub address. Each spoke’s single hub peer may carry the other LAN; the hub’s per-spoke peer carries only that spoke’s source LAN. No default or broad RFC1918 aggregate is permitted.

01

LET’S BUILD

Inspect three disposable VMs

Run on all three fresh gateways with an independent console. The hub needs a reachable UDP endpoint 198.51.100.10. Spokes initiate toward it and can be behind NAT. LAN addresses and connected routes must already be assigned by your normal network manager. Stop for any existing FRR configuration/service, conflicting interface/root or production traffic; never disable an existing router to make room. Inspect real firewall ownership and record management routes before installing. Keep this terminal and ROLE selection for subsequent role-gated panels; in a new shell repeat the role prompt deliberately.

bash

Dedicated fresh lab gateways; Bash

set -eu
cat /etc/os-release
ip -br address
ip route show table all
sudo ss -lntup
if command -v nft >/dev/null; then sudo nft list ruleset; else printf '%s\n' 'nft not installed: inspect the existing firewall owner before proceeding'; fi
test ! -e '/srv/academy-wgbgp'
test ! -L '/srv/academy-wgbgp'
test ! -e /etc/frr
! ip link show 'wg-ac-a' 2>/dev/null
! ip link show 'wg-ac-b' 2>/dev/null
read -r -p 'Lab role (h/a/b): ' ROLE
case "$ROLE" in h|a|b) ;; *) exit 1;; esac
How do I know it worked?

The root, tunnel names and FRR configuration are absent; LAN/management routes are documented and UDP ports are free.

02

LET’S BUILD

Install the selected distribution packages

Use signed distribution packages and record the candidate. The selected OS guard must pass. FRR 8.4 and 10.x share the configuration used here; security revisions take precedence. This does not claim the newest upstream release or that every OS was installed. Only the controlled runtime described in the evidence note was executed. A package may start its empty service; stop only this freshly installed lab service before configuration.

bash

Dedicated fresh lab gateways; Bash

set -eu
. /etc/os-release
test "$VERSION_CODENAME" = 'noble'
sudo apt-get update
apt-cache policy frr wireguard-tools
sudo apt-get install --no-install-recommends frr wireguard-tools nftables iproute2 iputils-ping curl python3 nano
sudo systemctl stop frr
/usr/lib/frr/bgpd --version
wg --version
How do I know it worked?

The OS guard passes and installed bgpd/wg versions match the recorded signed package candidate.

Explore all tutorials ↗