diff --git a/README.md b/README.md index 909012e..6f51520 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,112 @@ -# wpimocall +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). -Whatsapp and IMO Voice Call \ No newline at end of file +This is achievable on MikroTik using a combination of **DNS hijacking**, **dynamic address lists**, and **policy-based routing**. + +The core idea is: +1. **Catch DNS requests** for key domains (`whatsapp.net`, `imo.im`, etc.). +2. **Resolve those domains** and **dynamically add** the resulting IP addresses to an address list. +3. **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-out1` in 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. + +```bash +/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): +```bash +/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`: + +```bash +: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. +```bash +/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. +```bash +/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. +```bash +/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_route` mark. +* **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:** +```bash +/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:** +```bash +/ip firewall connection print where connection-mark=vpn_conn +``` + +**3. Check the routes:** +```bash +/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=ping` parameter 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. \ No newline at end of file