I wanted to achieve the ability to use Mullvad as my go-to VPN service while also accessing my home services, like PiHole and Audiobookshelf, when I'm on the go. In this post, I'll walk you through the setup, as it requires some special settings to get the routing right.
I'm far away from being a network professional and iptables is breaking my brain sometimes as i'm still learning. To get this done I was searching through a lot of reddit posts, and other websites and getting help of some LLMs: reading and trying the settings and rules. It was very complicated first (for me), but I'd like to show y'all exactly my setup.
My Server
- a VM running Debian bookworm
- a WireGuard server is installed on that VM, which is accessible from the internet to connect to my home network via PiVPN.
- Pi-hole is running on the same machine and is used for DNS (via dnscrypt-proxy)
- a working WireGuard profile on my phone which uses Pi-hole for DNS
- different services on other VMs like AudioBookShelf
What I want to add
- a new WireGuard connection to mullvad which is used for Internet things, while still having access to my local services.
Let's start
Okay, so as we already have WireGuard installed on the VM (it acts as a server and a client if you want to) we first need to create a WireGuard config file for Mullvad. To do this you can just use the online config creator of Mullvad:
- Login to Mullvad with your user ID
- check into the Downloads Section and select WireGuard Configuration
- select Linux as your platform and generate a new key
- now select all the options you want, such as the desired endpoint and other preferred settings, and download the generated .conf file
Once the conf file is downloaded, I rename it to mullvad.conf and transfer it to my VM into /etc/wireguard/ (as root, via SFTP or any other method, or by copy-pasting it's content via SSH). I rename it to mullvad.conf because that will be the name of the network adapter, and we’ll need that name for our configuration edits.
Inside /etc/wireguard there is (in my case) also the wg0.conf which is the configuration of the WireGuard server to my home-network. We start editing here.
Edit your Home-VPN's config
Let's start and begin to edit my Home-VPN's config which is (in my case) wg0.conf (as root)
nano /etc/wireguard/wg0.conf
to something like this:
[Interface]
PrivateKey = XXXXXXXXXXXXXX
Address = 10.10.10.1/24
MTU = 1420
ListenPort = yourVPNPort
FwMark = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT;
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT;
PostUp = iptables -t nat -A POSTROUTING -o mullvad -j MASQUERADE;
PostUp = ip6tables -t nat -A POSTROUTING -o mullvad -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT;
PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT;
PostDown = iptables -t nat -D POSTROUTING -o mullvad -j MASQUERADE;
PostDown = ip6tables -t nat -D POSTROUTING -o mullvad -j MASQUERADE
### my clients ###
[Peer]
PublicKey = XXXXXXXX
PresharedKey = XXXXXXXX
AllowedIPs = 10.10.10.2/32
FwMark = 51820
FwMark is used to mark the data-packets in order to route them later to mullvad.
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT;
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT;
PostUp = iptables -t nat -A POSTROUTING -o mullvad -j MASQUERADE;
PostUp = ip6tables -t nat -A POSTROUTING -o mullvad -j MASQUERADE
These are the firewall rules needed to forward the traffic from wg0 to mullvad and masquerade the sources IP address with Mullvad's.
Now Mullvad's .conf file
Let's edit mullvad.conf as well to something like this:
[Interface]
# Device: DeviceName
PrivateKey = XXXXXXXXXX
Address = SomeMullvadIP
DNS = SomeMullvadIP
FwMark = 51820
PostUp = ip rule add from 10.5.5.4 table main;
PostUp = iptables -t mangle -A PREROUTING -i eth0 -j CONNMARK --set-mark 51820;
PostUp = iptables -t mangle -A PREROUTING -m connmark --mark 51820 -j MARK --set-mark 51820
PreDown = ip rule del from 10.5.5.4 table main;
PreDown = iptables -t mangle -D PREROUTING -i eth0 -j CONNMARK --set-mark 51820;
PreDown = iptables -t mangle -D PREROUTING -m connmark --mark 51820 -j MARK --set-mark 51820
[Peer]
PublicKey = XXXXXXXXXXX
AllowedIPs = 0.0.0.0/0,::0/0
Endpoint = SomeMullvadIP:Port
By marking and tagging traffic (using the 51280
mark), we're controlling how specific types of traffic are handled. For example, in our VPN setup, certain types of traffic might need to be sent through Mullvad, while other traffic goes through your regular network adapter. These lines are enabling local communication via UDP and TCP.
10.5.5.4
is the local IP address of my VM, so you need to change it to your machine's IP.
The FwMark
value needs to be the same as we have used in the other config.
eth0
is my default network adapter which uses my LAN IP address, change its name to yours if it differs.
Test it
Now I restart the WireGuard-server and bring up the mullvad connection:
wg-quick up mullvad
and connect to my Home-VPN with my phone.
If everything works like on my end, you should be able to communicate with your local services, and when you check your IP (browserleaks for example) you should see the IP of the mullvad endpoint you picked before on your device.
Comments