5.7 KiB
Of course. This is a more advanced and interesting use case. You want to dynamically identify traffic going to WhatsApp and IMO and then force only that traffic through a VPN tunnel (likely for policy or security reasons).
This is achievable on MikroTik using a combination of DNS hijacking, dynamic address lists, and policy-based routing.
The core idea is:
- Catch DNS requests for key domains (
whatsapp.net,imo.im, etc.). - Resolve those domains and dynamically add the resulting IP addresses to an address list.
- Create a routing rule that sends any traffic destined for IPs in that address list through your VPN interface.
This method is far superior to a static IP list because it automatically updates itself.
Step-by-Step Configuration Guide
Prerequisites:
- A working VPN connection (PPTP, L2TP, SSTP, or OpenVPN) set up on your MikroTik. Its interface is named
vpn-out1in this example. - Your main gateway (e.g., for direct internet traffic) has a route with a distance of
1.
Step 1: Create the Dynamic Address List
We'll create a list to hold the IPs of the blocked services.
/ip firewall address-list
add list=vpn-services address=31.13.64.0/18 comment="Meta WhatsApp Range - EXAMPLE" disabled=no
add list=vpn-services address=157.240.0.0/16 comment="Meta WhatsApp Range - EXAMPLE" disabled=no
# We start with some known ranges but the script will populate it dynamically.
Step 2: Hijack DNS Requests to Identify Domains
We use the MikroTik as the DNS server for the network and use a script to catch requests for specific domains.
2.1. Set up the router as the DNS server for your DHCP clients (if it isn't already):
/ip dhcp-server network
set [ find ] dns-server=192.168.88.1 # Replace with your router's LAN IP
2.2. Create a script to resolve domains and add them to the list:
Go to System > Scripts and create a new script called resolve-vpn-domains:
:local domain [/ip dns cache all find where name ~ "whatsapp" or name ~ "imo\.im" or name ~ "wa\.me" and type="A" and expired=false]
:foreach i in=$domain do={
:local resolvedAddress [/ip dns cache all get $i address]
:local resolvedName [/ip dns cache all get $i name]
:if ([:len $resolvedAddress] > 0) do={
/ip firewall address-list add list=vpn-services address=$resolvedAddress comment="$resolvedName" timeout=3h
}
}
This script runs every 3 hours, finds non-expired DNS cache entries for key domains, and adds their IPs to the vpn-services list with a 3-hour timeout.
2.3. Schedule the script to run periodically: Go to System > Scheduler and add a new task:
- Name:
update-vpn-ips - Interval:
03:00:00(every 3 hours) - On Event:
resolve-vpn-domains
Step 3: Create the Policy-Based Routing Rule
This is the most important step. It tells the router what to do with the traffic going to the IPs in our dynamic list.
3.1. First, mark the connection when a packet is destined for an IP in our vpn-services list. This mark will follow the entire connection.
/ip firewall mangle
add chain=prerouting action=mark-connection new-connection-mark=vpn_conn passthrough=yes dst-address-list=vpn-services comment="Mark Connections for VPN Services"
3.2. Then, mark the routing for all packets that are part of that marked connection.
/ip firewall mangle
add chain=prerouting action=mark-routing new-routing-mark=vpn_route passthrough=yes connection-mark=vpn_conn comment="Mark Routing for VPN Route"
3.3. Finally, create a route that uses the VPN interface for traffic with the vpn_route mark.
/ip route
add dst-address=0.0.0.0/0 gateway=vpn-out1 routing-mark=vpn_route check-gateway=ping comment="Route VPN-marked traffic through VPN"
- dst-address=0.0.0.0/0: This is the default route, but it only applies to packets with the
vpn_routemark. - gateway=vpn-out1: The name of your VPN interface.
- check-gateway=ping: This is crucial. It will disable this route if the VPN gateway becomes unreachable, preventing a black hole.
Step 4: Verification and Monitoring
1. Check your dynamic address list to see if it's populating:
/ip firewall address-list print where list=vpn-services
You should see entries with comments showing the domain name and a timeout counting down.
2. Check your connections to see the marking and routing in action:
/ip firewall connection print where connection-mark=vpn_conn
3. Check the routes:
/ip route print
You should see your main route (distance=1, main table) and the special route for vpn_route (dynamic table).
Important Considerations & Enhancements
- Kill Switch: The
check-gateway=pingparameter acts as a basic kill switch. If the VPN drops, the route is disabled, and traffic won't leak out the main WAN. For a stronger kill switch, you would need more complex firewall rules to drop all traffic not going through the VPN. - Performance: This method uses connection tracking and is very efficient on modern MikroTik hardware (hAP ac², RB4011, etc.).
- Completeness: This method is very good but not 100% perfect. Some services, especially IMO, might use hard-coded IPs or other Google domains that are harder to catch. The L7 method from the previous answer is more accurate for identification but is more CPU-intensive and can't be used for routing decisions as easily.
- Multiple VPNs: You can create different address lists and routing marks for different services to send them through different VPN tunnels.
This solution provides a powerful, dynamic, and maintainable way to achieve your goal of selectively routing specific application traffic through a VPN.