Minimal control plane for Wireguard (site to site via a VPS)

Hi,

I've got two sites I want to connect with a VPN (Wireguard seems easiest to configure). The same ISP, IPv6, public addresses but they may change over time. I know Wireguard tolerates changing addresses (one at a time), but I would like to make sure that the tunnel won't die even if both ends of the tunnel change IP's (remember, the same ISP).

I've got a Linux VPS, to which I can connect both routers. However, given the network conditions (same ISP) I'd rather the connection between sites was direct and the VPS was used only as a randevouz point that allows routers to establish their addresses. I will probably set up a routing protocol to allow the VPS act as a backup connection but only if the direct connection fails. The VPS has a stable address.

Is there a way/tool in ROS to make routers establish wireguard connections to VPS and then discover each other end establish direct connections for better performance.

Kind regards,
s

If your use case is more on management between sites then use zerotier/tailscale specially for light loaded application if you do have dynamic ips

DMVPN is possible but it's not supported in Mikrotik but you still need stable public ips

@steelman If you want a very easy, web-based managed VPN network, use a modern SD-WAN solution like for example the built-in ZeroTier package or a container-based Tailscale setup.

SD-WAN installation and management in a nutshell:

  1. Install the SD-WAN client on all nodes you want to include in your VPN network.
  2. Go to the web-based controller and authorize each node you want to participate in your network.
  3. Done.

Forget about DMVPN. It's Cisco’s old, proprietary, and pretty static from a setup/admin point of view, and is an IOS/IOS XE-based IPsec/GRE/NHRP VPN overlayv (published way back in 2002).

It's do-able without external tools or complicated routing protocol setup.

We assume that the LAN subnet behind router 1, to be accessible from router 2 is 192.168.10.0/24. And the LAN subnet behind router 2, to be accessible from router 1 is 192.168.20.0/24.

