Mikrotik dual ISP setup

This is a guide on how to setup a failover ISP for your Mikrotik router. With this setup, the router should seamlessly transition from main ISP to the failover when the main ISP becomes unavailable. There should be no downtime for the user.

This article is an expansion over the official documentation, which is a bit lacking in detail.

Setup

Let's say we have two ISP connections:

In this example, a separate bridge to the LTE router was created and a DHCP client assigned to it.

First, make sure both the pppoe client and the dhcp client don't setup default routes.

PPP -> pppoe-out1 -> Dial Out -> uncheck Add Default Route
IP -> DHCP Client -> (bridge name) -> set Add Default Route to no

For this setup to work, we need some external IP addresses that the router can ping with the gateway ping option.
Public DNS servers are good candidates, but check if they can be pinged first. Note that they are not actually used for DNS.

Let's pick the OpenDNS and Quad9 servers:

OpenDNS (A)
208.67.222.222
208.67.220.220

Quad9 (B)
9.9.9.9
9.9.9.10

We are going to create routes to these hosts via gateway1 (pppoe-out1 gateway 10.0.0.1) and gateway2 (failover router IP 10.21.12.1).

/ip route add dst-address=208.67.222.222 gateway=10.0.0.1 scope=10 comment="PPPOE-A"
/ip route add dst-address=9.9.9.9 gateway=10.0.0.1 scope=10 comment="PPPOE-B"
/ip route add dst-address=208.67.220.220 gateway=10.21.12.1 scope=10
/ip route add dst-address=9.9.9.10 gateway=10.21.12.1 scope=10

Note that we added two comments for the pppoe routes, which will come in handy later.

Virtual Hops

Next step is to add "virtual hops" to these routes. These are some random IP addresses that will be used as gateway for our routes. The point is that the router will recursively resolve routes until it reaches one ISP or the other, depending on their availability or distance metric that we will set.

Choose two random addresses for the virtual hops, making sure they don't conflict with anything in your local network:

Let's now add the routes:

/ip route add dst-address=10.1.1.1 gateway=208.67.222.222 scope=10 target-scope=10 check-gateway=ping
/ip route add dst-address=10.1.1.1 gateway=9.9.9.9 scope=10 target-scope=10 check-gateway=ping
/ip route add dst-address=10.2.2.2 gateway=208.67.220.220 scope=10 target-scope=10 check-gateway=ping
/ip route add dst-address=10.2.2.2 gateway=9.9.9.10 scope=10 target-scope=10 check-gateway=ping 

The final step is to add default routes through the two virtual hops.

/ip route add distance=1 gateway=10.1.1.1
/ip route add distance=2 gateway=10.2.2.2 

Now, make sure everything is OK:

Check /ip route and see if the default routes (the routes to 0.0.0.0/0) show something like:

recursive via 10.0.0.1 pppoe-out1

The default route with distance 1 should be active while the one with distance 2 should not be (inactive routes are shown in blue).

Try disabling one of the interfaces (pppoe-out1 or failover bridge) or better, unplug the network cable and see if the other route becomes active.

Quirks

In this example we used 10.0.0.1 as the pppoe gateway, but this is likely to be a dynamic value set by the PPPoE server. To use it in our setup, we need a script to update the routes when the pppoe gateway changes.

To do this, create a custom pppoe profile:

 PPP -> Profiles -> Add

Then navigate to Scripts and add the following code in the On Up section:

:local newgw [/ip address get [find interface="pppoe-out1"] network];
/ip route set [find comment="PPPOE-A"] gateway=$newgw;
/ip route set [find comment="PPPOE-B"] gateway=$newgw;

In this script, we used the comments we set earlier to identify the two routes where we need to update the gateway.

The only remaining thing is to replace the default profile on the pppoe interface with the one we created:

 PPP -> Interface -> pppoe-out1 -> Profile: myprofile

Email notifications

A nice-to-have would be to get notified when the primary ISP goes down and the failover kicks in. This can be achieved through scripting.
First, make sure the router can send emails.

/tool e-mail

If your getting a timeout error when trying to Send email, you may want to try to connect to the email server via telnet.

/system telnet 1.2.3.4 25

If connection doesn't work most likely you need to allow input to the router on port 25.

Next step would be to setup a schedule to run a script on a regular basis, checking if the primary ISP is active.

/system scheduler

:local metric;
:set metric [/ip route get [find dst-address=0.0.0.0/0 active=yes] distance];
:if ($metric = 2) do={ /tool e-mail send to="hi@mihai.fm" subject="Internet connection drop" body="Failover kicked in" };

The script uses the route distance we set earlier. If the default route (0.0.0.0/0) has a distance of 2, it means that the
failover ISP has kicked in, so we need to send an email.

The scheduler script needs the following permissions: read, write, policy, test.
I set mine to run at a one hour interval.

2025-07-08

Comments