:.: Mullvad to hostname.if

I found Mullvad not long ago and I just totally loved their approach to many things in privacy and customers information, you can read more about them on their website of course, but the highlights I like the most are:

* You can pay sending a letter!
* Ram based servers
* They accept all kind of payments
* Wireguard configs
* They don't give information about customers

So basically are good guys (you can research about them), anyway...

I want to believe

:. "The problem"

Once you create an account on Mullvad you get your hash/customer number and you can create devices that you want to connect with your account, of course Mullvad keeps the Wireguard's config files as default but on OpenBSD we have a different syntax, that you can see here hostname.if(5) or here on a previous article.

You can create a device and download all the config files for it, with all the different locations around the globe, the thing is, you need to convert from the original Wireguard's config file to our hostname.if(5), so since I know you are as lazy as I am, I created a little script that with a Wireguard's config file given it will create an OpenBSD one.

:. Converting to OpenBSD

The script will create for a given file a hostname.wg0_name_of_mullvad_conf_given as output with a pre-loaded wg config using rdomain(4) to ensure that all the traffic goes inside the tunnel, you can read more on my other wireguard article.

Assuming that you already have a hostname.if(5) for your wireless card using rdomain(4) like this:

$ doas cat /etc/hostname.iwm0
rdomain 1
-wpa
join "OpenBSD" wpakey "puffypuffy"
inet autoconf

And you downloaded all the config files, you can use the little script as follow to create the OpenBSD's files:

$ ls -al *jp*.conf
-rw-r--r--  1 gonzalo  gonzalo   292B Feb 10 08:41 jp-osa-wg-001.conf
-rw-r--r--  1 gonzalo  gonzalo   293B Feb 10 08:41 jp-osa-wg-003.conf
-rw-r--r--  1 gonzalo  gonzalo   293B Feb 10 08:41 jp-osa-wg-004.conf
-rw-r--r--  1 gonzalo  gonzalo   293B Feb 10 08:41 jp-tyo-wg-001.conf
-rw-r--r--  1 gonzalo  gonzalo   293B Feb 10 08:41 jp-tyo-wg-002.conf
-rw-r--r--  1 gonzalo  gonzalo   293B Feb 10 08:41 jp-tyo-wg-201.conf
-rw-r--r--  1 gonzalo  gonzalo   291B Feb 10 08:41 jp-tyo-wg-202.conf
-rw-r--r--  1 gonzalo  gonzalo   292B Feb 10 08:41 jp-tyo-wg-203.conf
$ cat wg-to-hostname
#!/bin/sh

## get info from mullvad's files
DESC=$1
ADDRESS=$(awk -F '[=,]' '/Address/{print $2}' "$1" | tr -d '[:space:]')
PRIVATE_KEY=$(awk -F '[=,]' '/PrivateKey/{print $2}' "$1" | tr -d '[:space:]')
PUBLIC_KEY=$(awk -F '[=,]' '/PublicKey/{print $2}' "$1" | tr -d '[:space:]')
ENDPOINT_IP=$(awk -F '[=,:]' '/Endpoint/{print $2}' "$1" | tr -d '[:space:]')
ENDPOINT_PORT=$(awk -F '[=,:]' '/Endpoint/{print $3}' "$1" | tr -d '[:space:]')

## create the hostname.wg0 file
cat <<EOF >>hostname.wg0_$1
description ${DESC}
inet ${ADDRESS}
wgkey ${PRIVATE_KEY}=
wgpeer ${PUBLIC_KEY}= wgrtable 1 wgendpoint ${ENDPOINT_IP} ${ENDPOINT_PORT} wgaip 0.0.0.0/0
!route add default -link -iface wg0
up
EOF

Running the script for all the Japan locations inside a for should be something like this

$ for i in $(ls *jp*.conf); do ./wg-to-hostname $i; done
$ $ ls -al hostname.wg0_jp-*                                                                                                           
-rw-r--r--  1 gonzalo  gonzalo   246B Feb 10 13:16 hostname.wg0_jp-osa-wg-001.conf
-rw-r--r--  1 gonzalo  gonzalo   247B Feb 10 13:16 hostname.wg0_jp-osa-wg-003.conf
-rw-r--r--  1 gonzalo  gonzalo   247B Feb 10 13:16 hostname.wg0_jp-osa-wg-004.conf
-rw-r--r--  1 gonzalo  gonzalo   247B Feb 10 13:16 hostname.wg0_jp-tyo-wg-001.conf
-rw-r--r--  1 gonzalo  gonzalo   247B Feb 10 13:16 hostname.wg0_jp-tyo-wg-002.conf
-rw-r--r--  1 gonzalo  gonzalo   247B Feb 10 13:16 hostname.wg0_jp-tyo-wg-201.conf
-rw-r--r--  1 gonzalo  gonzalo   245B Feb 10 13:16 hostname.wg0_jp-tyo-wg-202.conf
-rw-r--r--  1 gonzalo  gonzalo   246B Feb 10 13:16 hostname.wg0_jp-tyo-wg-203.conf

Placing one of those under /etc and restarting the network or each device it will connect to the VPN and you should be able to see it on the ifconfig(8) output as follows:

$ doas cp hostname.wg0_jp-tyo-wg-001.conf /etc/hostname.wg0
$ doas ifconfig iwm0 down
$ doas ifconfig wg0 destroy
$ doas route -n flush
$ doas sh /etc/netstart iwm0
$ doas sh /etc/netstart wg0
$ doas ifconfig wg0
wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
        description: Mullvad WireGuard (jp-tyo-wg-001)
        index 8 priority 0 llprio 3
        wgport 10374
        wgrtable 1
        groups: wg egress
        inet 19.19.90.36 netmask 0xffffffff

If you check your public IP should be one of Mullvad or you can check it out already on their website on the top of it. Keep in mind that if you want to connect to your local network you need to use route(4) and the table name, for example:

$ route -T1 exec ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=1.086 ms
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.910 ms
^C
--- 192.168.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.910/0.998/1.086/0.088 ms

We are done, you can rotate the files and restart the wg0 to get another location, or many other things that you probably have in mind, in case you already have wg0 adjust the script to another device.