How to Configure the WireGuard VPN Server in OPNsense

post-thumb

Photo by Danny144 from Pixabay

Table of Contents

WireGuard is a modern designed VPN that uses the latest cryptography for stronger security, is very lightweight, and is relatively easy to set up once you understand how it functions in OPNsense. I found setting up WireGuard in OPNsense to be more difficult than I anticipated when I was first learning how to properly configure the service. It seemed to be more difficult than configuring OpenVPN even though there are fewer options to configure in WireGuard (since WireGuard takes care of many details behind the scenes).

WireGuard is similar to a SSH server that is configured to use keys since only devices which share their cryptographic keys with one another are able to connect via an encrypted tunnel. The WireGuard protocol is designed to only respond to clients which present a valid key so WireGuard cannot be port scanned like other services since it requires authentication before any response is sent. That is a nice security benefit of WireGuard. Here is a quote from the WireGuard documentation:

“We require authentication in the first handshake message sent because it does not require allocating any state on the server for potentially unauthentic messages. In fact, the server does not even respond at all to an unauthorized client; it is silent and invisible. The handshake avoids a denial of service vulnerability created by allowing any state to be created in response to packets that have not yet been authenticated.”

Devices that connect via WireGuard are referred to as “peer” devices. WireGuard uses the terminology of peers and endpoints rather than clients and servers. Every device connecting via WireGuard is considered a peer or endpoint. Therefore, the WireGuard VPN in OPNsense is simply a peer which other WireGuard-enabled devices (peers) on your network may connect. I will refer to the WireGuard installation on OPNsense as the WireGuard server rather than a “peer” to make it more clear which device I am configuring unless I am describing various elements on the user interface so that I am consistent with the terminology used by WireGuard.

Please keep in mind that in this guide I am describing how to connect securely to your home network remotely via WireGuard in OPNsense and not how to connect OPNsense to an external WireGuard VPN provider such as Mullvad. I imagine many of the same concepts apply but your mileage may vary.

Note

If your ISP blocks all incoming connections as in the case with CGNAT, you will not be able to directly connect to your home network via WireGuard on OPNsense. You will have to consider using a Virtual Private Server (VPS) to create a VPN tunnel or some other means such as Cloudflare Argo tunnels in order to access services on your home network remotely.

Install the WireGuard VPN Plugin

The first thing that you will need to do 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.

OPNsense Install WireGuard

Tip

As of OPNsense 23.1, the kmod version of WireGuard is the default plugin. If you upgrade from a version of OPNsense prior to 23.1, you will be automatically updated to the kmod version of WireGuard. The Go version is still available should want to use it instead.

One reason to use the Go version is if you use Zenarmor since at the time of this update, Zenarmor only works on the Go version of WireGuard due to lacking netmap support for the kernel version of WireGuard.

Configure the WireGuard VPN Server

After installing the plugin, let us start configuring the WireGuard VPN Server. Go to the “VPN > WireGuard” page and click the “Local” tab. Click the “+” button to add a new WireGuard server.

OPNsense WireGuard Server List

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. Even if you plan to use the default port, you must enter 51820. I tried leaving it blank to test if I could connect to the server, and I was unable to do so. Do not assume if you leave it blank that it will use the default port!

Amendment: In my original post, I stated that changing the default port to something different would reduce port scanning traffic since many scanners simply check the default ports and could potentially reduce the likelihood of the VPN being attacked (although I have not yet heard of any WireGuard VPN breaches). I assumed that would be the case similar to most other hosted services, but after receiving information about how the WireGuard protocol works I now know that authentication is required before any response is sent back to the client.

If you have Unbound DNS in OPNsense set at the default behavior of being applied to “All” interfaces or you have the WireGuard interface selected as one of the interfaces that uses Unbound DNS, it will use the WireGuard tunnel address as the DNS server, which in our example will be 10.0.0.1. This is essentially the same behavior as any other interface in OPNsense when Unbound DNS is enabled on the interface.

Note

If you are using alternate DNS server(s) such as Pi-hole, you will need to specify those DNS servers by clicking the “advanced mode” and entering the DNS server IP address in the “DNS Server” box. You will need to have a firewall rule to allow access to the alternate DNS server(s) (unless you have an “allow all” rule for your WireGuard clients, which is not the best security practice).

For the “Tunnel Address”, enter a network address such as 10.0.0.1/24. The WireGuard interface address will be 10.0.0.1 and the network will fall in the 10.0.0.2-10.0.0.254 range. 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.

Warning

