Build log · MikroTik RB5009 · Series finale

Multi-homing IPv6 over CGNAT on RouterOS

Two IPv6 uplinks at once under one announceable provider-assigned /48 — VPS path with BFD as primary, Route64 path as backup, BGP best-path picks the active default. Includes the ASN + /48 acquisition story.

Overview

The series finale of the MikroTik RB5009 home-network series: run two IPv6 uplinks at once under one announceable provider-assigned /48, so a dead tunnel on one upstream pivots traffic to the other without the LAN losing routable IPv6. This post is WAN clean-slate — it replaces the WAN-side plumbing of the two equal-paths posts (VPS, Route64) with a self-contained multi-homed build, so you do not need to have read or built those posts first. The LAN side still assumes the VLAN foundation post — bridge, VLANs, inter-VLAN IPv4 firewall, per-VLAN DHCPv4, ULA-bound DoH resolver.

The hard prerequisite is a 32-bit ASN (<OWN_AS>) and an announceable /48 (<OWN_48>) — the assigning provider must authorize you to originate the /48 from the ASN, with a matching ROA for RPKI. The same <OWN_48> rides over both upstreams, so consistent origin matters more than which provider issues it. If you do not yet have either, follow jf.si's IPv6 ASN + BGP + WireGuard write-up for the acquisition step — this post is another flavor of the same idea (MikroTik RouterOS on the home side, Route64 as the second upstream, BFD on the VPS path) that picks up where it ends. The flavor I used was NoPkt for both the ASN and the /48 ($20 one-time + $60/year USD), and pdxnet.co.uk / getvps.net (AS 52025) for the transit VPS — $6/month including a free self-service BGP session, so <TRANSIT_AS> in the snippets below is 52025 for this flavor.

On top of the jf.si baseline (ASN + /48 + one transit VPS) you're adding the operational weight of a second BGP session and a BFD layer. That's worth weighing against what multi-homing actually buys you. It pays off if you self-host v6 services on <OWN_48> and want a public prefix that survives an upstream swap; if your two upstreams genuinely fail independently (different transits, different physical paths to the home); or if the build itself is the point — BGP, BFD, and RIR bureaucracy as a weekend project. If none of those apply — one path plus Happy Eyeballs fail-to-IPv4 already covers your failure modes invisibly — stop at the VPS path or the Route64 path and skip this post.

Every numbered section is paste-ready against a defconf RouterOS v7 box that already has the VLAN segmentation from the foundation post. Italicized notes are the rationale.

1. Topology

                     Internet (IPv4 + IPv6)
                            │
              ┌─────────────┴─────────────┐ ┌──────────────────────────┐
              │  Transit A — your VPS     │ │  Route64 PoP (WireGuard) │
              │  AS<OWN_AS>, runs BFD     │ │  AS 212895, no BFD       │
              │  iBGP to home over wg-host│ │  eBGP to home over wg-r64│
              └─────────────┬─────────────┘ └────────────┬─────────────┘
                            │                            │
                       wg-host                       wg-route64
                            │                            │
                            │ both transit your <OWN_48>│
                            │  and return ::/0 to home  │
                            │                            │
                       ┌────┴────────────────────────────┴────┐
                       │             home router              │
                       │  AS<OWN_AS>, originates <OWN_48>     │
                       │  receives ::/0 from both, best-path  │
                       │  installs VPS-learned default        │
                       └──────────────────────────────────────┘
                                       │
                          ┌────────────┴────────────┐
                          │  per-VLAN /64s from     │
                          │  <OWN_48> — same recipe │
                          │  as Per-VLAN IPv6 post  │
                          └─────────────────────────┘

Per-VLAN IPv6 from <OWN_48> is plumbed via the Per-VLAN IPv6 post once both BGP sessions are up.

2. WAN architecture

Three working pieces:

text

text

