Build log · MikroTik RB5009 · VPS-routed /48 · VyOS relay
VyOS relay for routed IPv6 over CGNAT
Same VPS-routed /48 design as the Ubuntu/BIRD path, implemented with VyOS WireGuard, BGP policy, and relay firewall rules.
Build log · MikroTik RB5009 · VPS-routed /48 · VyOS relay
Same VPS-routed /48 design as the Ubuntu/BIRD path, implemented with VyOS WireGuard, BGP policy, and relay firewall rules.
This is the VyOS variant of the
VPS path in the
RB5009 CGNAT series: a self-operated VPS still
routes a provider-delegated /48 over WireGuard and eBGP, but the relay is
VyOS instead of Ubuntu + bird2 + nftables.
The home-router side is intentionally the same shape as the Linux VPS recipe:
WireGuard is transport, BGP is routing intent, and the home router advertises
the home aggregate while learning only ::/0 from the VPS. The VyOS side
replaces systemd services and hand-written config files with configure,
commit, and save.
Use this when the VPS itself is becoming a router appliance. If the VPS is a general-purpose Linux host that merely relays IPv6, the Ubuntu/BIRD recipe is simpler to inspect with ordinary Linux tools.
Do not put the routed prefix on the VyOS WAN as /48. Some providers
configure one address from the routed prefix on the public NIC with a /48
mask. On a relay, that creates a connected route for the entire home
aggregate on the WAN. The route you actually want is the BGP-learned route
to the home router over WireGuard. In this VyOS variant, any address from
the routed prefix on the VPS uses /128; the aggregate itself is learned
from the home router.
Use VyOS BGP policy instead of BIRD filters. The import side permits only
<LAN_PREFIX>::/48 from the home router. The export side uses BGP
default-originate, so the home router sees a default route and not the VPS's
provider-connected prefixes.
Keep the VPS firewall interface-based. The relay is still pure transit:
SSH and WireGuard are allowed on the WAN, BGP is allowed only on wg0, and
forwarded IPv6 can enter or leave wg0. Application policy remains on the
home router.
Internet (IPv4 + IPv6)
│
┌─────────────┴─────────────┐
│ VPS — VyOS, routed /48 │
│ <VPS_IP> on <WAN_IF> │
│ wg0: <LAN_PREFIX>:0::1 │
│ FRR: eBGP to home │
└─────────────┬─────────────┘
│ WireGuard / UDP 51820
│ (IPv6 transit + eBGP)
│
home wg-vps
<LAN_PREFIX>:0::2
Series-wide placeholders (<ULA_PREFIX>) live in the
index §2. This variant adds:
| Placeholder | Meaning |
|---|---|
<WAN_IF> | VyOS public interface. On this VPS it is eth0; cloud-init may call the same MAC ens3. |
<VPS_IP> / <VPS_PREFIXLEN> | Provider IPv4 address and prefix length, e.g. 198.51.100.53/24. |
<VPS_GW4> | Provider IPv4 gateway. |
<VPS_LINK_GUA> | Provider IPv6 link address, if supplied as a /128. |
<VPS_GW6> | Provider IPv6 gateway. |
<LAN_PREFIX> | Routed IPv6 /48. Drop trailing zeros, e.g. 2001:db8 for 2001:db8::/48. |
<VPS_PUBKEY> / <HOME_PUBKEY> | WireGuard public keys, one per side. |
<VPS_AS> / <HOME_AS> | Private ASNs (RFC 6996, 64512–65534) for the eBGP session. |
<VPS_ROUTER_ID> | Any unique 32-bit router ID written like an IPv4 address. |
If your provider metadata says the routed prefix address is
<LAN_PREFIX>::a/48, configure it as <LAN_PREFIX>::a/128 on VyOS. The
provider still routes the /48 to the VPS; VyOS does not need a connected
WAN route for the whole aggregate.
These commands assume you are on the provider console or already have a working SSH session. Keep console access open while applying firewall rules.
configure
set interfaces ethernet <WAN_IF> address <VPS_IP>/<VPS_PREFIXLEN>
set interfaces ethernet <WAN_IF> address <VPS_LINK_GUA>/128
set interfaces ethernet <WAN_IF> address <LAN_PREFIX>::a/128
# Add the host routes only if your provider metadata declares the gateways
# as on-link routes. They are harmless when the IPv4 gateway is already
# inside the interface prefix.
set protocols static route <VPS_GW4>/32 interface <WAN_IF>
set protocols static route 0.0.0.0/0 next-hop <VPS_GW4>
set protocols static route6 <VPS_GW6>/128 interface <WAN_IF>
set protocols static route6 ::/0 next-hop <VPS_GW6>
set service ssh port 22
commit
save
exitVerification before touching WireGuard:
show interfaces ethernet
show ip route
show ipv6 route
ping 1.1.1.1
ping 2606:4700:4700::1111Create wg0, commit it once, then let VyOS generate and install the private
key. The public key printed by show interfaces wireguard wg0 public-key
becomes <VPS_PUBKEY> on the home router.
configure
set interfaces wireguard wg0 address <LAN_PREFIX>:0::1/64
set interfaces wireguard wg0 address fe80::1/64
set interfaces wireguard wg0 mtu 1420
set interfaces wireguard wg0 port 51820
commit
run generate pki wireguard key-pair install interface wg0
run show interfaces wireguard wg0 public-key
set interfaces wireguard wg0 peer home public-key <HOME_PUBKEY>
set interfaces wireguard wg0 peer home allowed-ips <LAN_PREFIX>:0::2/128
set interfaces wireguard wg0 peer home allowed-ips <LAN_PREFIX>::/48
commit
saveThe BGP policy accepts only the home aggregate from the home router and sends only a default route back.
configure
set policy prefix-list6 HOME-V6 rule 10 action permit
set policy prefix-list6 HOME-V6 rule 10 prefix <LAN_PREFIX>::/48
set policy route-map HOME-IN rule 10 action permit
set policy route-map HOME-IN rule 10 match ipv6 address prefix-list HOME-V6
set policy route-map HOME-IN rule 100 action deny
set protocols bgp system-as <VPS_AS>
set protocols bgp parameters router-id <VPS_ROUTER_ID>
set protocols bgp neighbor <LAN_PREFIX>:0::2 remote-as <HOME_AS>
set protocols bgp neighbor <LAN_PREFIX>:0::2 update-source wg0
set protocols bgp neighbor <LAN_PREFIX>:0::2 address-family ipv6-unicast route-map import HOME-IN
set protocols bgp neighbor <LAN_PREFIX>:0::2 address-family ipv6-unicast default-originate
set protocols bgp neighbor <LAN_PREFIX>:0::2 address-family ipv6-unicast nexthop-self
commit
saveThis is the equivalent of the Ubuntu recipe's nftables block. It keeps the
public input surface small while letting the VPS route through wg0.
configure
set firewall global-options state-policy established action accept
set firewall global-options state-policy related action accept
set firewall global-options state-policy invalid action drop
set firewall ipv4 input filter default-action drop
set firewall ipv4 input filter rule 10 action accept
set firewall ipv4 input filter rule 10 protocol tcp
set firewall ipv4 input filter rule 10 destination port 22
set firewall ipv4 input filter rule 10 description SSH
set firewall ipv4 input filter rule 20 action accept
set firewall ipv4 input filter rule 20 protocol udp
set firewall ipv4 input filter rule 20 destination port 51820
set firewall ipv4 input filter rule 20 description WireGuard
set firewall ipv4 input filter rule 30 action accept
set firewall ipv4 input filter rule 30 protocol icmp
set firewall ipv4 input filter rule 30 description ICMP
set firewall ipv6 input filter default-action drop
set firewall ipv6 input filter rule 10 action accept
set firewall ipv6 input filter rule 10 protocol icmpv6
set firewall ipv6 input filter rule 10 description ICMPv6
set firewall ipv6 input filter rule 20 action accept
set firewall ipv6 input filter rule 20 inbound-interface name wg0
set firewall ipv6 input filter rule 20 protocol tcp
set firewall ipv6 input filter rule 20 destination port 179
set firewall ipv6 input filter rule 20 description 'BGP from home'
set firewall ipv6 forward filter default-action drop
set firewall ipv6 forward filter rule 10 action accept
set firewall ipv6 forward filter rule 10 inbound-interface name wg0
set firewall ipv6 forward filter rule 10 description 'LAN to internet'
set firewall ipv6 forward filter rule 20 action accept
set firewall ipv6 forward filter rule 20 outbound-interface name wg0
set firewall ipv6 forward filter rule 20 description 'internet return to LAN'
commit
saveIf you also want the WireGuard listener reachable over IPv6 on the VPS public
address, add a matching UDP/51820 rule under firewall ipv6 input filter.
The CGNAT home line only needs outbound IPv4 UDP to the VPS, so the IPv4 rule
is enough for the base build.
This is the same RouterOS shape as the Ubuntu VPS post. The interface names
below use wg-vps and vyos-vps so the VyOS relay stays easy to distinguish
from the Ubuntu/BIRD variant in exports, logs, and follow-up BFD snippets.
The home router initiates to the VPS, so the local listen port is not part of
the provider-facing contract.
/interface/wireguard add name=wg-vps listen-port=51820 mtu=1420
/interface/wireguard/peers add interface=wg-vps name=vyos-vps \
public-key="<VPS_PUBKEY>" \
endpoint-address=<VPS_IP> endpoint-port=51820 \
allowed-address=::/0 \
persistent-keepalive=25s
/ipv6/address add address=<LAN_PREFIX>:0::2/64 interface=wg-vps advertise=no
/ipv6/route add dst-address=<LAN_PREFIX>::/48 blackhole distance=254 \
comment="aggregate-for-bgp"
/ipv6/firewall/address-list add list=bgp-networks-vyos-vps \
address=<LAN_PREFIX>::/48 comment="aggregate to VPS"
/routing/filter/rule add chain=bgp-in-vyos-vps \
rule="if (dst == ::/0) { accept } reject"
/routing/filter/rule add chain=bgp-out-vyos-vps \
rule="if (dst == <LAN_PREFIX>::/48) { accept } reject"
/routing/bgp/instance add name=default-bgp as=<HOME_AS> router-id=<HOME_ROUTER_ID>
/routing/bgp/template add name=tpl-vps as=<HOME_AS>
/routing/bgp/connection add name=vyos-vps instance=default-bgp \
remote.address=<LAN_PREFIX>:0::1 remote.as=<VPS_AS> \
local.address=<LAN_PREFIX>:0::2 local.role=ebgp \
templates=tpl-vps afi=ipv6 \
input.filter=bgp-in-vyos-vps \
output.network=bgp-networks-vyos-vps output.filter-chain=bgp-out-vyos-vpsAt this point the home router should learn a BGP ::/0 over wg-vps, but
LAN clients still need the
Per-VLAN IPv6 post to receive GUAs. Use the same
substitution as the Ubuntu VPS path:
<GUA_LAN>=<LAN_PREFIX>:1, <GUA_IOT>=<LAN_PREFIX>:10,
<GUA_GUEST>=<LAN_PREFIX>:20.
# VyOS:
show interfaces wireguard
show bgp ipv6 summary
show bgp ipv6 <LAN_PREFIX>::/48
show ipv6 route <LAN_PREFIX>::/48
ping <LAN_PREFIX>:0::2
# Home router:
/interface/wireguard/peers/print detail where name=vyos-vps
/routing/bgp/session/print
/ipv6/route/print where dst-address=::/0
/ping 2606:4700:4700::1111 count=3The important return-routing check is on VyOS:
run ip -6 route get <client-IPv6-addr>Expect dev wg0, not dev <WAN_IF>. If the route points to the WAN, check
that the VPS address from the routed prefix is configured as /128, not
/48, and that the BGP session is importing <LAN_PREFIX>::/48 from the
home router.
Comments