You should choose an address range that falls outside the range of the other networks you have set up in OPNsense as well as any network(s) where you are connecting from.

I did not consider the issue of the network addresses of where I was connecting from until I tried connecting from my parents’ network which used the same 10.0.0.0/24 network range as my WireGuard network. VPNs typically operate on their own virtual networks so they need to have different address ranges than any of the physical networks which you are connected.

Even though the WireGuard network addresses have to be different that your other internal networks, you can still allow access to other parts of your network via firewall rules (see the (Optional) Add Firewall Rules to Access Internal Networks/Devices section below).

For the “Peers” dropdown, you will need to select all of your configured peers that you wish to access your home network remotely, but for now you need to leave the “Peers” as “Nothing selected”. Once you have your users/peers configured as described in the steps below, you will need to come back to this tab to select the peers.

Click the “Save” button.

OPNsense Add WireGuard VPN

Copy and Send the Server’s Public Key

After saving the WireGuard server configuration, click the edit button (the pencil icon).

OPNsense WireGuard List Edit

You will notice that the public and private keys have been automatically generated. In order to set up peers/clients that will connect to your OPNsense WireGuard VPN, you will need to send the server’s public key to all of your WireGuard client devices. Emailing the public key may be the easiest way to send the key to a mobile device or using a secure file sync application with the key in a text file…or you can simply just type out the long key but that is potentially error prone.

OPNsense Edit WireGuard VPN

Warning

Only send yourself the public key. You need to keep the private key a secret! You do not have to worry as much about keeping the public key a secret like the private key. However, it is not a bad idea if you wish to avoid sending the public key to yourself over unsecure communications such as email. A malicious user will need your private key in order to fully decrypt your traffic.

Configure the WireGuard Client (iOS Example)

Now that you have the server’s public key sent to the client device, you can now set up the 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, click the “Add a tunnel”.

OPNsense iOS WireGuard Blank

Then click “Create from scratch” since the WireGuard OPNsense plugin does not support QR codes at the time of this writing.

OPNsense iOS WireGuard Configuration

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. You cannot use 10.0.0.1/32 since it is the interface address. The /32 is CIDR notation which in this case means you are specifying a single IPv4 address.

The “Listen port” can be left blank since it will automatically select a random port. This is the listen port of the client and not the OPNsense WireGuard server so it does not have to be set to the same port as the server.

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”. When I first tried WireGuard, this caused an issue for me until I realized I needed to enter the DNS information since it does not automatically use the WireGuard interface IP address.

OPNsense iOS WireGuard Configuration

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. You will need to leave the WireGuard app (but do not force close the app since you will lose your progress!) and open your email client (or file sync app) in order to obtain the public key you sent yourself. Copy and paste the public key into the “Public key” box.

If you plan to use a passphrase in addition to the keys, you can enter it in the “Preshared key” box. Be sure to use the same preshared key when you set up the client endpoint in OPNsense.

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 noip.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). You need to include the port number after your domain name or IP address even if you are using the default port. As you can see in the screenshot below, I used a fictional domain and the WireGuard server port number: vpn.home.com:51820.

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 lookups is tunneled through WireGuard. Routing all network traffic through the VPN is useful if you want to use public WiFi hotspots, but it is also good if you do not wish to leak DNS lookups from your device for privacy reasons. If you are using IPv6, you can specify ::/0 after the 0.0.0.0/0 (separated by a comma) to tunnel all IPv6 traffic in the same way as IPv4.

OPNsense iOS WireGuard Configuration

Do not click “Save” until you complete the next step of copying the iOS client public key. It will save you a few clicks.

Copy the WireGuard Client’s Public Key (iOS Example)

Before saving the client configuration, scroll back up to the top of the screen and click on the long string of characters beside the “Public key” label under the “Interface” section (for the iOS client’s public key). A “copy” dialog box will be displayed. Click “copy” and paste the public key somewhere you can access easily. If you can access the OPNsense web interface from your phone you could paste it using that method as well. You will need the iOS client’s public key in the next step.

OPNsense iOS Public Key

Click “Save” to finish setting up the iOS client.

Configure the WireGuard Client Endpoint in OPNsense

With the user/client device configured, next up is the client endpoint configuration in OPNsense. Go back to the “VPN > WireGuard” page and click on the “Endpoints” tab. Then click the “+” button to add a new client.

OPNsense Endpoint List

Click the “Enabled” checkbox and a descriptive “Name” for the user (something more descriptive than User1).

Enter the “Public Key” you copied in the previous step for the client.