1A. VPS — runs BFD with home, eBGPs your /48 to upstream transit, 2 iBGP-originates ::/0 to home with empty AS_PATH 3B. Route64 — eBGPs your /48 from home to AS 212895, advertises ::/0 4 back with AS_PATH=[212895] 5C. Home — receives ::/0 from both sessions, BGP best-path installs the 6 VPS-learned default (shorter AS_PATH), Route64-learned 7 default is the backup

Home and VPS share <OWN_AS>, so the session between them is iBGP and the VPS-side ::/0 reaches home with an empty AS_PATH. Route64 sits in AS 212895, so its ::/0 arrives with AS_PATH=[212895]. No local-pref or MED is set on either session, so RouterOS best-path falls through to AS_PATH length — empty beats [212895] — and the VPS default wins. The Route64 default sits in BGP as the backup. Nothing on the home router explicitly marks one path preferred — the primary/backup ordering falls out of where each AS boundary sits.

The home router is the only place that needs to know about multi-homing. The VPS and Route64 each see exactly one BGP peer (home) and don't know the other exists. Both transits accept your <OWN_48> announcement on their respective sessions and reach <OWN_48> via the WireGuard tunnel.

3. Conventions and placeholders

PlaceholderMeaning
<OWN_AS>Your 32-bit ASN. Both home and the VPS use this; the session is iBGP.
<OWN_48>Your assigned /48, written without trailing zeros, e.g. 2a14:7583:eff9.
<TRANSIT_AS>The VPS provider's ASN (your eBGP peer from the VPS upstream-side). Provider tells you.
<TRANSIT_PEER_V6>Provider's IPv6 BGP peer address handed to your VPS. From the provider's BGP onboarding.
<VPS_IP>VPS public IPv4 (used as the WireGuard endpoint for the home → VPS tunnel).
<VPS_NIC>VPS public interface (ip -o link; typical enp3s0, ens3).
<VPS_PUBKEY> / <HOME_PUBKEY>WireGuard public keys, one per side. Printed during §4.
<VPS_ROUTER_ID> / <HOME_ROUTER_ID>Unique 32-bit BGP router IDs written like IPv4 addresses.
<R64_LINK>The /64 Route64 carves out for the BGP transport (portal calls it the point-to-point /64). ::1 is the PoP, ::2 is your home router.
<R64_*> (other)Other Route64 placeholders defined in the Route64 post §2.
<ULA_PREFIX>Your locally-generated ULA (same one the DNS post uses).
<CLIENT_GUA>A LAN client's GUA from <OWN_48>, used as the source in §8 induced-failover pings.

The Route64 portal needs your <OWN_AS> set as the tunnel's BYO ASN — the BGP session requires it. The field is on the tunnel page next to the WireGuard config.

<OWN_48> substitution mirrors the equal-paths posts: <OWN_48>:0::1/64 on the tunnel link, <OWN_48>:1::/64 for the trusted VLAN, etc.

4. VPS — WireGuard, transit BGP, iBGP to home, BFD

Two bird2 BGP sessions on the VPS: eBGP upstream to the transit provider (carries your <OWN_48> outbound and ::/0 inbound), and iBGP downstream to home (carries <OWN_48> inbound from home and ::/0 outbound). BFD only runs on the home-side session because that's the one your <OWN_48> rides over and the one that needs sub-second failure detection.

Each WireGuard tunnel needs the peer's public key in its own config, so the keygen runs on both sides before either config is pasted. The VPS script below prints <VPS_PUBKEY> at the end; <HOME_PUBKEY> comes from running the /interface/wireguard add name=wg-host … line in §5 first and reading the auto-generated public key with /interface/wireguard print where name=wg-host. The <R64_*> keys are not generated locally — Route64 hands you <R64_PRIVKEY> and <R64_SRV_PUBKEY> on the tunnel page.

Assumes a minimal Ubuntu install. bird listens on TCP/179 on all interfaces by default; the nftables ruleset below scopes which NIC each session is reachable on — transit NIC for the upstream session, wg0 for the home session.

VPS — wg0 + bird2 (transit eBGP + home iBGP + BFD) + nftables

bash

