Additional information and inspiration:
schnerring.net (https://schnerring.net/blog/opnsense-baseline-guide-with-vpn-guest-and-vlan-support/)
OPNsense Docs (https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html)
0. About
Consolidated the available information for us who get cross eyed by walls of text. Don't expect to learn why it's working here.
The bare minimum needed to get it up and running on a "clean" OPNsense.
Hopefully, it can be of help to someone and lets hope I never have to do BBcode formatting ever again 🤦
1. Install WireGuard
NOTE: Not required on newer versions
Navigate to: System > Firmware > Plugin
- Install WireGuard
2. Download Mullvad config - I'll call it .conf
1. Login mullvad.net & go to wireguard-config
2. Generate Key
3. Scroll down and select server
4. Select IPv4
5. Select Only IPv4
6. Configure Content Blocking
- Irrelevant here, changes the DNS server provided in .conf
7. Download .conf
Additional Mullvad info
These can be used as monitoring IP for gateway(s):
- Mullvad - How to set up ad-blocking in our app (https://mullvad.net/it/blog/2021/5/27/how-set-ad-blocking-our-app)
- 100.64.0.1 for Ad-blocking
- 100.64.0.2 for Tracker-blocking
- 100.64.0.3 for Ad- + Tracker-blocking.
- Mullvad - Adding another layer: malware DNS blocking (https://mullvad.net/en/blog/2022/3/16/adding-another-layer-malware-dns-blocking)
- 100.64.0.4 Malware blocking only
- 100.64.0.5 Ad and malware blocking, no tracker blocking
- 100.64.0.6 Tracker and malware blocking, no ad blocking
- 100.64.0.7 Ad, tracker and malware blocking ("everything")
3. WireGuard Configuration
3.1 WireGuard INSTANCE - [interface] in .conf
Navigate to: VPN > WireGuard > Settings > Instances
Fields not mentioned = BLANK / Default
- ADD
| Field | Value |
| --------------- | ------------------------------ |
| Name | Instance Name |
| Pub Key | From Mullvad .conf creation* |
| Priv Key | Value of "PrivateKey" in .conf |
| Port | 51820 | * leave empty for random or specify manually
| Tunnel Address | Value of "Address" in .conf |
| Disable Routes | CHECKED |
| Gateway | Tunnel_Address (-1)** |
* mullvad-conf-pubkey.png
edit: no need, see comment https://forum.opnsense.org/index.php?msg=229060
** See note: OPnsense Docs - wireguard-selective-routing (https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html#step-2-configure-the-wireguard-instance)
- SAVE but don't apply
3.2 WireGuard PEER - [peer] in .conf
Navigate to: VPN > WireGuard > Settings > Peers
- ADD
| Field | Value |
| ------------------- | ---------------------------- |
| Name | Peer Name |
| Pub Key | Value of "PublicKey" in .conf|
| Allowed IPs | 0.0.0.0/0 |
| Endpoint Address | Value of "Endpoint" in .conf |
| Endpoint Port | 51820 |
| Instance | The one you set up earlier |
| Keepalive internal | 25 |
- SAVE
- APPLY
Navigate to: VPN > WireGuard > Settings > General
- Enable WireGuard
- Verify tunnel is UP in VPN > WireGuard > Diagnostics
4. Add an interface
Navigate to: Interfaces > Assignments > Assign
a new interface
- Expand list and select the WireGuard interface
- Device wg1
- ADD
- SAVE (above)
- Click on the new interface (above)
- Enable Interface: CHECKED
- SAVE
5. Add a gateway
Navigate to: System > Gateways > Configuration
- ADD
| Field | Value |
| ------------------------------- | -------------------------------------------------|
| Name | GW name |
| Interface | wg1 |
| Address Family | IPv4 |
| IP Address | Value of "Address"(-1) in .conf* |
| Far Gateway | CHECKED |
| Disable Gateway Monitoring | UNCHECKED |
| Monitor IP | 10.64.0.1 (An internal Mullvad DNS) |
* If .conf address is xx.xx.xx.10/32 you can use xx.xx.xx.9 - i.e. remove the subnet mask and subtract one from the last segment.
- SAVE
- APPLY
6. Firewall configuration
This configuration is as barebones as they come, modify it to your liking
Navigate to: Firewall > Aliases
- ADD
| Field | Value |
| ----------------- | ---------------------------------------------- |
| Name | [selected hosts] - any name you want |
| Type | Host(s) |
| Content | Add the IP of each device to Selectively Route |
- SAVE
- APPLY
6.1 FIRST rule: Route [selected hosts] traffic through the tunnel
Navigate to: Firewall > Rules > Floating
- ADD
| Field | Value |
| -------------------- | ------------------------------|
| Action | Pass |
| Quick | CHECKED |
| Interface | Interface(s) where your [selected hosts] live
| Direction | In |
| TCP/IP Version | IPv4 |
| Protocol | Any |
| Source | [selected hosts] |
| Destination | Any |
| Gateway | WG Gateway |
| Show Advanced Features |
| SET local tag | NO_WAN_EGRESS | * for kill switch
- SAVE
6.2 SECOND rule: Kill switch
May not be needed depending on your configuration, better safe than sorry?
- OPNsense Docs: Kill Switch (https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html#step-11-add-a-kill-switch-optional)
6.3 NAT Rule: NAT WireGuard for [selected hosts]
Navigate to: Firewall > NAT > Outbound
- Change mode to Hybrid outbound NAT rule generation
- ADD
| Field | Value |
| ------------------------| ---------------------------------------------- |
| Interface | WG interface |
| TCP/IP Version | IPv4 |
| Protocol | Any |
| Source | [selected hosts] |
| Src Port | Any |
| Destination | Any |
| Dst Port | Any |
| Translation / Target | Interface Address |
- SAVE
- APPLY to save all the firewall rules
7. Verify it's working as intended
- Add a device IP to the [selected hosts] Alias
- Use Mullvad Check (https://mullvad.net/en/check)
- All three should be green
- API, Powershell
(curl https://am.i.mullvad.net/json).Content | ConvertFrom-Json
[glow=cyan,2,300]Thanks for reading![/glow]
Please educate me where there are misstakes!
Just a awesome amazing guide!
Works like a charm!
I just got one question if you dont mind.
Following these steps i get it working so i get my traffic over Mullvad and can access my "LAN" devices ( as per my Interface i selected in 6.1 ) but i am not able to connect to any of my "IOT" devices in a different vlan.
Do you have any recommendation for this?
Cheers
Awesome guide. I was 0-3 with the OPNSENSE docs guide. Finally got my selective routing going with your guide thought, thank you very much.
Greetings,
Any additional steps I need to take when using a vlan tag (interface) as the gateway since my ISP uses that for internet traffic over the fiber connection. When I add the mullvad gateway it stays red with 100% loss even after selecting it as the upstream gateway.
Thank you
Update:
When I use the same ip in the monitor ip section as the ip adress things light up green but the mullvad check does not pass. Tried different dns ip's to no avail.
If I understood properly, there is no need of rules within the actual Wireguard/VPN interface, but only in the interface where the hosts live, is that correct?
Tia.
Can I ask why your routing rule is different than the one in the OPNsense docs? They have a floating rule, direction out.
Quote from: OCT0PUSCRIME on October 23, 2024, 08:50:23 PM
Can I ask why your routing rule is different than the one in the OPNsense docs? They have a floating rule, direction out.
This guide is using the "Step 8 - Create a Firewall rule" rule: https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html#step-8-create-a-firewall-rule (https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html#step-8-create-a-firewall-rule)
I don't have my opnsense active at the moment. You'll be able to confirm whether it's working or not with the last step. You can easily add the rules from the wiki and see if it behaves differently after you've confirmed that selected routing is working.
Didn't manage to find any problems with this despite not using all the rules. All traffic I tested hopped the correct routes and was blocked where I wanted. Possibly something I missed that the other rules fixed. Going to need someone smarter than me to confirm.
Quote from: hushcoden on October 14, 2024, 02:35:08 PM
If I understood properly, there is no need of rules within the actual Wireguard/VPN interface, but only in the interface where the hosts live, is that correct?
Tia.
The NAT and Floating rule should cover that.
Quote from: pete.magnusson on July 27, 2024, 06:33:51 PMJust a awesome amazing guide!
Works like a charm!
I just got one question if you dont mind.
Following these steps i get it working so i get my traffic over Mullvad and can access my "LAN" devices ( as per my Interface i selected in 6.1 ) but i am not able to connect to any of my "IOT" devices in a different vlan.
Do you have any recommendation for this?
Cheers
Hi Pete,
I had the exact same challenge as you. Here's how I solved it:
- Create an alias for your VLANs under Firewall --> Aliases. In my case I named it "PrivateNetworks" and assigned the content of "192.168.0.0/16" because my different VLANs resolve into subnets within 192.168.10.0/24, 192.168.20.0/24, etc. (this is just my case, yours might be different)
- Adjust the "Destination" in step 6.1: Select the checkbox "Destination / Invert" and select your previously created alias "PrivateNetworks" as "Destination". --> Save & Apply
This will result in only allowing traffic to the new (mullvad/wireguard) gateway if the destination address is not within a private range, in my case within 192.168.0.0/16
In other words internet traffic will use the new mullvad/wireguard gateway, whereas internal networks will continue to be routed internally.
Hope this helps. If it doesn't feel free to ask again.
Cheers,
Ed
Big thank you first!
Now a question: what is the best practice in case of multiple (Mullvad) WiregGuard instances?
When doing step 5 with a second instance:
| IP Address | .conf > [interface] > address (-1)* |
| Monitor IP | 10.64.0.1 or one of the DNS servers |
I get errors
> This Gateway IP address already exists.
> This Monitor IP address already exists.
For GW IP, we probably can just decrement one more: address (-2), ... , address (-n).
But what should I configure for "Monitor IP", given DNS IP is always the same?
Quote from: cami09 on January 13, 2025, 08:31:46 AMBig thank you first!
Now a question: what is the best practice in case of multiple (Mullvad) WiregGuard instances?
There are more than one DNS server you can use. Check out the first link in the original post, I believe he went thru the steps to make more than one tunnel 🤞😎
So I'm not using Mullvad but I followed these instructions changing the main vpn connection to use wireguard settings of my provider and the tunnel seems fine. However, I'm receiving an error on any website I try to visit telling me its not secure, click advance continue and it gives an opnsense rebind dns attack error page. Any suggestions on what it is causing this?
I should add, when I do a ping test to like 8.8.8.8 it says I'm getting a reply from my opnsense IP address of 192.168.1.1 , so clearly something isn't right there but I don't know what.
This tutorial is 100% spot on and works as advertised, love it!
Did you ever try this with IPv6? I would like to use Destination routing instead of based on source.
It works well for IPv4 but nowadays a ton of sites do have AAAA records too.
I've tried adding the IP address that you get in the .conf to the Interface/Peer but I run into the unknown with the gateways.
You can only add one gateway to an instance .. which makes this hard. Should I make an IPv6 only instance?
The Wireguard instance does not need the Listen Port to use 51820.
If you leave it blank it will use a random source port number.
Also, the Wireguard instance does not need a public key, only the private key.
I just wanted to drop by and give you the utmost of praises. This was friggin phenomenal guide and got me up and running!!! Thank you so much for this guide!!!
Do you know if there's a way to keep this working while simultaneously running a home VPN for my own devices? I had a road warrior wireguard setup for my devices, but every configuration for Mullvad seems incompatible with it. I'm not entirely sure why, but I think it's because the outbound NAT rule for the road warrior setup interferes with the outbound NAT rule for the Mullvad setup. I'm not entirely sure how to work around this though.
Quote from: Arby on March 13, 2025, 01:36:31 AMDo you know if there's a way to keep this working while simultaneously running a home VPN for my own devices? I had a road warrior wireguard setup for my devices, but every configuration for Mullvad seems incompatible with it. I'm not entirely sure why, but I think it's because the outbound NAT rule for the road warrior setup interferes with the outbound NAT rule for the Mullvad setup. I'm not entirely sure how to work around this though.
I am running this and my own roadwarrior setup side by side.
Not sure how the NAT rules could collide TBH. They won't be running on the same source interfaces.
The NAT rule for road warrior setup to access other internal networks doesn't seem to be needed if you assigned it an interface. My rule below is disabled for WGHOME and I can still access my internal resources.
Interface Source Source Port Destination Destination Port NAT Address NAT Port Static Port Description
WAN WGHOME net udp/ * * udp/ * Interface address * NO NAT wgHome Internal
WGSTO1 selectiveRoute * * * Interface address * NO NAT wgSTO-1 SelectiveRoute
Perhaps I had some firewall rules misconfigured then. I was able to get the Mullvad connection working perfectly when I followed your guide, but only after I disabled everything for my road warrior setup. I'm going to try again today with a fresh OPNsense build (I opted to do a factory reset after I ended up breaking some things), and I'll try and be a little bit more well-informed about what each step is doing along the way. The road warrior setup that I did was pretty much identical with the OPNsense documentation; I'm not entirely sure yet if there's anything I'd need to change for it.
Hmm, okay, this is interesting. This time, I encountered the opposite issue. After setting up a home wireguard system, I successfully got Mullvad working simultaneously with my road warrior setup (wg0). But devices in the Mullvad alias made in step 6 of this guide become unable to communicate with one another. This is in spite of the fact that I'm using wg0 as interface for this alias. So the devices are definitely still part of my home VPN (and a quick look at the WireGuard status page confirms this), but I can't, e.g., SSH into my NAS from my main PC, unless it's over LAN.
I think I understand why this is happening, at least. I think the floating rule in place directs ALL traffic sourced from my Mullvad alias through the Mullvad gateway, which means that if I ping 10.0.0.3, that ping is first going to bounce over to Mullvad's server, and then from there, bounce to local IP 10.0.0.3 -- which is a nonsense IP at that point, so there's no response. So now the question is how to exclude wg0 traffic from the Mullvad gateway. I tried changing the "Destination" on the floating rule to "WAN net" and/or "WAN address", but doing this seems to disable Mullvad connectivity for either case.
Eureka! I figured it out.
Here's what I did: I created a new Floating rule:
Interface | The one used to make the alias in step 6 |
Source | The alias in step 6 |
Destination | wg0 net |
Gateway | default |
Description | (if you want one) |
Then after hitting "Save," I clicked the check mark on the left next to this new rule, and then clicked on the left arrow on the right of the Mullvad floating rule (the one that says "Move selected rules before this rule" when you hover over it).
This rule captures packets running over wg0. Since packets only ever get handled by one firewall rule [citation needed], the Mullvad Gateway rule gets bypassed.