A “Shared Secret” may be used if you want another layer of protection. If someone is able to obtain your private key, a valid password is required for communication to occur. You need to ensure you use the same preshared key as you entered for your client device.

For the “Allowed IPs” box, enter the user/client’s IP address. This address is a static address associated with the client’s public key, which in my example is 10.0.0.2/32.

You may leave the “Endpoint Address” and the “Endpoint Port” blank. Click the “Save” button.

OPNsense Add User

Add the WireGuard Client to the WireGuard VPN Server

As mentioned earlier, after a client/peer has been added in OPNsense, you will need to go back to the WireGuard server configuration to add a new peer. This step is critical in allowing your WireGuard client access to your WireGuard VPN server.

On the “VPN > WireGuard” page, click the “Local” tab. Then you will need to click the pencil edit icon on your server instance you created earlier. You will see a “Peers” option near the bottom. Clicking on the dropdown box should show you a list of all of your WireGuard clients/endpoints. Choose the client endpoint you created in the prior step (in this example, it is User1) and click “Save” when you are finished.

OPNsense Add Peer

Enable the WireGuard VPN Server

At this point, the WireGuard VPN server can be enabled since the server and one client endpoint has been configured. To enable to the WireGuard server, go to the “General” tab and click the “Enable WireGuard” checkbox.

OPNsense Enable WireGuard

Click the “Apply” button.

Add the WireGuard Interface

A WireGuard interface is not automatically created when the service is enabled like with OpenVPN. Technically, creating a WireGuard interface is optional, but I highly recommend it. The benefits of creating a WireGuard interface are listed in the official OPNsense WireGuard documentation. The greatest benefit is that it automatically creates the necessary outbound NAT rule to allow clients to access your home Internet connection (assuming you have the appropriate firewall rules in place to allow it).

If you only need to access your home network but not your home network’s Internet connection, you may skip this step. However, if you plan to have more than once instance of WireGuard, I recommend creating separate interfaces because it will make creating firewall rules more straightforward.

To add the WireGuard interface, go to “Interfaces > Assignments”. Select the “wg0” interface (which may already be selected if it is the only interface available to be assigned). Enter a “Description” so that the interface is easier to identify. Otherwise, it will be displayed something like “[OPT1]”. I am using “WG” in my example. Click the “+” button to add the interface to the list of interfaces.

OPNsense Add Interface

Go to the “Interfaces > [WG]” page. Click the “Enable” checkbox and “Prevent interface removal” checkbox. You do not need to enter any other interface settings like you normally would do for physical interfaces (because the IP address range is specified on the “VPN > WireGuard > Local” page).

OPNsense Configure Interface

Add the WAN Firewall Rule

To allow external access to the WireGuard VPN, a WAN rule needs to be created. Since the WireGuard service is running on the OPNsense system, you do not need to use a NAT port forward rule. Go to the “Firewall > Rules > WAN” page. Click on the “+” button to add a new firewall rule.

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).

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 the default port 51820 but if you are using a different port, you need to enter it.

You may add a useful “Description” such as “Allow external access to the WireGuard VPN server”.

OPNsense WireGuard WAN Rule

Add the Outbound NAT Rule (Required if Not Creating WireGuard Interface)

If for some reason you do not want to create a WireGuard interface, you will need to manually add the outbound NAT rule. I do not recommend doing this since creating the WireGuard interface simplifies the configuration in a number of ways. For the sake of completeness, I will describe the process in hopes that it will help someone. Please skip this step if you already created a WireGuard interface!

If you are using the default “Automatic outbound NAT rule generation” option on the “Firewall > NAT > Outbound NAT” page, 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 so you do not have to manually configure the outbound NAT rules for all of your networks.

Once you enable the hybrid or manual mode, you will see a “+” button on the top right corner of the “Manual rules” section.

OPNsense WireGuard Outbound NAT Hybrid

Click the “+” button to create a new outbound NAT rule.

OPNsense WireGuard Outbound NAT Rule

Ensure that the “Interface” is set to “WAN”. Choose “any” for the “Protocol”. The “Source address” should be “WireGuard (Group) net” which is the autogenerated alias that applies to all instances of WireGuard. Since you did not create a WireGuard interface, it will be your only WireGuard alias you can select. 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 so that outgoing WireGuard traffic will be translated to the external WAN interface address (NAT translation just like with other interfaces that are behind a NAT).

Add Firewall Rules to Access Internal Network(s)/Internet

At this point, the WireGuard VPN should be configured to allow external connections from client devices such as your phone. However, if you do not create any firewall rules, the client will not be able to access anything on your network. It is just like any other interface on your network – no firewall rules means “deny all”.