1set -e 2apt-get update -qq 3apt-get install -y -qq wireguard bird2 nftables 4 5cat >/etc/sysctl.d/99-multi-homed.conf <<'EOF' 6net.ipv6.conf.all.forwarding = 1 7net.ipv6.conf.default.forwarding = 1 8net.ipv6.conf.<VPS_NIC>.accept_ra = 2 9EOF 10sysctl --system >/dev/null 11 12umask 077 13mkdir -p /etc/wireguard 14wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub 15VPS_PRIVKEY=$(cat /etc/wireguard/server.key) 16 17cat >/etc/wireguard/wg0.conf <<EOF 18[Interface] 19PrivateKey = ${VPS_PRIVKEY} 20Address = <OWN_48>:0::1/64, fe80::1/64 21ListenPort = 51820 22MTU = 1420 23Table = off 24 25[Peer] 26PublicKey = <HOME_PUBKEY> 27AllowedIPs = <OWN_48>:0::2/128, <OWN_48>::/48 28PersistentKeepalive = 25 29EOF 30 31systemctl enable --now wg-quick@wg0 32echo "VPS public key: $(cat /etc/wireguard/server.pub)" 33 34cat >/etc/nftables.conf <<'EOF' 35#!/usr/sbin/nft -f 36flush ruleset 37 38table inet filter { 39 chain input { 40 type filter hook input priority filter; policy drop; 41 42 ct state established,related accept 43 ct state invalid drop 44 iif lo accept 45 meta l4proto { icmp, icmpv6 } accept 46 47 tcp dport 22 accept # SSH 48 udp dport 51820 accept # WireGuard from home 49 iifname "<VPS_NIC>" tcp dport 179 accept # BGP from transit 50 iifname "wg0" tcp dport 179 accept # BGP from home, wg0 only 51 iifname "wg0" udp dport 3784 accept # BFD from home, wg0 only 52 } 53 54 chain forward { 55 type filter hook forward priority filter; policy drop; 56 57 ct state established,related accept 58 iifname "wg0" accept # LAN -> internet 59 oifname "wg0" accept # internet -> LAN 60 } 61 62 chain output { 63 type filter hook output priority filter; policy accept; 64 } 65} 66EOF 67systemctl enable --now nftables 68 69mkdir -p /etc/bird 70cat >/etc/bird/bird.conf <<'EOF' 71log syslog all; 72router id <VPS_ROUTER_ID>; 73 74protocol device { } 75 76protocol direct { 77 ipv6; 78 interface "wg0", "<VPS_NIC>"; 79} 80 81protocol kernel kernel6 { 82 metric 32; 83 ipv6 { 84 # Pull only ::/0 from the kernel. This is what becomes locally- 85 # originated in BGP (empty AS_PATH) and what wins best-path on home. 86 import filter { 87 if net = ::/0 then accept; 88 reject; 89 }; 90 91 # Install the BGP-learned <OWN_48> (from home) into the kernel so 92 # return traffic to home actually goes via wg0. 93 export filter { 94 if net = <OWN_48>::/48 then accept; 95 reject; 96 }; 97 }; 98 learn yes; 99} 100 101# Active BFD probing toward home. Without an explicit neighbor, bird is 102# passive; after a flap both sides wait for the other and recovery stalls. 103protocol bfd { 104 interface "wg0" { 105 min rx interval 200 ms; 106 min tx interval 200 ms; 107 idle tx interval 1 s; 108 multiplier 3; 109 }; 110 neighbor <OWN_48>:0::2 dev "wg0"; 111} 112 113# iBGP downstream to home — both ends in <OWN_AS>. 114protocol bgp home { 115 local <OWN_48>:0::1 as <OWN_AS>; 116 neighbor <OWN_48>:0::2 as <OWN_AS>; 117 bfd on; 118 119 ipv6 { 120 import filter { 121 if net = <OWN_48>::/48 then accept; 122 reject; 123 }; 124 125 export filter { 126 if net = ::/0 then accept; 127 reject; 128 }; 129 130 next hop self; 131 }; 132} 133 134# eBGP upstream to transit — your <OWN_AS> peering with <TRANSIT_AS>. 135# The transit hands you a peer address (<TRANSIT_PEER_V6>) over the 136# public NIC; the session is single-hop and rides the on-link /64. 137protocol bgp transit { 138 local as <OWN_AS>; 139 neighbor <TRANSIT_PEER_V6> as <TRANSIT_AS>; 140 141 ipv6 { 142 # Accept only ::/0 from transit. Anything more-specific is 143 # provider-routed and would compete with our own announcements. 144 import filter { 145 if net = ::/0 then accept; 146 reject; 147 }; 148 149 # Originate only <OWN_48> upstream. ROA must already authorize this 150 # origin or transit will drop it via RPKI. 151 export filter { 152 if net = <OWN_48>::/48 then accept; 153 reject; 154 }; 155 }; 156} 157EOF 158chown -R bird:bird /etc/bird 159 160mkdir -p /etc/systemd/system/bird.service.d 161printf '[Service]\nRestart=on-failure\nRestartSec=2s\n' \ 162 > /etc/systemd/system/bird.service.d/restart.conf 163systemctl daemon-reload 164systemctl enable --now bird

