Introduction
WireGuard is a modern VPN protocol (UDP, ChaCha20-Poly1305 encryption, ~4000 lines of kernel code), heavily used peer-to-peer or as VPN client. But it also makes an excellent BGP transit transport when:
- Your ISP blocks IP proto 47 (Bouygues Bbox notably)
- You want to encrypt tunnel traffic (GRE and VXLAN are clear-text)
- You want a simple setup, no exotic kernel dependency
This tutorial assumes you ordered a VeryCloud Remote Transit IP with WireGuard transport (request explicitly at order). VeryCloud then provides a WG peer config from their backbone.
Prerequisites
- A Linux server with a public IP (or behind NAT with port forwarding for keepalive)
- VeryCloud's technical email with:
PUB_VC,PORT_VC(UDP, often 51820),PubKey_VC, tunnel addressing plan169.254.X.0/30+2a0e:XXXX:XXXX::/127 - Root / sudo
- WireGuard installed (kernel ≥ 5.6 or
wireguard-toolsuserland)
Step 1: Install WireGuard
# Debian / Ubuntu
sudo apt update
sudo apt install -y wireguard wireguard-tools
# RHEL / Rocky / Alma
sudo dnf install -y wireguard-tools
wg --version
Step 2: Generate your key pair
cd /etc/wireguard
sudo umask 077
sudo wg genkey | sudo tee privatekey | sudo wg pubkey > publickey
sudo cat publickey
privatekey: NEVER leaves your serverpublickey: send to VeryCloud for their backbone config
💡 Private key must be chmod 600. If leaked, attacker can impersonate your endpoint.
Step 3: Send your pubkey to VeryCloud
Reply to the ticket / technical email with your public key. VeryCloud configures their side and confirms with:
PubKey_VC: VeryCloud peer's public keyPUB_VC:PORT_VC: VeryCloud's WireGuard endpoint- Unchanged tunnel addressing plan
Step 4: Create the WireGuard config
Create /etc/wireguard/wg-vc.conf:
[Interface]
PrivateKey = <contents of privatekey>
Address = 169.254.X.2/30, 2a0e:XXXX:XXXX::1/127
ListenPort = 51820
MTU = 1420
# No Table=auto: we don't want WG to inject default routes
Table = off
[Peer]
PublicKey = <PubKey_VC provided by VeryCloud>
Endpoint = PUB_VC:PORT_VC
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Key explanations:
Address: internal tunnel IPs (client side/30and/127)MTU = 1420: WG adds 80 bytes overhead in IPv4 (60 in IPv6). 1500 - 80 = 1420Table = off: critical — otherwise WG installs a default route, and we want BGP to do itAllowedIPs = 0.0.0.0/0, ::/0: allow any traffic in the tunnel (filtering will be done by BGP / iptables, not WG)PersistentKeepalive = 25: keepalive every 25s, useful behind NAT
⚠️
Table = offis essential. WithTable = auto, WG installs default route — conflicts with BGP setup.
Step 5: Start the tunnel
sudo chmod 600 /etc/wireguard/wg-vc.conf
sudo wg-quick up wg-vc
Verify:
sudo wg show
Recent handshake (< 2 min) = tunnel up:
peer: <PubKey_VC>
endpoint: PUB_VC:51820
allowed ips: 0.0.0.0/0, ::/0
latest handshake: 32 seconds ago
transfer: 1.2 KiB received, 1.8 KiB sent
Test:
ping 169.254.X.1
ping6 2a0e:XXXX:XXXX::0
Step 6: Enable at boot
sudo systemctl enable --now wg-quick@wg-vc
Step 7: MTU and MSS clamping
WG handles MTU internally, but for forwarded flows (your server is a router routing traffic via WG), use clamping:
sudo iptables -t mangle -A FORWARD -o wg-vc -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Step 8: Allow TCP/179 on the tunnel
sudo iptables -A INPUT -i wg-vc -p tcp --dport 179 -j ACCEPT
sudo iptables -A INPUT -i wg-vc -p tcp --sport 179 -j ACCEPT
Step 9: WireGuard + BGP trap — Table = off
The subtlety of this tutorial.
With default Table = auto, wg-quick:
- Creates a default route via wg-vc
- Sets up fwmark
- Prevents "normal" forwarding via BGP routes
With Table = off:
- WG doesn't touch the routing table
- BGP installs routes according to what VeryCloud announces
- You keep full control
Step 10: Ready for BGP
WG tunnel up, internal IPs pinging, TCP/179 open. Launch BIRD or FRR with:
- Peer IPv4:
169.254.X.1 - Peer IPv6:
2a0e:XXXX:XXXX::0 - Local:
169.254.X.2and2a0e:XXXX:XXXX::1
Troubleshooting
No handshake
- UDP port blocked (cloud provider firewall, iptables)
- Wrong
Endpoint sudo tcpdump -i eth0 udp port PORT_VC -nn
Handshake OK but ping fails
- Wrong
AllowedIPs(must include0.0.0.0/0, ::/0) - Tunnel IPs not assigned:
ip addr show wg-vc
BGP refuses to establish despite tunnel UP
- TCP/179 not authorized on wg-vc
Table = offnot set: WG installed conflicting routes
Tunnel up at boot but drops after hours
- No keepalive: add
PersistentKeepalive = 25 - Conntrack table full if behind NAT
Performance < GRE
- Expected: WG encrypts, GRE doesn't. Count 10-30% less depending on CPU
- On recent Linux with AES-NI or ARM Crypto, overhead is minimal
Useful commands
sudo wg show
sudo wg show wg-vc dump
ip -s link show wg-vc
sudo tcpdump -i wg-vc -nn
sudo tcpdump -i eth0 udp port 51820 -nn
sudo systemctl restart wg-quick@wg-vc
sudo wg-quick down wg-vc
Conclusion
WireGuard as transit transport = the winning combo when GRE is filtered or you want bonus encryption. The setup key is Table = off: without it, WG works against your BGP. Once that subtlety is understood, you have a fast, encrypted tunnel that survives NAT and goes wherever UDP goes.
Going further: BIRD 2 or FRR for the BGP session, multi-peer WG to fail over multiple VeryCloud PoPs, handshake monitoring via Prometheus WG exporter.


















