Mullvad WireGuard with RouterOS 7
Introduction
After getting a GL iNet travel router and Mikrotik releasing RouterOS 7 I thought it's time to look at a 24/7 VPN connection again. When looking through the VPN services GL iNet suggests, I stuck with Mullvad. So in this post I will explain how I setup my Mikrotik CHR to use Mullvad VPN with WireGuard, implement a kill-switch and use the Mullvad DNS. If you are using RouterOS 7.2 or later read my other post first!
1) Interface Configuration
First, we need a WireGuard interface. In the RouterOS terminal enter
/interface/WireGuard/add name=mullvad
Then open the WireGuard-config generator. There we need to either 1.1) Upload our key, or 1.2) Mullvad generates a key for us.
1.1) Upload our key
In the RouterOS terminal enter
[admin@mikrotik] > /interface/WireGuard/print detail 0 R name="mullvad" mtu=1420 listen-port=38044 private-key="gF+iGVw1T/njKC2+AE8kZeQ/3/0gNAe6YumPQwMFhXY=" public-key="Pvxe8aXKmdLIzd5u7u62PDSoQezy6XtIzteCD5w06Xw="
from the output copy the private-key= value for the mullvad interface. In this example it would be gF+iGVw1T/njKC2+AE8kZeQ/3/0gNAe6YumPQwMFhXY= In the WireGuard-config generator extend the Manage keys section and past the private key into the bottom field, then click Import key. When it is correctly pasted the key list should show the interface's public key. Lastly, chose a country, city and server from the three drop down fields in section 3. Platform and DNS Server (section 1 and 4) don't matter to us right now so we leave them as default, when done hit Download file at the bottom. Open the config file in a text editor and jump to 1.3) WireGuard peer setup.
1.2) Mullvad generates a key
In the WireGuard-config generator click on generate key, then chose a country, city and server from the three drop down fields in section 3. Platform and DNS Server (section 1 and 4) don't matter to us right now so we leave them as default, when done hit Download file at the bottom. We need to now set the private key of the router to the one generated by Mullvad. To do so we open the config file in a text editor and copy the value of PrivateKey = * under the *[Interface] section. In the RouterOS terminal then execute the command
/interface/wireguard/set mullvad private-key="<private key>"
where <private key> is the private key Mullvad generated. To verify, we can use the command
[admin@mikrotik] > /interface/wireguard/print detail 0 R name="mullvad" mtu=1420 listen-port=35044 private-key="gCsS9ao/s1i0+1vsB3qYGagDZlhL0TQPdL4b/yyvJWc=" public-key="1Aebyd1hmTveMDpBsc9dUg0brOke/dQTrztou/0e5Dw="
The public key shown by the print command should match the public key in the key list of the WireGuard-config generator.
1.3) WireGuard peer setup
With the interface all set we are ready to add the WireGuard peer, in this example we will be using WireGuard server de8. All infos we need for this are in the config file we downloaded earlier. At the time of writing this guide the command would look like this
/interface/wireguard/peers/add interface=mullvad public-key="XIge3HgGEHf52e4Jpzk8iFOrrp6q7trq0udhufFlDVo=" \ endpoint-address=185.209.196.67 endpoint-port=51820 allowed-address=0.0.0.0/0,::/0
- interface
-
is the interface name we chose earlier
- public-key
-
is the public key of the mullvad server
- endpoint-address
-
is the external IP of the mullvad server
- endpoint-port
-
is the port WireGuard is running on, on the mullvad server
- allowed-address
-
are all networks reachable through the WireGuard peer, we want to use the peer as for everything here
Please double check, that the parameters are still the same when you follow this guide.
2) IP and Routing
Next, we will set up the IPv4 and IPv6 addresses, then add a new routing table and add the default route. We will again take most infos we need from the config file we got earlier. Under the [Interface] section we find the Address parameter. The IPv4 address we can use as is, the IPv6 address we have to change the subnet to /64. What we are missing to make this work with Mikrotik is the internal gateway IP of mullvad. Sadly this is not documented by Mullvad as of right now so I did some testing and sniffing. The IPv4 gateway is the SOCKS5 proxy address as listed in the server list, for de8 this would be de8-wg.socks5.mullvad.net which, right now, resolves to 10.124.1.24. The IPv6 gateway is the IPv6 address we got in the config but ends on ::1. I will be using the IP addresses I got, please substitute with your own.
/ip/address/add interface=mullvad address=10.67.150.151/32 network=10.124.1.24 /ipv6/address/add interface=mullvad address=fc00:bbbb:bbbb:bb01::4:9696/64 /routing/table/add name=mullvad fib /ip/route/add gateway=10.124.1.24 dst-address=0.0.0.0/0 routing-table=mullvad /ipv6/route/add gateway=fc00:bbbb:bbbb:bb01::1%mullvad dst-address=::/0 routing-table=mullvad /routing/rule/add action=lookup-only-in-table table=mullvad routing-mark=mullvad
Make sure to replace address with the address you got in your config file, also don't forget to change the subnet from /128 to /64 on the IPv6 address. Furthermore you need to replace network and gateway with your server IP/IPv6.
3) Firewall Rules
Now that our routes are set we need to actually use them. To do so we need mangle rules that mark the traffic we want to send through the VPN. We will also need NAT rules, otherwise we wount get an answer back. And for safty we will add firewall rules to block incoming traffic.
Note: This is not the most resource efficient way of doing it but I couldn't get anything else to work.
/ip/firewall/nat/add action=masquerade out-interface=mullvad chain=srcnat /ip/firewall/filter/add action=drop chain=input in-interface=mullvad /ip/firewall/filter/add action=drop chain=forward in-interface=mullvad connection-state=new connection-nat-state=!dstnat /ipv6/firewall/nat/add action=masquerade chain=srcnat out-interface=mullvad /ipv6/firewall/filter/add action=drop chain=input in-interface=mullvad /ipv6/firewall/filter/add action=drop chain=forward in-interface=mullvad connection-state=new /ip/firewall/mangle/add chain=prerouting in-interface=ether2 action=mark-routing \ new-routing-mark=mullvad connection-nat-state=!dstnat passthrough=no /ipv6/firewall/mangle/add chain=prerouting in-interface=ether2 action=mark-routing \ new-routing-mark=mullvad passthrough=no
I am assuming here, that the LAN interface is ether2. If you use a different interface make sure to change the in-interface parameter for the mangle rules (last two lines above). If you have multiple LAN interfaces you can either make a rule for every interface or work with a interface list. To my knowladge these mangle rules only work without fast-track!
With these rules in place traffic should already be routed through the mullvad interface. To verify that we can simply use the connection check. At least Using Mullvad VPN should be green, if you have WebRTC leaks check the WebRTC guide Mullvad provides.
4) DNS
Lastly we will work on the DNS leak which we have left. First we need to make sure that our browser doesnt use DoH or DoT, otherwise all DNS settings we set on the router will be ignored by the browser. Mullvad provides an excelent guide on how to disable this setting in their prevent DNS leaks article.
With that set we can turn our attention to the mikrotik settings. Mullvad provides quite a few DNS servers with different blocking lists, below I've put the IPs I found in the Mullvad help pages into a table.
IP Address |
Feature |
---|---|
194.242.2.2 |
without anything (public) |
100.64.0.1 |
Ad blocking only |
100.64.0.2 |
Trackers only |
100.64.0.3 |
Ad blocking, trackers, no malware blocking |
100.64.0.4 |
Malware blocking only |
100.64.0.5 |
Ad blocking, malware blocking, no tracker blocking |
100.64.0.6 |
Tracker, malware blocking, no ad blocking |
100.64.0.7 |
Ad blocking, tracker and malware blocking (“everything”) |
So first we need to chose a server to use, for my setup I picked the "everything" server but the setup is the same for all of them. Just make sure to replace the servers and dst-address parameter in the commands below appropriately. What we need to do is set the DNS server in the Mikrotik config and create a mangle rule to route the requests through the VPN. All servers except the first wount answer otherwise.
/ip/dns/set servers=100.64.0.7 allow-remote-requests=yes use-doh-server="" /ip/firewall/mangle/add chain=output dst-address=100.64.0.7 action=mark-routing new-routing-mark=mullvad passthrough=no
Having done all the steps now we should get 4 green checks on the connection check.
5) Port forwarding (optional)
Mullvad lets you generate a random port number we can use for incoming connections using the VPN public IP. This step is optional and only works if you did not setup a subscription with Mullvad. To generate a port go to Manage ports and WireGuard keys in your account. Select the city you are connected to and the public key the Mikrotik is using. Mullvad will give you a random port number prefixed by the country and city code, e.g. de-fra-55555 which would be port 55555.
To use this port in our network we simply create a netmap rule. For example, if we got port 55555 from Mullvad and want to NAT to an internal webserver with IP 192.168.88.2 on port 80 we would use the following command.
/ip/firewall/nat/add action=netmap chain=dstnat protocol=tcp dst-port=55555 \ in-interface=mullvad to-addresses=192.168.88.2 to-ports=80
I found that the port forwarding takes a bit to take effect on Mullvads side, so if the NAT doesn't instantly work just wait a bit.
"WireGuard" is a registered trademark of Jason A. Donenfeld.