The explicit neighbor <OWN_48>:0::2 dev "wg0" line in the protocol bfd block is what turns this side into the active prober. Without it bird is passive — it answers BFD packets but never originates them. If the home side is also passive (or briefly drops out), both ends sit waiting for the other and the session never re-establishes. The config will work fine on first boot and fail to recover from the first real outage.

Two separate protocol bgp blocks because the sessions have very different shapes — iBGP to home over wg0 with BFD, eBGP to transit over the public NIC without. The transit session has no BFD by default; whether your transit provider supports it varies and is not required for the multi-homed story to work. The kernel import filter taking only ::/0 is what gives home an empty AS_PATH on the route — bird treats kernel-learned routes as locally originated, and iBGP doesn't prepend.

5. Home router — both BGP sessions, BFD on the VPS one

The configuration below is RouterOS-only. If your home router is Linux/bird2 or VyOS, take §4 as the template: it's the same bird2 session shape you need at home, with the BGP roles swapped — home originates <OWN_48> (kernel-import a static blackhole for it) and imports ::/0 from both peers; VPS originates ::/0 (already shown) and imports <OWN_48> from home. The Route64 session is plain eBGP with no BFD.

Three blocks below — origination + aggregate, VPS session, Route64 session. The first block stands up the BGP instance and the locally-originated /48 that both sessions advertise; the second and third blocks are independent and either order works.

Home router — BGP instance + originated /48 (shared by both sessions)

bash

1/ipv6/route add dst-address=<OWN_48>::/48 blackhole distance=254 \ 2 comment="aggregate-for-bgp" 3 4/ipv6/firewall/address-list add list=bgp-networks-own \ 5 address=<OWN_48>::/48 comment="/48 to both upstreams" 6 7/routing/bgp/instance add name=default-bgp as=<OWN_AS> router-id=<HOME_ROUTER_ID>

Home router — VPS path WireGuard + iBGP + BFD

bash

