WireGuard is a modern designed VPN that uses the latest cryptography for stronger security, is very lightweight, and is relatively easy to set up (mostly). I say ‘mostly’ because I found setting up WireGuard in OPNsense to be more difficult than I anticipated. The basic setup of the WireGuard VPN itself was as easy as the authors claim on their website, but I came across a few gotcha's. The gotcha's occur with functionality that is beyond the scope of the WireGuard protocol so I cannot fault them for that. My greatest struggle was configuring WireGuard to function similarly to my OpenVPN server. I want the ability to connect remotely to my home network from my iPhone or iPad, tunnel all traffic through the VPN, have access to certain devices and services on my network, and have the VPN devices use my home's Internet connection.
WireGuard behaves more like a SSH server than a typical VPN server. With WireGuard, devices which have shared their cryptographic keys with each other are able to connect via an encrypted tunnel (like a SSH server configured to use keys instead of passwords). The devices that are connecting to one another are referred to as “peer” devices. When the peer device is an OPNsense router with WireGuard installed, for instance, it can be configured to allow access to various resources on your network. It becomes a tunnel into your network similar to OpenVPN (with the appropriate firewall rules enabled). I will refer to the WireGuard installation on OPNsense as the server rather than a “peer” to make it more clear which device I am configuring unless I am describing the user interface because that is the terminology used interchangeably by WireGuard.
The documentation I found on WireGuard in OPNsense is straightforward and relatively easy to understand, but I had to wrestle with it for a little while to gain a better understanding on how it should be configured. I believe it was partially due to differing end goals – I was trying to achieve something a little different than the authors of other wiki/blog/forum posts. Piecing together various sources of information, I finally ended up with a configuration that met the goals stated above.
Install the WireGuard VPN Plugin
The first thing that needs to be done is to install the WireGuard plugin in OPNsense because it is not a VPN provider that is natively installed in OPNsense. Go to the “System > Firmware > Plugins” page. Scroll down to the “os-wireguard” plugin and click the install button.
Configure the WireGuard VPN Server
First thing that needs to be configured is the WireGuard VPN Server. Go to the “VPN > WireGuard” page and click the “Local” tab:
Click the “+” button to add a new WireGuard server.
Click the “Enabled” checkbox. Give the server a “Name” of your choice. Leave the “Public Key” and “Private Key” blank as they will be automatically generated when you click “Save”.
The default “Listen Port” is 51820. I like to change it to a non-default port when exposing the port to the world so I am using 51821 in my example. It makes it a little less likely to be found by automated scans especially if the scans are only searching for the default port of an application. Even though it may not offer a great deal of security, it would likely reduce the number of scanning/access attempts you might see in the firewall logs.
Specify the “DNS Server”(s) you wish the clients to use. Since I am using two Pi-hole DNS servers, I included their IP addresses. If you are using the Unbound DNS or some other DNS plugin/package in OPNsense, you may specify the router's IP address. I believe you may need to specify the router's IP address rather than localhost (127.0.0.1) since the WireGuard interface is a virtualized tunnel interface (but do not quote me on that…).
For the “Tunnel Address”, enter a network address such as 10.0.0.1/24. All of the peers/clients connecting to the server should have an IP address that falls in that range. Keep that in mind when you are configuring the user.
Leave the “Peers” as “Nothing selected” for now. You will need to come back to this once the user/peer has been configured. Configuring the peers on the server and exchanging public keys is probably the least user friendly part of the configuration process for WireGuard (not counting the OPNsense firewall rules since that is not strictly a part of WireGuard but rather is something required to allow the desired access to your network).
Click the “Save” button.
Overall the server configuration is very simple compared to OpenVPN. Notice you do not have to worry about setting any cryptography settings because out of the box it is using strong, modern encryption. I love that simplicity.
Configure the WireGuard User/Endpoint
Next up is the user endpoint configuration. It is even more simple than the server configuration. The page is located at “VPN > WireGuard” on the “Endpoints” tab.
Click the “Enabled” checkbox and a “Name” for the user. Leave the “Public Key” blank for now. It will be obtained later when you are setting up the client for the user.
A “Shared Secret” may be used if you want additional protection by adding a passphrase in addition to the key. The keys are strong enough that a shared key may not be necessary but if you want the strongest protection possible, you have the option to add another layer of protection.
For the “Allowed IPs” box, enter the user/client's IP address. This address is a static and is associated with the user's public key.
The “Endpoint Port” needs to be set the same as the server's “Listen Port”. I have seen an example where it was not included so I do not know if it is really necessary. Through experimentation, I have discovered that some information may technically be optional (at least on the GUI), but the VPN did not work without specifying the information.
Click the “Save” button.
Enable the WireGuard VPN Server
At this point, the WireGuard VPN server can be enabled even though the peer user is not fully set up yet. The reason it needs to be enabled is so that the WireGuard interface can be created in the next step. To enable to the WireGuard server, go to the “General” tab and click “Enable”.
Click the “Save” button.
Add the WireGuard Interface
I found this next step of creating a WireGuard interface necessary via trial and error. A blog post included this step in their instructions.
When I originally set up OpenVPN, I noticed that there was the ability to actually add an OpenVPN interface in a similar manner to adding a physical, VLAN, or LAG interface. Enabling the interface caused issues for me so I never used it – likely due to the way I incorrectly configured that interface. There is an automatic “OpenVPN” firewall group that was created and putting my firewall rules in that group did the trick for me.
The blog post may have cleared up why I may have had issues with enabling the OpenVPN interface. If you are running multiple OpenVPN (or WireGuard) servers, you can enable a new interface for each instance without setting any IP address information (because it is already defined by the VPN service) and firewall rules can be applied separately to each VPN interface. Then you can use the automatically generated firewall group “OpenVPN” for rules that may apply to all the VPN instances. Since I was only running one instance of OpenVPN, I did not have the need to create separate VPN interfaces to have different sets of firewall rules.
I am assuming this concept applies to both OpenVPN and WireGuard. However, I think due to how Wireguard is implemented differently than OpenVPN, the creation of a WireGuard interface is necessary to allow clients to use the Internet connection of the remote network. It acts as the bridge between the virtualized tunnel and the physical network.
To add the WireGuard interface, go to “Interfaces > Assignments”.
Select the “wg0” interface and click the “+” button to add the interface to the list of interfaces. Click the “Save” button to persist the change. It will show up as something like “[OPT1]” or a higher number if you already have an “[OPT1]” interface. Now click on the “[OPT1]” interface (or whatever the new interface is called).
Click the “Enable” checkbox and “Prevent interface removal” checkbox. You may enter a better name in the “Description” box. Do not enter “WireGuard” as the name because there is already a “WireGuard” firewall group created when WireGuard is enabled. I used “WG” in the example to keep it short and simple. You do not need to enter any other settings. Normally you would set up an IP address for the interface and the range of network addresses. However, that is unnecessary in this case. It has already been defined in the WireGuard server settings.
I have seen some examples that do not include creating a WireGuard interface, which may be ok if you do not need to access the remote network's Internet connection. Once I finally got everything working, I noticed that if I removed the WireGuard interface, the VPN no longer functioned properly. If you only need to access a remote network's devices without needing the remote network's Internet connection, you may be able to skip this step.
Add the WAN Firewall Rule
To allow external access to the WireGuard VPN, a WAN rule needs to be created. I saw an example that suggested using a NAT port forward rule, but since the WireGuard VPN is running on the same machine as OPNsense, a simple WAN rule is enough to allow external access. Go to the “Firewall > Rules > WAN” page.
Choose “Pass” for the “Action” and “UDP” as the “Protocol”. The “Source” should be set to “any” to allow any remote host to connect. You can restrict this if you know you are always connecting from a certain network with static IP address(es) or address range(s). The “Destination” needs to be the “WAN address”, which is your external IP address. For the “Destination port range”, select “(other)” and enter the port number you used when you created the WireGuard VPN service. In my example, I am using port 51821. If you prefer, you can add a “Description” such as “Allow remote access to the WireGuard VPN”.
Add the Outbound NAT Rule
In order to for WireGuard clients/users to use the Internet connection of the remote network (like with OpenVPN), an outbound NAT rule has to be created. Most home users will likely want this configuration because you can browse the Internet more securely than when you are using public WiFi. It is as though you are sitting at home using your home Internet connection.
If you are using the default “Automatic outbound NAT rule generation” option, you will need to set it to “Hybrid outbound NAT rule generation” or “Manual outbound NAT rule generation”. The hybrid option is likely best for most home users unless you want to take the time to configure all of the necessary outbound NAT rules (which I believe may be a very tedious task to ensure you are not blocking a lot of legitimate traffic used by various applications on your network).
Once you enable the hybrid or manual mode, you will see an “Add” button on the top right corner of the page.
Note: You should see the “WG” WireGuard interface listed in the “Automatic rules” section at the bottom of the page. If you do not see it listed, you may need to reboot your router. It is possible it will show up later when you are applying other various changes to the configuration so a reboot may not always be necessary.
Click the “Add” button to create a new outbound NAT rule.
Ensure that the “Interface” is set to “WAN”. Choose “any” for the “Protocol”. The “Source address” should be your “WireGuard net” which includes all users/clients connected to your WireGuard VPN server. The “Source port” should be set to “any”. The “Destination address” and “Destination port” should both be set to “any” to allow outgoing connections to any address. The “Translation/target” dropdown should be set to “Interface address” to indicate the WAN's interface – so route any WireGuard network traffic through the WAN interface to your desired destination.
Add Firewall Rules to Access Internal Networks/Devices
Now that the the WAN and outbound NAT rules are created which allow outgoing/incoming connections to/from the Internet, the remaining rules will govern what can be accessed internally in your network. You could create an “allow all” rule that will allow the WireGuard users/clients full access to your network, but I imagine you would want to only allow access to specific devices/services on your network.
If you have an IoT or guest network, for instance, and you want your users/clients to have similar access as those networks, you could clone your rules from those VLANs/interfaces in order to provide similar access. Since the internal network firewall rules could vary greatly depending on your specific needs, I will leave the creation of such rules to the reader. If you would like some guidance on creating OPNsense firewall rules, I have written about them, and I have also created a “cheat sheet” list providing several common firewall rule examples.
There is one firewall rule you are likely going to need if you are tunneling all of your user/client traffic through the WireGuard interface (by using 0.0.0.0/0 as the allowed IPs – see the “Configure the WireGuard iOS Client” section below). You will need a rule to allow access to your network's DNS servers even if you are using a DNS server running on your OPNsense box. I found out the hard way that the WireGuard's interface IP (in our example 10.0.0.1) does not provide DNS to the WireGuard network similar to other interfaces.
Use the following settings for the rule:
|Protocol||TCP/UDP (or just UDP)|
|Destination||Single host or Network|
|192.168.1.5 (use your DNS server address)|
|Description||Allow access to DNS server|
You will need to repeat this process for the secondary DNS server unless you create an alias which contains both IP addresses. This is what I have done so that I only need to create one DNS rule instead of two.
If you are using the OPNsense router's Unbound DNS server, you can change “Single host or Network” to “This firewall” (no IP address needs to be added since it is known by the built-in “This firewall” alias).
Copy the Server's Public Key
At this point, the WireGuard VPN server is mostly configured. The main steps after this is to exchange public keys and set up the WireGuard client. Go to the “Local” tab and click the pencil button to edit the VPN server configuration. You will notice that the public/private key have been generated. You will need to copy the server's public key and send it to all of your WireGuard client devices connecting to the server. Emailing the public key may be the easiest way or if you are using a (hopefully encrypted) file sync application, you could transfer the key via a text file. I transferred my public key via email which is using a TLS/SSL connection.
Important: Only send yourself the public key. You need to keep the private key a secret!
Since the key is a public key, you do not have to worry about keeping the key as much as a secret as the private key. It is not a bad idea if you still want to keep it secured. Keep in mind that someone also needs your private key in order to do any sort of damage with the public key. At that point the attacker can fully decrypt everything.
Configure the WireGuard iOS Client
There are a number of devices/operating systems which have WireGuard support, but I am going to use iOS as the example client – mostly because that is what I am using to access my home network remotely. You can find Android and other examples on various blogs, forums, etc. I am using the official WireGuard app on the app store.
When you open the WireGuard app, you will need to click “Create from scratch” since currently the OPNsense WireGuard plugin does not provide a QR code to scan (which would make this process a lot easier).
Once you click the button you will see the “Edit configuration” screen.
For the “Name” enter a description for the VPN connection. If you have more than one connection, a useful description becomes more important. Click “Generate keypair” to generate a public and private key. For the “Addresses”, enter the static IP address for the user. I am using 10.0.0.2/32. The “/32” is CIDR notation which in this case means you are specifying a single IPv4 address. Use the same “Listen port” that the WireGuard server is using. I am using port 51821.
If you are tunneling all traffic from the client through the WireGuard VPN, you must specify the DNS servers even though it says it is “strongly recommended”. It becomes required when tunneling all traffic through the VPN. This caused some issues for me until I realized I needed to enter the information (which is stated in the “Step 3 - Setup WireGuard Client” section of the OPNsense documentation).
Click on “Add peer” to open up a new section of configuration on the screen:
The peer device is the OPNsense router with WireGuard installed. Remember the public key you emailed yourself? Leave the app (but do not force close the app and lose your settings) and open your email client (or file sync app). Copy and paste the public key into the “Public key” box. If you chose to use a passphrase when you configured your WireGuard user on OPNsense, you can enter it in the “Preshared key” box.
For the “Endpoint”, you should ideally use a domain name for external access to your home network rather than an IP address. This can be a dynamic DNS domain name like dyn.com or your own custom domain name which have APIs available to allow clients on your network to update the IP address when it changes (see my Dynamic DNS how-to).
The “Allowed IPs” box allows you to enter IPs that should pass through the VPN. If you specify 0.0.0.0/0, that means all network traffic including DNS which is why you have to specify the DNS server in the “DNS servers” box above. This setting is useful if you want to use public WiFi hotspots. If you were not interested in using the remote network's Internet connection and only wanted internal network access, I imagine you can use this setting to access your home network but then use your current cellular (or WiFi) connection for the Internet. I have not tested that scenario since I prefer to tunnel all traffic through my home network. If you are using IPv6, you can specify ::/0 to indicate tunnel all IPv6 traffic.
Do not click “Save” yet until after the next step! It saves you a few clicks…
Copy the iOS User's Public Key
Before saving the client configuration, click on the long string of characters beside the “Public key” label. A “copy” dialog box will be displayed. Click “copy” and then email that public key to yourself. You will need that key to enter for the user configuration in OPNsense.
Click “Save” to finish setting up the iOS client.
Update the WireGuard User/Endpoint
Go back to OPNsense and go to the “VPN > WireGuard” page. Click the “Endpoints” tab. Then click the pencil icon beside the user you are setting up to edit the user/client information. Copy and paste the iOS client public key from the email (or text file) and paste it into the “Public Key” box. Then click the “Save” button.
Connect to the WireGuard VPN
Now you are finally finished with configure both the WireGuard server and the client! Go to your client device and click connect. In OPNsense, go to the “List Configuration” tab on the “VPN > WireGuard” page, and you should be able to see information about the connected user. You will see which peer (by its public key), the IP address of the connected user, how long ago the last connection occurred, and the amount of data transferred.
When I was attempting to change my WireGuard DNS server for my client device to be the IP address of my router's interface instead of my Pi-hole DNS server, DNS requests would not resolve properly. I tried changing various firewall rules and other settings. Nothing seemed to work, but my Pi-hole DNS server worked properly. I recalled when I was setting up the DNSCrypt-Proxy plugin in OPNsense, I removed the default system DNS servers (located at “System > Settings > General”) since the DNS servers I was using is handled by the DNSCrypt-Proxy plugin. In case I made changes, I assumed the default DNS servers were redundant.
It turns out that I could not use my router's Unbound DNS server (which then sends requests to the DNSCrypt-Proxy plugin which sends encrypted DNS requests to the configured DNS servers like Cloudflare or Quad9) in WireGuard unless I had the default DNS servers specified. When I checked the DNSCrypt-Proxy log file, the DNS requests from WireGuard clients were being passed from Unbound DNS to DNSCrypt-Proxy as it should be doing. I was wondering if it would bypass the DoH configuration I had established but it does not seem to do so. I thought I would add this scenario as something interesting to look out for depending on your current configuration. It caused me a lot of headaches because it does not come to mind as the first place to look when a problem occurs.
Another important consideration is that the configuration I have outlined above does not work if you are trying to use WireGuard while connected to your home network even if you try to use the external IP address. It is possible that some sort of NAT reflection, firewall rule(s), or other WireGuard configuration is necessary to make it function properly. For my purpose (and most others, I assume), if you are already on your home network, you do not need to access it via WireGuard.