Awesome
Custom third party binaries for the Mullvad VPN app
This repository holds our custom binaries and build scripts for third party software we need to
bundle with the Mullvad VPN app: OpenVPN for our target platforms, libmnl
and
libnftnl
for Linux, and Wintun and WireGuardNT for Windows.
Security and integrity
This repository should conform to the same integrity standards as the main Mullvad VPN app repository, meaning that every merge commit has to be signed.
This repository contains a number of submodules, pulling in the source code for the third party software we store the binaries for. These submodules must point to commits that are either directly signed or has a signed tag attached to them. Upon moving a submodule to a different commit, the new commit must be cryptographically verified.
Container image
The easiest way to build the binaries is by using the container image specified by Dockerfile
:
podman build . -t mullvadvpn-app-binaries
OpenVPN
The openvpn
submodule is tracking our mullvad-patches
branch that contain a few custom
changes needed by the Mullvad VPN app.
Updating OpenVPN
When bumping the submodule (rebasing mullvad-patches
) to a new OpenVPN release. Make sure
the upstream release tag is properly signed by the following gpg key:
B62E6A2B4E56570B7BDC6BE01D829EFECA562812
Then tag the new head of mullvad-patches
as <original tag name>-mullvad
, for example
v2.4.8-mullvad
. This tag should be signed and pushed to our fork repository.
Repeat the process above for the openvpn-build
. Note: The upstream tags are not signed in
openvpn-build
.
Building on macOS
Before building, one has to ensure that the build host has all the required dependencies installed:
brew install automake autoconf libtool pkg-config
Building the OpenVPN binary should be as simple as running:
make openvpn TARGET="aarch64-apple-darwin"
or
make openvpn TARGET="x86_64-apple-darwin"
depending on the desired target architecture.
Building on Linux
Simply run ./container-run.sh make openvpn
.
ARM64
Cross-compile on x64 Linux by setting the appropriate TARGET
:
./container-run.sh make openvpn TARGET="aarch64-unknown-linux-gnu"
Building for Windows
Building openvpn.exe
for Windows is done by cross-compiling from Linux using the container image:
-
Compile:
./container-run.sh make openvpn_windows
-
Sign
openvpn.exe
- Do this by copyingopenvpn.exe
to the Windows machine with the certificate and run the following in powershell:signtool sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 \ /d "Mullvad VPN" \ /du "https://github.com/mullvad/mullvadvpn-app#readme" \ /f the_certificate.pfx \ /p <the_certificate.pfx password> \ openvpn.exe
OpenSSL
OpenSSL is a transitive dependency for OpenVPN. When bumping the submodule to a new OpenSSL release. Make sure to only point to a release tag, and not a random commit. Also verify that said tag is properly signed by one of the keys listed here: https://www.openssl.org/community/otc.html
apisocks5
This is a small SOCKS5 proxy designed to be used in conjunction with the Mullvad VPN app for accessing the Mullvad API from restricted locations. See mullvad/apisocks5.
Build instructions:
# on linux (x86_64)
./container-run.sh make apisocks5 TARGET="x86_64-unknown-linux-gnu"
./container-run.sh make apisocks5 TARGET="aarch64-unknown-linux-gnu"
./container-run.sh make apisocks5 TARGET="x86_64-pc-windows-msvc"
./container-run.sh make apisocks5 TARGET="aarch64-pc-windows-msvc"
./container-run.sh make apisocks5 TARGET="x86_64-apple-darwin"
./container-run.sh make apisocks5 TARGET="aarch64-apple-darwin"
When bumping the submodule to a new apisocks5 release. Make sure to only point to a release tag, and not a random commit. Also verify that said tag is properly signed by a trusted party at Mullvad.
Windows
apisocks5.exe
must be signed before being committed to this repository:
signtool sign \
/tr http://timestamp.digicert.com \
/td sha256 /fd sha256 \
/sha1 "<certificate-sha1-thumbprint>" \
/v apisocks5.dll
signtool
is available in the Windows SDK.
libmnl
and libnftnl
These libraries are only required for Linux and are required by our app to
apply firewall rules. To produce the required libraries, run ./container-run.sh make libnftnl
.
ARM64
Cross-compile both libraries on x64 Linux by setting the appropriate TARGET
:
./container-run.sh make libnftnl TARGET="aarch64-unknown-linux-gnu"
libnl
libnl
is a dependency of OpenVPN, specifically DCO on Linux.
When bumping the submodule, point to a release tag, and verify that the tag is signed by
49EA7C670E0850E7419514F629C2366E4DFC5728
.
Updating Wintun
Only applicable to Windows.
Wintun is found in .\<arch>-pc-windows-msvc\wintun\wintun.dll
. The driver can be downloaded and verified
by running the script .\wireguard\download-wintun.cmd
. This script downloads Wintun, verifies its
checksum, and makes sure that wintun.dll is correctly signed.
WireGuardNT
Only applicable to Windows.
WireGuardNT can be found in .\<arch>-pc-windows-msvc\wireguard-nt
. The wireguard-nt
submodule contains a fork that fixes multihop tunnels.
To update it, pull the new tag from https://git.zx2c4.com/wireguard-nt, manually verify that the
changes are sensible, and rebase the mullvad-patches-build
branch on top of it. The new head of
mullvad-patches-build
should be tagged as <original tag name>-mullvad
, for example
0.7-mullvad
. This tag should be signed and pushed to the fork repository.
Follow the instructions in MULLVAD_BUILD.md
in said submodule to build and sign the driver.
Split tunnel driver
Only applicable to Windows.
The split tunneling functionality implemented in Mullvad VPN app is supported by a custom kernel driver.
The driver is developed by us, and is represented here as a submodule named win-split-tunnel
.
Instructions for building and signing the driver are provided in said submodule.
The built and signed driver, and associated files, reside under <arch>\split-tunnel
.
Storage of binaries
This repository, apart from having the scripts used to build OpenVPN, also holds the built binaries for the platforms we need. These exist under directories named after the target triplet they are intended for.