1/interface/wireguard add name=wg-host listen-port=51820 mtu=1420 2/interface/wireguard/peers add interface=wg-host name=vps \ 3 public-key="<VPS_PUBKEY>" \ 4 endpoint-address=<VPS_IP> endpoint-port=51820 \ 5 allowed-address=::/0 \ 6 persistent-keepalive=25s 7 8/ipv6/address add address=<OWN_48>:0::2/64 interface=wg-host advertise=no 9 10/routing/filter/rule add chain=bgp-in-vps \ 11 rule="if (dst == ::/0) { accept } reject" 12/routing/filter/rule add chain=bgp-out-vps \ 13 rule="if (dst == <OWN_48>::/48) { accept } reject" 14 15/routing/bgp/template add name=tpl-host as=<OWN_AS> use-bfd=yes 16/routing/bgp/connection add name=host-vps instance=default-bgp \ 17 remote.address=<OWN_48>:0::1 remote.as=<OWN_AS> \ 18 local.address=<OWN_48>:0::2 local.role=ibgp \ 19 templates=tpl-host afi=ipv6 use-bfd=yes \ 20 input.filter=bgp-in-vps \ 21 output.network=bgp-networks-own output.filter-chain=bgp-out-vps 22 23/routing/bfd/configuration/add interfaces=wg-host \ 24 min-rx=200ms min-tx=200ms multiplier=3 25 26# BFD's UDP/3784 packets arrive unsolicited, so the defconf 27# established,related,untracked rule doesn't cover them. The BGP 28# session itself is dialed out by home and needs no input rule. 29/ipv6/firewall/filter add chain=input action=accept protocol=udp dst-port=3784 \ 30 in-interface=wg-host comment="BFD from VPS" \ 31 place-before=[find where chain=input and comment="defconf: drop everything else not coming from LAN"] 32# place-before= pins the new accept above the defconf drop. If your 33# RouterOS version's defconf wording differs, [find ...] returns 34# nothing and the rule lands at the bottom (after the drop) — swap to 35# a numeric place-before= in that case.

Home router — Route64 path WireGuard + eBGP, no BFD

bash

1/interface/wireguard add name=wg-route64 mtu=1420 \ 2 listen-port=<R64_POP_PORT> private-key="<R64_PRIVKEY>" 3/interface/wireguard/peers add interface=wg-route64 \ 4 public-key="<R64_SRV_PUBKEY>" \ 5 endpoint-address=<R64_POP_IP> endpoint-port=<R64_POP_PORT> \ 6 allowed-address=::/0 persistent-keepalive=15s 7/ipv6/address add address=<R64_LINK>::2/64 interface=wg-route64 advertise=no 8 9/routing/filter/rule add chain=bgp-in-r64 \ 10 rule="if (dst == ::/0) { accept } reject" 11/routing/filter/rule add chain=bgp-out-r64 \ 12 rule="if (dst == <OWN_48>::/48) { accept } reject" 13 14# Route64 portal must have BYO ASN set to <OWN_AS> for this to peer. 15/routing/bgp/connection add name=host-r64 instance=default-bgp \ 16 remote.address=<R64_LINK>::1 remote.as=212895 \ 17 local.address=<R64_LINK>::2 local.role=ebgp \ 18 afi=ipv6 \ 19 input.filter=bgp-in-r64 \ 20 output.network=bgp-networks-own output.filter-chain=bgp-out-r64

No input firewall rule is needed for either WireGuard peer at base — both BGP sessions dial out from home on TCP/179, so the return traffic rides the defconf established,related,untracked rule. The only unsolicited inbound is BFD/3784, which exists only on wg-host.

The Route64 link uses Route64's <R64_LINK> /64 from the portal (the point-to-point pair, ::1/::2) as the BGP session addressing — your <OWN_48> does not appear in the Route64 transport at all; it appears in the BGP advertisement that rides over it.

6. BFD where the peer supports it

BFD is enabled where it works (AS 52025-class transits like the VPS upstream above, where bird2 on a peer you operate runs BFD) and skipped where it doesn't. Route64 does not reply to BFD — use-bfd=yes on the host-r64 connection drops the BGP session — so the home-router BGP configuration in §5 only attaches BFD to the host-vps connection.

The host-r64 connection runs plain BGP liveness — the only option, since Route64 doesn't support BFD — and that's fine for the backup-path role it occupies: the fast-failover work is done by the primary's BFD. When BFD says the VPS path is dead, RouterOS withdraws the VPS-learned ::/0 within ~1.5 s and best-path immediately switches to the Route64-learned ::/0, which is already in BGP, just not active.

