This project focused on configuring policy-based routing on a MikroTik router to route traffic through different ISPs and a GRE/IPsec tunnel based on destination IP addresses. The goal was to provide users with access to different services without requiring them to manually change network connections or access points.
The network had two Internet connections with different characteristics. The primary ISP provided the main Internet connection, while the second ISP provided a lower-latency and more reliable connection with limited bandwidth and higher cost. The second connection was therefore reserved for latency-sensitive services such as VoIP calls and online meetings.
In addition, because some services and websites outside Iran were restricted when accessed directly from the local Internet connection, non-Iranian destination IP addresses needed to be routed through a GRE tunnel to a remote VPS. Iranian destination IP addresses could continue using the primary ISP directly.
To implement this, I used MikroTik firewall address lists to identify destination networks, firewall mangle rules to mark packets based on their destinations, and policy-based routes to forward the marked traffic through the appropriate WAN connection or GRE tunnel.
As a result, Iranian traffic continued to use the primary WAN, non-Iranian traffic was routed through the GRE/IPsec tunnel, and selected Google Meet and VoIP traffic was routed through the second ISP. This allowed users to access required services and make calls and meetings without manually changing their connection.
The main objective was to replace a single default routing path with policy-based routing that could select different physical and logical paths based on the destination of the traffic.
The specific objectives were:
Route Iranian and non-Iranian destination IP addresses through different interfaces.
Route Google Meet, VoIP, and other latency-sensitive traffic through the lower-latency second ISP.
Route non-Iranian traffic through the GRE/IPsec tunnel while keeping Iranian traffic on the primary WAN.
Allow users to access these services without manually switching between different network connections.
By the end of the project, the router needed to classify traffic based on destination IP addresses and automatically select the appropriate WAN or tunnel for each traffic type.
The network consisted of a MikroTik router acting as the central routing device. It connected the local users to two separate ISPs and also maintained a GRE tunnel with IPsec encryption to a remote VPS.
The physical and logical design allowed the router to use the primary WAN for normal local traffic, the second WAN for selected latency-sensitive services, and the GRE/IPsec tunnel for non-Iranian destinations.
The physical topology was based on two WAN connections and two LAN segments connected to the MikroTik router:
ISP-1 ISP-2
| |
Modem Modem
| |
ether1 ether2
| |
+------- MikroTik -------+
Router
|
+-------------+-------------+
| |
ether5 ether4
| |
LAN Switch LAN Switch
The MikroTik router also established a GRE tunnel with IPsec encryption to a remote VPS:
MikroTik Router
|
GRE over IPsec
|
Remote VPS
This was a branch network where users needed reliable access to Internet services for communication, social media, customer interaction, and marketing activities. The main requirement was not simply higher bandwidth, but the ability to route different types of traffic through the connection best suited to them.
The primary ISP was connected to ether1 and provided the main Internet connection. Local users accessed the Internet through the MikroTik router, which also provided NAT, DHCP, and DNS caching.
The second ISP was connected to ether2. It provided lower latency, higher uptime, and dedicated bandwidth, but had lower bandwidth and a limited monthly traffic allowance because of its higher cost. For this reason, it was not suitable as the default route for all users. Instead, it was reserved for latency-sensitive services such as VoIP and online meetings.
The router also maintained a GRE tunnel with IPsec encryption to a remote VPS. This tunnel was used for traffic destined for non-Iranian IP addresses.
The MikroTik router therefore performed the following main routing decisions:
Iranian destinations → Primary ISP (ether1)
Google Meet and selected VoIP destinations → Secondary ISP (ether2)
Other non-Iranian destinations → GRE/IPsec tunnel
The LAN consisted of wired devices connected through switches.
Because I was not permitted to use the original project's IP addresses or other real network data, I recreated the environment using different IP ranges. This allowed me to reproduce and test the configuration in a MikroTik RouterOS virtual machine running on VMWare, exactly same as the project.
To keep the project focused, I only included the IP addresses and configurations directly related to the routing design.
Interface Purpose Network
ether1 WAN-1 192.168.88.0/24
ether2 WAN-2 192.168.11.0/24
GRE Tunnel Tunnel to VPS 172.16.1.0/30
ether5 LAN Switch 192.168.10.0/27
ether4 LAN WAP 192.168.10.128/27
The main device configured in this project was the MikroTik edge router running RouterOS v6. The other network devices were already configured and did not affect the routing configuration, so they are not covered in detail.
The main RouterOS features used in this project were:
Firewall Address Lists
Firewall Mangle
Routing Marks
Static Routes
GRE Tunnel
IPsec
NAT
RouterOS Ping and Traceroute tools
I also used the built-in RouterOS testing tools, interface traffic counters, and firewall rule counters to verify that packets were following the intended routing paths.
This section covers the configuration changes made on the MikroTik edge router to implement the routing design described in the Network Architecture section.
The network was already operational before this project. The purpose of these changes was to improve traffic routing and service stability by directing different traffic types through the most appropriate network path. I therefore only describe the configurations related to the policy-based routing implementation.
To classify traffic, I needed destination IP address lists for Iranian networks and Google Meet. For Iranian networks, I used the source described in a separate blog post on my website, where I explain how I maintain the list and represent the networks efficiently using CIDR notation. For Google Meet, I used the CIDR ranges provided by Google.
Because these address lists are long, I exported them as .rsc files rather than including the complete lists in this documentation. The files are provided as project resources at the end of the project.
The router's primary Internet connection was connected to ether1 through a modem. The router initially received its address from the modem's DHCP server. To make the connection more predictable, I configured a static IP assignment for the router on the modem and configured the corresponding address on the MikroTik router.
/ip address
add address=192.168.88.10/24 comment=WAN-1 interface=ether1 network=192.168.88.0
I then connected the second modem to ether2. This connection was intended primarily for VoIP and other latency-sensitive services, so I assigned the appropriate IP address to the interface.
/ip address
add address=192.168.11.143/24 comment=WAN-2 interface=ether2 network=192.168.11.0
Next, I configured a GRE tunnel with IPsec encryption to the remote VPS. IPsec was enabled to protect the traffic carried through the GRE tunnel.
/interface gre
add allow-fast-path=no comment=VPS ipsec-secret=1234 name="GRE Tunnel" remote-address=192.168.88.1
I also assigned an IP address to the GRE tunnel. This address was required to establish routing between the MikroTik router and the remote endpoint.
/ip address
add address=172.16.1.2/30 comment=VPS interface="GRE Tunnel" network=172.16.1.0
The resulting interface and IP address configuration is shown below:
I first imported the required destination IP address lists into the MikroTik firewall Address List. To do this, I uploaded the prepared .rsc files to the router and imported them using the commands below:
import Google-Meet-IPs.rsc
import IranIP-CIDR.rsc
After importing the address lists, I used firewall mangle rules to classify packets for policy-based routing. The first rule marked packets destined for Google Meet and other selected calling or meeting services:
/ip firewall mangle
add action=mark-routing chain=prerouting comment="Route Meet" dst-address=!192.168.0.0/16 dst-address-list=Meet new-routing-mark=VoIP passthrough=no
I then created another mangle rule for traffic that was not destined for Iranian IP addresses. Using the NOT condition allowed me to identify non-Iranian destinations and mark those packets for the GRE/IPsec tunnel, while Iranian destinations remained on the primary WAN.
/ip firewall mangle
add action=mark-routing chain=prerouting comment="Route ! Iran" dst-address=!192.168.0.0/16 dst-address-list=!Iran new-routing-mark=Tunnel passthrough=no
At this point, the router was able to classify traffic based on its destination and attach routing marks to the matching packets. These marks were then used by the routing table to select the appropriate next hop.
I first configured the default route through WAN-1. This provided the normal Internet path for traffic that did not require a different routing policy, including Iranian destinations.
/ip route
add comment="WAN-1 - Iran" distance=1 gateway=192.168.88.1 target-scope=30
I then added a policy route for packets marked as Google Meet and VoIP traffic. This route forwarded the marked traffic through WAN-2:
/ip route
add comment="WAN-2 - VoIP" distance=1 gateway=192.168.11.2 routing-mark=VoIP target-scope=30
Finally, I added a policy route for packets marked as non-Iranian traffic. This route forwarded those packets through the GRE/IPsec tunnel to the remote VPS.
/ip route
add comment="Tunnel - ! Iran" distance=1 gateway=172.16.1.1 routing-mark=Tunnel
For the tunnel route, I used the next-hop IP address rather than selecting the GRE interface directly as the route's interface. In RouterOS, using a point-to-point tunnel interface directly in certain routing configurations can result in unreliable or unexpected route resolution. Specifying the reachable next-hop IP gives RouterOS an explicit destination for resolving the route and makes the routing behavior more predictable.
The final configurations for this section shown below:
After completing the configuration, I tested the routing behavior using MikroTik RouterOS built-in tools and then verified the results from devices on the local network.
The tests were designed to confirm that each traffic category was using the intended path:
Iranian destinations → ether1
Non-Iranian destinations → GRE/IPsec tunnel
Google Meet and VoIP destinations → ether2
Before testing from the router itself, I temporarily changed the mangle rules. The original mangle rules used the prerouting chain, which processes packets arriving at the router from connected clients. However, packets generated by the router itself, such as those created by the Ping tool, are processed through the output chain instead.
Therefore, I temporarily changed both mangle rules from prerouting to output. This allowed traffic generated by the router's own testing tools to be evaluated by the same routing policies.
/ip firewall mangle
add action=mark-routing chain=output comment="Route Meet" dst-address=!192.168.0.0/16 dst-address-list=Meet new-routing-mark=VoIP passthrough=no
add action=mark-routing chain=output comment="Route ! Iran" dst-address=!192.168.0.0/16 dst-address-list=!Iran new-routing-mark=Tunnel passthrough=no
I also temporarily disabled the physical interfaces connected to the local network. This ensured that the traffic used during the tests was generated by the router itself and did not include traffic from local clients.
Finally, I reset the interface traffic counters and firewall mangle counters before each test. This made it easier to identify which interface handled the test traffic and whether the corresponding mangle rule matched the packets.
To show the results, I use WinBox as it provides an overall overview of the process. In this test, I used the Ping tool available through WinBox. The test results are therefore shown using screenshots.
Test 1: Iranian IP Address
For the first test, I selected an IP address belonging to an Iranian network. Instead of choosing an address directly from the imported address list, I used git.ir as a practical example of an Iranian website and entered its IP address into the WinBox Ping tool.
Then I increased the packet size from 50 bytes to 500 bytes. This made the traffic counters easier to observe and helped distinguish the test traffic from very small control packets.
When testing public websites, I kept the number of packets limited to 30. Sending unnecessary traffic to a production website is not a good testing practice, especially when the site is not intended for testing or load generation.
Before starting the test, I reset the mangle counters.
I then started the ping test and observed traffic being transmitted through ether1, as expected. The interface traffic counters also increased accordingly.
The mangle rule counters remained at zero, which was also expected because the destination IP did not match the non-Iranian traffic rule.
Test 2: Non-Iranian IP Address
For the second test, I reset the mangle counters and used an IP address associated with x.com.
This time, the traffic was routed through the GRE tunnel as expected. The GRE interface counters increased, and the corresponding mangle rule also showed packet matches.
This confirmed that the destination was identified as non-Iranian and that the routing mark was successfully directing the traffic through the tunnel.
Test 3: Google Meet and VoIP
For the final test, I repeated the same process using an IP address associated with Google Meet and another IP address used for VoIP testing.
The interface counters showed that the traffic was routed through ether2, as intended. The results confirmed that the specific service traffic was being identified by the mangle rules and forwarded through the lower-latency second ISP.
I also tested the configuration using Traceroute. However, interpreting traceroute results can be misleading if the expected next-hop addresses are not known. I compared the first three hops and confirmed that the traffic was taking different paths according to the routing policy. Moreover, intermediate routers may not respond to ICMP or UDP probes. As a result, missing hops do not necessarily indicate a routing failure. Interface counters, firewall mangle counters, and controlled ping tests provided more reliable evidence for verifying the routing behavior.
I configured the MikroTik router to route traffic through different physical and logical interfaces based on the destination IP address.
Iranian destinations continued to use the primary WAN, while non-Iranian destinations were routed through the GRE/IPsec tunnel. Google Meet and selected VoIP traffic was routed through the second ISP, which provided lower latency, higher uptime, and dedicated bandwidth.
This separation reduced unnecessary traffic through the tunnel and prevented latency-sensitive services from competing with general Internet traffic on the primary connection. It also allowed services that required a local Iranian source IP to continue using the primary WAN instead of being sent through the remote VPS.
The final routing design allowed users to access different services and use calling and meeting applications without manually changing network connections. Traffic was automatically sent through the most appropriate network path based on its destination and routing policy.
All configurations and resources used in this project, including the fully configured and tested RouterOS environment exported in OVA format, are available on my GitHub for reference.
[Link to this project on GitHub]
I also documented how I collect and maintain the Iranian IP address list in detail on my blog: Iran IPs.