marfillaster · notes

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.

Overview

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.

Design decisions

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.

1. Topology recap

                       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

2. Conventions and placeholders

Series-wide placeholders (<ULA_PREFIX>) live in the index §2. This variant adds:

PlaceholderMeaning
<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.

3. Baseline VyOS networking

These commands assume you are on the provider console or already have a working SSH session. Keep console access open while applying firewall rules.

bash

bash

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
exit

Verification before touching WireGuard:

bash

bash

show interfaces ethernet
show ip route
show ipv6 route
ping 1.1.1.1
ping 2606:4700:4700::1111

4. VyOS — WireGuard and BGP

Create 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.

bash

bash

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
save

The BGP policy accepts only the home aggregate from the home router and sends only a default route back.

bash

bash

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
save

5. VyOS — relay firewall

This is the equivalent of the Ubuntu recipe's nftables block. It keeps the public input surface small while letting the VPS route through wg0.

bash

bash

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
save

If 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.

6. Home router — WireGuard client and BGP

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.

bash

bash

/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-vps

At 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.

7. Verification

bash

bash

# 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=3

The important return-routing check is on VyOS:

bash

bash

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.

References

Share

Comments

View or add comments