Failure modeWhat detects itRecovery time
VPS WG path dead, Route64 still upBFD on wg-host~1.5 s to switch
Route64 path dead, VPS still upirrelevant — VPS is already primary; no client-visible event0
Both paths dead simultaneouslynetwatch (§7)~6–8 s to drain LAN RA
VPS path recovers, Route64 was activeBFD comes back up~10 s to reinstall

The second row is the asymmetry worth internalizing. If only Route64 fails, nothing happens at the LAN — Route64's ::/0 is the backup, not the active path, so its withdrawal is invisible to clients.

7. Last-resort fallback — netwatch + LAN RA drain

If both upstreams fail at once, neither BGP session has a route to withdraw against — there is no surviving primary to fail over to. The LAN would happily continue picking the home router as its IPv6 default even though the router can't reach anything beyond <OWN_48>. The mitigation, lifted directly from the Route64 post §6, is a netwatch that drains LAN RA so clients fall back to IPv4 by Happy Eyeballs.

Home router — netwatch drains LAN RA when both paths are gone

bash

1/tool/netwatch add name=v6health type=tcp-conn \ 2 host=2606:4700:4700::1111 port=443 \ 3 interval=5s timeout=2s comment=v6health \ 4 up-script="/ipv6/nd set [find interface=bridge] ra-lifetime=30m; /ipv6/nd set [find interface=vlan-iot] ra-lifetime=30m; /ipv6/nd set [find interface=vlan-guest] ra-lifetime=30m; :log info v6-up" \ 5 down-script="/ipv6/nd set [find interface=bridge] ra-lifetime=0s; /ipv6/nd set [find interface=vlan-iot] ra-lifetime=0s; /ipv6/nd set [find interface=vlan-guest] ra-lifetime=0s; :log info v6-down-failedtoIPv4"

The probe is a TCP-connect to Cloudflare's IPv6 anycast on 443 — it exits via whichever ::/0 is active, so a single netwatch covers both paths. It does not distinguish VPS-down from Route64-down, by design: BFD + BGP best-path already handle single-path failures invisibly, so the netwatch only needs to fire when neither path is forwarding — the one state where the LAN must drop IPv6 entirely.

RouterOS 7.22's IPv6 ICMP netwatch is broken (type=icmp stays "down" for v6 targets even when /ping works) — type=tcp-conn is the working replacement. End-to-end client failover is netwatch detection (~5–7 s at interval=5s timeout=2s) plus the ~0.6 s unsolicited RA RouterOS emits whenever ra-lifetime changes ≈ ~6–8 s, symmetric on recovery. The set [find interface=...] lines start working as soon as Per-VLAN IPv6 is applied (substitution: <GUA_LAN>=<OWN_48>:1, <GUA_IOT>=<OWN_48>:10, <GUA_GUEST>=<OWN_48>:20).

8. Verification

Home router — both sessions healthy

bash

1# Both BGP sessions established 2/routing/bgp/session/print 3# expect: host-vps established 4# host-r64 established 5 6# BFD up on the VPS session only 7/routing/bfd/session/print 8# expect: one entry, state=up, peer=<OWN_48>:0::1 9 10# Active default route 11/routing/route/print where dst-address=::/0 12# expect: two ::/0 candidates; the bgp.as-path=[] one is active 13 14# The active default's gateway is the VPS WG endpoint 15/ipv6/route/print where active and dst-address=::/0 16# expect: gateway=<OWN_48>:0::1%wg-host 17 18# netwatch healthy 19/tool/netwatch/print where comment=v6health 20 21# BFD/3784 input rule lives above the defconf drop. 22# The §5 place-before=[find ...] depends on the defconf comment string 23# in your RouterOS version; if it doesn't match, the rule lands at the 24# bottom of the chain (after the drop) and BFD silently never arrives. 25/ipv6/firewall/filter print 26# expect: the chain=input udp dst-port=3784 rule above the 27# "defconf: drop everything else not coming from LAN" rule

VPS — transit + home sessions healthy

bash