On each of the two routers, add a separate WireGuard interface (let's say wg1) with the subnet, for example 10.0.10.0/24.

  • Router 1 has WG address 10.0.10.100/24 on its wg1.
  • Router 2 has WG address 10.0.10.200/24 on its wg1.
  • Router 1 has direct WG peer to router 2 on wg1, with allowed-address=10.0.10.200/32,192.168.20.0/24.
  • Router 2 has direct WG peer to router 1 on wg1, with allowed-address=10.0.10.100/32,192.168.10.0/24.

On each of the two routers, configure a 2nd WireGuard interface (let's say wg2), listening on different UDP port from the one of wg1, of course. This interface is for the communication with the VPS. The used subnet is for example 10.0.20.0/24.

  • Router 1 has WG address 10.0.20.100/24 on its wg2.
  • Router 2 has WG address 10.0.20.200/24 on its wg2.
  • Router 1 has WG peer to VPS on wg2, with allowed-address=10.0.10.0/24,192.168.20.0/24.
  • Router 2 has WG peer to VPS on wg2, with allowed-address=10.0.10.0/24,192.168.10.0/24.

On VPS router:

  • VPS has WG address Address = 10.0.20.1/32 under [Interface].
  • In the [Peer] setting towards router 1, set AllowedIPs = 10.0.20.100/32, 192.168.10.0/24.
  • In the [Peer] setting towards router 2, set AllowedIPs = 10.0.20.200/32, 192.168.20.0/24.
  • Assuming tools like wg-quick is used, corresponding routes should be automatically installed.
  • Make sure forwarding is enabled (net.ipv4.ip_forward=1).

On router 1, we add routes towards the router 2's LAN subnet 192.168.20.0/24. The route with lower distance uses the direct WG link to router 2. The failover route uses the WG link to VPS.

/ip route
add dst-address=192.168.20.0/24 check-gateway=ping gateway=10.0.10.200 distance=1
add dst-address=192.168.20.0/24 check-gateway=ping gateway=10.0.20.200 distance=2

On router 2, we add routes towards the router 1's LAN subnet 192.168.10.0/24. The route with lower distance uses the direct WG link to router 1. The failover route uses the WG link to VPS.

/ip route
add dst-address=192.168.10.0/24 check-gateway=ping gateway=10.0.10.100 distance=1
add dst-address=192.168.10.0/24 check-gateway=ping gateway=10.0.20.100 distance=2

Make sure the firewall on all three devices allows forwarding between the relevant subnets.

With the configuration, when the WG link (interface wg1) between the two routers in working, and they can ping themselves through it, then the traffic between the two LAN subnets will use this link. If it's down, the link through the VPS will be used.

Same principle applies if the two LAN subnets use IPv6. You can use fixed ULA addresses for the WG interfaces in place of the 10.0.x.y ones.

@CGGXANNX, your setup still needs to be complemented with WG endpoints using DDNS entries and a script that updates the WG endpoints when the IP address changes.

Otherwise, it works as a static/failover setup, but it doesn't really solve the original “rendezvous” part where both routers can change address and still rediscover each other automatically.

And if you also want to run this dual-stack, there's another dimension to handle as well, since IPv4/IPv6 endpoint selection and failover behavior on ROS still need extra care (it's still not dual-stack safe)

That's also why I suggested an SD-WAN solution like ZeroTier or Tailscale instead, since peer discovery, endpoint roaming, NAT traversal, and dual-stack handling are basically what they're built to handle.

When you say linux VPS, do you mean you rent space in the cloud. If so, for any business case, VPS is not a secure method as there is no way to know who can access your setup and thus wireguard to the VPS as an endpoint is not ideal. One can get wireguard through the VPS and not really use it as an endpoint and that gets far more complex. I concur with Larsa that zerotier is better if one believes two wireguards are necessary.......

I thought the way wireguard works is that both ends update the other on changes to their address and thus unless this change happened within the same seconds, I dont see the issue with sticking to one ordinary wg setup. In other words much angst for a very rare occasion if any.

@steelman, if you're going to use WG with dynamic IPv4 addresses, you need to make sure that the endpoint address on both your VPS and MT is updated through DDNS, and use the DDNS name as the WG endpoint-address.

Since WG doesn't automatically detect dynamic IP address changes of the endpoint-address, you need to run a script to trigger WG to refresh/update the endpoint address when it changes. Run a script like the example below, say every 30 seconds with the ROS scheduler. Create a corresponding script on your VPS as well.

:foreach i in=[/interface/wireguard/peers/find where disabled=no endpoint-address~"[a-z]\$"] do={
  :local LastHandshake [/interface/wireguard/peers/get $i last-handshake]
  :if (([:tostr $LastHandshake] = "") or ($LastHandshake > [:totime "3m"])) do={
    :local Hostname [/interface/wireguard/peers/get $i endpoint-address]
    :local Interface [/interface/wireguard/peers/get $i interface]
    /interface/wireguard/peers/set $i endpoint-address=$Hostname
    :log info "WG-Check-Endpoint-Address: WG $Interface refreshed endpoint-address $Hostname"
  }
}

@anav

When you say linux VPS, do you mean you rent space in the cloud. If so, for any business case, VPS is not a secure method as there is no way to know who can access your setup and thus wireguard to the VPS as an endpoint is not ideal.

Fortunately it's not for business. I am aware of those downsides, and I've got a few options to choose from, including a collocation of an SBC in a friendly server room.

I thought the way wireguard works is that both ends update the other on changes to their address and thus unless this change happened within the same seconds

You are almost right. If there is no traffic between WG endpoints, they may not notice their addresses have change for quite a while. When they do, it may be too late to recover. There other scenario when a WG link fails is when both endpoint addresses change and routers are rebooted (does ROS update the saved endpoint addresses?).

Thank you! This looks great and I will definitely start with this setup. And because temporary solutions are most durable I guess it will last (-;

This check-gateway option will make it work even if the WAN IP of one of routers changes. I didn't know about this one.

To supplement your solution and make it handle changing routers' IPs I'll try the following:

  • on the VPS: set up a service bound to the WireGuard interface (wg0) which upon connection runs wg show wg0 endpoints.
  • on routers: periodically run a script that connects to that service, parses its output and adjusts configuration if needed (I hope ROS scripting is capable enough).

@Larsa I don't need NAT traversal, I will use IPv6 for WG endpoints as both sites have full IPv6 connectivity. Than you for your suggestions.

zerotier/tailscale

I've studied these and I was hoping a lightweight self-hosted option exists. Both of these can be self-hosted but they seem to be more complex than it is justified for two maybe three sites.