Make Your Own VPN - Wireguard, Ipv6 and Ad-Blocking Included
![/featured/lock_iphone.webp](/featured/lock_iphone.webp)
Note: This article assumes a setup based on OpenBSD. If you prefer a version based on FreeBSD, it is available here.
VPNs are a fundamental tool for securely connecting to your own servers and devices. Many people use commercial VPNs for various reasons, ranging from not trusting their provider (especially when connecting from a public hotspot) to wanting to “go out” on the Internet with a different IP address, perhaps from another country.
Whatever the reason, solutions are not lacking. I have always set up management VPNs to allow servers and/or clients to communicate with each other using secure channels. Lately, I have been activating IPv6 connectivity on all my devices (both desktop/servers and mobile devices) and I needed to quickly create a node that concentrated some networks and allowed them to go out on the network in IPv6. The tools I used and will describe are:
- VPS - in this case, I used a basic Hetzner Cloud VPS (using this link, you will receive 20 euros of cloud credits), but any provider that provides IPv6 connectivity will do - if you want IPv6, of course.
- OpenBSD - a clean, stable, and secure operating system.
- Wireguard - lightweight, secure, and at the same time, not very “chatty”, so it is also gentle on mobile device batteries. When there is no traffic, it simply does not transmit/receive anything. Well supported by all major desktop and server operating systems as well as Android and iOS devices.
- Unbound - can make DNS queries directly to root servers, not through forwarders. It also allows you to insert block-lists and have a result similar to that of Pi-Hole (i.e., ad-blocking).
- SpamHaus lists - to immediately stop connections to and from users on blacklists.
The first step is to activate a VPS and install OpenBSD. On the Hetzner cloud console, there won’t be a pre-built OpenBSD image, but only a selection of Linux distributions. Don’t worry, just choose any of them and create the VPS. Once done, the OpenBSD ISO image will be available among the “ISO Images”. Just insert the virtual CD, restart the VPS, and the OpenBSD installation will appear in the console.
I won’t go into detail, the operation is simple and straightforward. The only precaution (in the case of a Hetzner Cloud VPS) is to use “autoconf” for IPv4 but, for now, do not configure IPv6. It will be configured later.
Install all OpenBSD updates (using the syspatch command) and restart, the kernel will be relinked.
Wireguard, on OpenBSD, is fully integrated into the base system and does not require the installation of external packages. This is a big advantage because over time, support for everything related to Wireguard will be managed directly by the main OpenBSD development team.
The first step is to configure IPv6 on the VPS. In the case of Hetzner, unfortunately, they only provide a /64, so it will be necessary to segment the assigned network. In this example, it will be divided into /72 subnetworks - to find valid subclasses, it will be possible to use a calculator.
The /etc/hostname.vio0 file should look something like this:
|
|
In short, keep the base address assigned by Hetzner, but change the netmask to /72 - thus giving the possibility of having other networks available.
|
|
It will reconfigure the network interface and allow IPv6 to start working. To test it:
|
|
If everything has been configured correctly, the ping will be executed and google.com will reply.
It is now necessary to enable forwarding for IPv4 and IPv6. Enter these lines in the /etc/sysctl.conf file:
|
|
To apply those changes you can reboot or just type:
|
|
To configure Wireguard, a few steps will be necessary. First of all, the private key will need to be created:
|
|
Something like this will come out:
YUkS6cNTyPbXmtVf/23ppVW3gX2hZIBzlHtXNFRp80w=
Now create a new file called /etc/hostname.wg0:
|
|
A new Wireguard interface called wg0 is being created. It will have the IPv4 address “172.14.0.1”, Wireguard will listen on port 51820, and with the private key created shortly before. It will also have an IPv6 address on one of the subclasses that the provider will have provided.
Save and activate the interface:
|
|
If everything has been entered correctly, it should enable the interface. Now:
|
|
And something like this will be returned:
|
|
Take note of the wgpubkey - it will be needed to configure the clients.
As for the firewall, OpenBSD comes with a basic pf configuration. In my setups, I tend to block what is not needed and be permissive with what may be useful. However, I like to keep out the “bad guys,” so I use blacklists. pf allows elements to be inserted and removed from tables in runtime, so the firewall can be configured accordingly.
To download and apply Spamhaus lists, I use a simple but effective script found on the Internet.
So create the script in /usr/local/sbin/spamhaus.sh:
|
|
Make it executable and run it:
|
|
There are many possibilities to configure pf. A fairly simple example could be this:
|
|
This is a very simple configuration: it blocks everything that is present in the list downloaded from Spamhaus, allows NAT from the Wireguard network to the public interface, allows icmp traffic in IPv6 (necessary for the network to function properly) while blocking incoming traffic to the Wireguard IPv6 LAN (remember that the IPs will be public and directly reachable, so we don’t want to expose our devices by default). All traffic on the Wireguard interface will be allowed to pass. Then everything will be blocked and exceptions will be specified, i.e. allowing ssh and Wireguard connections (of course). Authorization will also be granted to allow traffic to exit from the public network interface.
Reload pf configuration:
|
|
If everything went correctly, the firewall should have loaded the new options.
To obtain caching of DNS queries and the related ad-block, it is now time to configure Unbound. A while ago, I found a script which I slightly adapted. I don’t remember where I got it, so I’ll paste it here without citing the original creator.
Create a script to update the unbound ad-block, in /usr/local/sbin/unbound-adhosts.sh:
|
|
Similarly, make the script executable and run it:
|
|
Now, the Unbound configuration file in /var/unbound/etc/unbound.conf can be modified as follows:
|
|
Before launching unbound, it is necessary to give the appropriate permissions:
|
|
Now it is possible to enable and start unbound. Since it needs to load the (long) blocklist, it will take a few seconds:
|
|
If everything has been done correctly, unbound will be able to respond to requests made on 172.14.0.1 and 2a01:4f8:cafe:cafe:100::1, from their respective LANs.
Now it is possible to configure the Wireguard client. Each implementation has its own procedure (Android, iOS, MikroTik, Linux, etc.) but essentially it is sufficient to create the right configuration both on the server and on the client. For example, the server’s public key (visible by typing “ifconfig wg0” on the OpenBSD server) should be inserted into the “peer” that will be created on the client, while the client’s public key will be used on the server in this way:
Reopen the file /etc/hostname.wg0 and add:
|
|
Reload the configuration:
|
|
On the client, create a new configuration by inserting “172.14.0.2/32, 2a01:4f8:cafe:cafe:100::2/128” (the ones that were entered in the peer configuration in the hostname.wg0 file) in the local IP addresses. Set the DNS server address to “172.14.0.1” and/or its corresponding IPv6 address (in the example, 2a01:4f8:cafe:cafe:100::1 - yours will be different). In the peer, insert the server’s data, including its public key, IP address:port (in the example, the port is 51820), and allowed addresses (setting “0.0.0.0/0, ::0/0” means “all connections will be sent via Wireguard” - all the traffic will pass through the VPN for both IPv4 and IPv6).
It is also possible to use the VPN only as an ad-blocker, by only routing DNS traffic through it. To achieve this result, it is sufficient to configure the client so that the only allowed address is the one of the just-configured unbound (in this example, 172.14.0.1 or 2a01:4f8:cafe:cafe:100::1) - DNS resolution will occur via VPN, but browsing will continue to work through the main provider.
If you want the spamhaus and ad-block lists to be updated automatically, create the /etc/daily.local file and add the following lines:
|
|
All of this can be achieved simply with a basic installation of OpenBSD, without the need to install any additional packages. This is an advantage both in terms of update management and security.
Related Content
- How We Are Migrating (Many Of) Our Servers From Linux to FreeBSD - Part 1 - System and Jails Setup
- Installing Mastodon Inside a FreeBSD Jail
- FreeBSD - Assign OVH Failover IPs to FreeBSD Jails
- How We Are Migrating (Many Of) Our Servers From Linux to FreeBSD - Part 3 - Proxmox to FreeBSD
- How We Are Migrating (Many Of) Our Servers From Linux to FreeBSD - Part 2 - Backups and Disaster Recovery