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.
Make this guide yoursYOUR SYSTEM. YOUR STEPS.
Where are you working?
Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.
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.
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.
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.
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
The root, tunnel names and FRR configuration are absent; LAN/management routes are documented and UDP ports are free.
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.
Dedicated fresh lab gateways; Bash
set -eu
. /etc/os-release
test "$VERSION_CODENAME" = 'stonking'
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
The OS guard passes and installed bgpd/wg versions match the recorded signed package candidate.