If you want to keep the rules simple, you could create an “allow all” rule that will allow the WireGuard users full access to your network, but I imagine you would want to only allow access to specific devices/services on your network and the Internet. If you are connecting to your home network using one of your mobile devices, you may want to simply clone the rules you use for the network that device is connected to in order to provide the same access remotely as you do internally. Of course you can choose to increase or decrease the amount of access as you see it. I tend to mimic the same rules I have for my IoT network where my cell phones/tablets connect so that I have the same level of access when I am connecting remotely as I do when I am connected at home.

The bare minimum rules to provide network isolation is similar to other interfaces: allow access to the interface address for DNS and block access to all private networks. Then you can add rules before the “block access to all private networks” to allow access to specific devices/services on your network. Go to the “Firewall > [WG]” page to add the following rules. Note that you will need to create an alias for “PrivateNetworks” as described below.

This rule allows DNS access to the WireGuard interface, which is 10.0.0.1 in my example, but you can use the “WG address” alias if you created a WireGuard interface (it is one of the advantages of creating an interface – automatic aliases for the interface/network). This rule is necessary because the next rule would end up blocking access since it blocks all private IP addresses. It is easier to block all private IP addresses and then allow specific access in order to provide network isolation across multiple networks.

Option Value
Action Pass
Interface WG
TCP/IP Version IPv4
Protocol TCP/UDP
Source WG net
Source Port any
Destination WG address
Destination Port DNS (53)
Description Allow access to the WG DNS server

The second rule blocks access to all private IP addresses but allows access to all public IP addresses. The “Destination / Invert” option is very important to enable because it essentially means “not” so the rule below allows all traffic that is not on private networks. With these two rules, you will have Internet access but no other access to your internal network(s). If you simply want a secure VPN for public WiFi hotspots, you do not need any other rules.

Option Value
Action Pass
Interface WG
TCP/IP Version IPv4
Protocol any
Source WG net
Source Port any
Destination / Invert checked
Destination PrivateNetworks (alias containing: 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16)
Destination Port any
Description Allow access to Internet and block access to all local networks

Since the internal network firewall rules could vary greatly depending on your specific needs, I will leave the creation of other rules as an exercise for the reader. If you would like some guidance on creating OPNsense firewall rules, I have written about it in another how-to. I have also created a “cheat sheet” list providing several common firewall rule examples.

Important: All of your firewall rules should be applied to the WireGuard interface you created so that you can have separate rules if you are running multiple WireGuard instances. There is an automatically generated firewall group called “WireGuard (Group)” which allows you to apply the same set of rules across multiple instances of WireGuard.

Connect to the WireGuard VPN

The moment of truth… you are finally ready to connect to your WireGuard VPN! 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.

OPNsense WireGuard User Connected

(Optional if not Automatic) Add ACL Entry for Unbound DNS

If you plan to use your WireGuard interface such as 10.0.0.1 in my example to provide DNS to your WireGuard clients rather than use some other DNS server on your network, it has been noted through feedback that there could be the possibility that you will need to manually add an entry to the Unbound DNS ACL (Access Control List) to allow the WireGuard interface to access your Unbound DNS server in OPNsense.

I have not personally encountered this issue, but if you are having issues with accessing your WireGuard interface DNS server (not Pi-hole, etc), you may want to check your ACL configuration by going to the “Services > Unbound DNS > Access Lists” page. Click the “Add” button to enter the WireGuard network 10.0.0.1/24 (or the IP range you are using) to the ACL.

Some users have noted that they needed to restart the Unbound DNS service before DNS functioned properly so perhaps that is all you need to do for the Unbound DNS ACL to be populated with the WireGuard network (especially if you made other DNS changes to Unbound during this process).

Conclusion

Although my initial attempt to configure WireGuard was a bit of a struggle, once I learned how to configure WireGuard in OPNsense, it became easier to configure than OpenVPN especially since you do not have to worry about creating certificate authorities, certificates, and separate user accounts in OPNsense. Part of my struggle was the fact I was using Pi-hole in my network at that time along with DNSCrypt-Proxy which made the DNS configuration more complex. Since the original version of this how-to, I have switched from Pi-hole to Zenarmor and now use DNS over TLS using the built-in functionality in Unbound DNS rather than DNSCrypt-Proxy. That has helped to simplify my network configuration, and I have fewer places to check when something I want to access gets blocked.

I hope you found this guide for setting up WireGuard in OPNsense helpful!

comments powered by Disqus