1birdc show protocols 2# expect: home (bgp) Established 3# transit (bgp) Established 4# bfd1 (bfd) Up 5 6birdc show route ::/0 all 7# expect: best path via wg0 to <OWN_48>:0::2 from home (iBGP, AS_PATH empty) 8# plus transit's ::/0 from <TRANSIT_PEER_V6> 9 10birdc show route <OWN_48>::/48 all 11# expect: via wg0 from home (learned by iBGP), exported to transit

Induced failover

Verify primary→backup pivot

bash

1# On the VPS, drop BFD packets to simulate a half-dead tunnel. 2# BFD declares down in ~700 ms; bird withdraws ::/0 from home; home's 3# best-path picks the Route64-learned ::/0. 4nft add rule inet filter input iifname wg0 udp dport 3784 drop 5 6# On home router: time it. 7/log/print where message~"BGP|BFD" 8/ipv6/route/print where active and dst-address=::/0 9# expect: gateway now <R64_LINK>::1%wg-route64 10 11ping -c 5 -I <CLIENT_GUA> 2606:4700:4700::1111 12# expect: 1 dropped packet at the switchover, rest reach via Route64 13 14# Undo it — BFD comes back, best-path returns to VPS. 15nft -a list ruleset | grep "udp dport 3784 drop" # note the handle 16nft delete rule inet filter input handle <handle>

Verify backup-only failure is invisible to the LAN

bash

1# Disable Route64 alone. Because VPS is already best-path, this should 2# produce no active-route change and no v6-down log line — Route64 3# leaves BGP, the LAN sees nothing. 4/interface/wireguard/peers/disable [find interface=wg-route64] 5/ipv6/route/print where active and dst-address=::/0 6# expect: gateway still <OWN_48>:0::1%wg-host 7/log/print where message~"v6-(up|down)" 8# expect: no new entries 9 10/interface/wireguard/peers/enable [find interface=wg-route64]

Verify both-paths-dead fallback

bash

1# Stop WireGuard on the VPS and disable Route64 on home simultaneously. 2# Within ~8 s the netwatch fires; clients drop their v6 default and 3# Happy-Eyeballs to IPv4. 4ssh vps "wg-quick down wg0" 5/interface/wireguard/peers/disable [find interface=wg-route64] 6/log/print where message~"v6-(up|down)" 7 8# Restore. 9/interface/wireguard/peers/enable [find interface=wg-route64] 10ssh vps "wg-quick up wg0"

A brief IPv6 miss at the switchover plus a 6–8 s window before clients drop to IPv4 when both paths die — instead of either a hold-time-long blackhole or a permanent LAN-thinks-it-has-v6 stall — is the whole point of this build.

After both BGP sessions are established and verified, continue to Per-VLAN IPv6 on RouterOS to plumb <OWN_48> through to every VLAN — per-VLAN GUA + ULA + RA RDNSS, IPv6 forward-chain isolation, and SLAAC anti-spoof, using the substitution <GUA_LAN>=<OWN_48>:1, <GUA_IOT>=<OWN_48>:10, <GUA_GUEST>=<OWN_48>:20.

Glossary

AcronymExpansionReference
AS / ASNAutonomous system (number)RFC 1930
BFDBidirectional Forwarding DetectionRFC 5880
BGPBorder Gateway ProtocolRFC 4271
eBGPexternal BGP (across AS boundary)RFC 4271 §3.2
iBGPinternal BGP (within one AS)RFC 4271 §3.2
LIRLocal Internet RegistryRIPE NCC
ROARoute Origin Authorization (RPKI)RFC 6482
RPKIResource Public Key InfrastructureRFC 6480

Series-wide acronyms (CGNAT, DoH, GUA, RA, RDNSS, SLAAC, ULA, VLAN, VPS, WireGuard) live in the index glossary.

References


Disclosure: the NoPkt and pdxnet.co.uk links above are affiliate links — signing up through them earns me a referral credit at no extra cost to you. I am recommending both providers because I use them on this build, not because of the credit.

Share

Comments

Comments are powered by GitHub Discussions and require a free GitHub account to post.