Wireguard VPN for OpenBSD/Linux
Jun 19, 2022
Wireguard is a simple VPN (Virtual Private Network) protocol known for its speed and security. It has been implemented in the Linux kernel as well as in OpenBSD. This is a guide on how to set up a Wireguard connection between two devices (an OpenBSD server and a Linux client) and a DNS resolver, in order to securely tunnel the traffic while using insecure public networks, or in any other case where it might be needed.
The official website of Wireguard includes a conceptual overview section and other links where the protocol is explained in more detail. What we need to do is generate keypairs for our server and our client (which are not taxonomically different in terms of how their configurations are handled), add the client as a peer on the server configuration, and add the server as a peer on the client configuration. Multiple peers may be added on the server to allow more client connections.
We begin by generating a base64 encoded 32-byte string that Wireguard can use as our private key.
The private key is now stored in the wg0.key
file. We change the file permissions for good measure.
Next, we create a network interface for Wireguard associating it with the private key we generated. We can also change the port for some obscurity, instead of using the default which is 51820. I chose 50101 in this case.
We can now verify that the interface was created with ifconfig
.
The wg0
interface should appear in the output.
wg0: ...
...
wgpubkey: <server-public-key>
...
The output should contain the public key that is extracted from the private key, on the line starting with wgpubkey
. We note down this key.
We also need to assign an IP address to the server for the VPN tunnel. I'm using the 10.0.0.0/24 subnet since it is available and reserved for private networks. You can use another subnet if this one not available for your network.
Now we move on to the Linux client to set up the interface.
Here, we install the wireguard-tools
package since it makes things easier. I am using Void Linux; you can use the package manager of your distribution.
wireguard-tools
on OpenBSD, but unnecessary in my opinion since the OpenBSD implementation is very simple.We create a new Wireguard interface. This time we do not need to specify a wg port, as we do not need to handle incoming connections on the client for this setup.
We also assign a different IP address for this endpoint, again on the 10.0.0.0/24 subnet.
This time, we generate a key using the wg
command from wireguard-tools
and add it to the wg0 interface on our client. It is possible to use openssl
for this as well.
Next up, we need to connect the client and the server. For this step, we need the public keys in order to add peers. We can check the public key that was extracted from the private key for our client.
The public key appears in the output. We note this key down.
interface: wg0
public key: <client-public-key>
private key: (hidden)
First, we add our server as a peer on the client, using the server public key we obtained earlier.
This specifies the peer public key, the allowed IP addresses and the server endpoint including the IP address and the port.
allowed-ips
is set to 0.0.0.0/0, which means all IP addresses. This tells Wireguard to send packages destined for any IP address over the tunnel. Therefore, all traffic while browsing the Internet goes through Wireguard.Now we write all of this to a configuration file on the Linux client, in order to be able to quickly set up the interface and initiate the connection in the future.
Here is the configuration including all the information.
[Interface]
<client-private-key>
DNS =
[Peer]
<server-public-key>
<server-public-IP>
25
DNS
line in the configuration file. We will be setting up a DNS resolver on our server with unbound
later. This is recommended, since your queries will go over your ISP's default DNS servers otherwise, which defeats the purpose of using a VPN for privacy in most cases. If this is not what you want, you should omit this line so that you can keep using the default DNS settings.Next, we add the client as a peer on our OpenBSD server, and make the configuration persistent across reboots by creating a hostname
file for the interface.
Here is what we should write in hostname.wg0
.
inet 10.0.0.1 255.255.255.0
wgkey <server-private-key>
wgport 50101
wgpeer <client-public-key> wgaip 10.0.0.2/24
up
We can use unbound
with a simple setup for now. We open the unbound
configuration file.
Here is a basic configuration.
server:
interface: 0.0.0.0
interface: ::1
access-control: 10.0.0.1/24 allow
access-control: 127.0.0.0/8 allow
access-control: ::1 allow
access-control: 0.0.0.0/0 refuse
access-control: ::0/0 refuse
hide-identity: yes
hide-version: yes
auto-trust-anchor-file: "/var/unbound/db/root.key"
qname-minimisation: yes
aggressive-nsec: yes
Now we enable and start unbound
We also need to enable IP forwarding (and make it persistent across reboots) on our OpenBSD server so that the VPN can function for browsing the Web.
Finally, we need to make the necessary changes in our pf
firewall configuration in order to allow traffic over Wireguard.
We add the following lines to pf.conf
.
"{50101}"
on wg in log on egress inet proto { udp } from any to any port $port_wg in log on egress inet from (wg:network) to any nat-to (egress:0) out
We load the firewall configuration.
That's is. We should now be able to initiate the VPN connection on our Linux client, and tunnel the traffic over Wireguard.