• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

mullvad/mullvadvpn-app: The Mullvad VPN client app for desktop and mobile

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

mullvad/mullvadvpn-app

开源软件地址(OpenSource Url):

https://github.com/mullvad/mullvadvpn-app

开源编程语言(OpenSource Language):

Rust 39.3%

开源软件介绍(OpenSource Introduction):

Mullvad VPN desktop and mobile app

Welcome to the Mullvad VPN client app source code repository. This is the VPN client software for the Mullvad VPN service. For more information about the service, please visit our website, mullvad.net (Also accessible via Tor on our onion service).

This repository contains all the source code for the desktop and mobile versions of the app. For desktop this includes the system service/daemon (mullvad-daemon), a graphical user interface (GUI) and a command line interface (CLI). The Android app uses the same backing system service for the tunnel and security but has a dedicated frontend in android/. iOS consists of a completely standalone implementation that resides in ios/.

Releases

There are built and signed releases for macOS, Windows, Linux and Android available on our website and on Github. The Android app is also available on Google Play and F-Droid and the iOS version on App Store.

You can find our code signing keys as well as instructions for how to cryptographically verify your download on Mullvad's Open Source page.

Platform/OS support

These are the operating systems and their versions that the app officially supports. It might work on many more versions, but we don't test for those and can't guarantee the quality or security.

OS/Platform Supported versions
Windows 10 and 11
macOS The three latest major releases
Linux (Ubuntu) The two latest LTS releases and the latest non-LTS releases
Linux (Fedora) The versions that are not yet EOL
Linux (Debian) The versions that are not yet EOL
Android The four latest major releases
iOS 12 and newer

On Linux we test using the Gnome desktop environment. The app should, and probably does work in other DEs, but we don't regularly test those.

Features

Here is a table containing the features of the app across platforms. This reflects the current state of latest master, not necessarily any existing release.

Windows Linux macOS Android iOS
OpenVPN
WireGuard
OpenVPN over Shadowsocks
Split tunneling
Custom DNS server
Ad and tracker blocking
Optional local network access ✓*

* The local network is always accessible on iOS with the current implementation

Security and anonymity

This app is a privacy preserving VPN client. As such it goes to great lengths to stop traffic leaks. And basically all settings default to the more secure/private option. The user has to explicitly allow more loose rules if desired. See the dedicated security document for details on what the app blocks and allows, as well as how it does it.

Checking out the code

This repository contains submodules needed for building the app. However, some of those submodules also have further submodules that are quite large and not needed to build the app. So unless you want the source code for OpenSSL, OpenVPN and a few other projects you should avoid a recursive clone of the repository. Instead clone the repository normally and then get one level of submodules:

git clone https://github.com/mullvad/mullvadvpn-app.git
cd mullvadvpn-app
git submodule update --init

We sign every commit on the master branch as well as our release tags. If you would like to verify your checkout, you can find our developer keys on Mullvad's Open Source page.

Binaries submodule

This repository has a git submodule at dist-assets/binaries. This submodule contains binaries and build scripts for third party code we need to bundle with the app. Such as OpenVPN, Wintun etc.

This submodule conforms to the same integrity/security standards as this repository. Every merge commit should be signed. And this main repository should only ever point to a signed merge commit of the binaries submodule.

See the binaries submodule's README for more details about that repository.

Install toolchains and dependencies

Follow the instructions for your platform, and then the All platforms instructions.

These instructions are probably not complete. If you find something more that needs installing on your platform please submit an issue or a pull request.

Windows

The host has to have the following installed:

  • Microsoft's Build Tools for Visual Studio 2019 (a regular installation of Visual Studio 2019 Community edition works as well).

  • Windows 10 SDK.

  • msbuild.exe available in %PATH%. If you installed Visual Studio Community edition, the binary can be found under:

    C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\amd64
    
  • bash installed as well as a few base unix utilities, including sed and tail. The environment coming with Git for Windows works fine.

  • gcc for CGo.

Linux

Debian/Ubuntu

# For building the daemon
sudo apt install gcc libdbus-1-dev
# For building the installer
sudo apt install rpm

Fedora/RHEL

# For building the daemon
sudo dnf install dbus-devel
# For building the installer
sudo dnf install rpm-build

Cross-compiling for Linux ARM64

By default, the app will build for the host platform. It is also possible to cross-compile the app for ARM64 on x64.

Debian

# As root
dpkg --add-architecture arm64 && \
    apt update && \
    apt install libdbus-1-dev:arm64 gcc-aarch64-linux-gnu
rustup target add aarch64-unknown-linux-gnu

To make sure the right linker and libraries are used, add the following to ~/.cargo/config.toml:

[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

[target.aarch64-unknown-linux-gnu.dbus]
rustc-link-search = ["/usr/aarch64-linux-gnu/lib"]
rustc-link-lib = ["dbus-1"]

Android

These instructions are for building the app for Android under Linux.

Download and install the JDK

sudo apt install zip default-jdk

Download and install the SDK

The SDK should be placed in a separate directory, like for example ~/android or /opt/android. This directory should be exported as the $ANDROID_HOME environment variable.

cd /opt/android     # Or some other directory to place the Android SDK
export ANDROID_HOME=$PWD

wget https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip
unzip commandlinetools-linux-6609375_latest.zip
./tools/bin/sdkmanager "platforms;android-29" "build-tools;29.0.3" "platform-tools"

If sdkmanager fails to find the SDK root path, pass the option --sdk_root=$ANDROID_HOME to the command above.

Download and install the NDK

The NDK should be placed in a separate directory, which can be inside the $ANDROID_HOME or in a completely separate path. The extracted directory must be exported as the $ANDROID_NDK_HOME environment variable.

cd "$ANDROID_HOME"  # Or some other directory to place the Android NDK
wget https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip
unzip android-ndk-r20b-linux-x86_64.zip

cd android-ndk-r20b
export ANDROID_NDK_HOME="$PWD"

Docker

Docker is required to build wireguard-go for Android. Follow the installation instructions for your distribution.

Configuring Rust

These steps has to be done after you have installed Rust in the section below:

Install the Rust Android target

Some environment variables must be exported so that some Rust dependencies can be cross-compiled correctly:

export NDK_TOOLCHAIN_DIR="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
export AR_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/aarch64-linux-android-ar"
export AR_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/arm-linux-androideabi-ar"
export AR_x86_64_linux_android="$NDK_TOOLCHAIN_DIR/x86_64-linux-android-ar"
export AR_i686_linux_android="$NDK_TOOLCHAIN_DIR/i686-linux-android-ar"
export CC_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/aarch64-linux-android21-clang"
export CC_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/armv7a-linux-androideabi21-clang"
export CC_x86_64_linux_android="$NDK_TOOLCHAIN_DIR/x86_64-linux-android21-clang"
export CC_i686_linux_android="$NDK_TOOLCHAIN_DIR/i686-linux-android21-clang"
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
Set up cargo to use the correct linker and archiver

This block assumes you installed everything under /opt/android, but you can install it wherever you want as long as the ANDROID_HOME variable is set accordingly.

Add to ~/.cargo/config.toml:

[target.aarch64-linux-android]
ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"
linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang"

[target.armv7-linux-androideabi]
ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang"

[target.x86_64-linux-android]
ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar"
linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang"

[target.i686-linux-android]
ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android-ar"
linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android21-clang"

Signing key for release APKs (optional)

In order to build release APKs, they need to be signed. First, a signing key must be generated and stored in a keystore file. In the example below, the keystore file will be /home/user/app-keys.jks and will contain a key called release.

keytool -genkey -v -keystore /home/user/app-keys.jks -alias release -keyalg RSA -keysize 4096 -validity 10000

Fill in the requested information to generate the key and the keystore file. Suppose the file was protected by a password keystore-password and the key with a password key-password. This information should then be added to the android/keystore.properties file:

keyAlias = release
keyPassword = key-password
storeFile = /home/user/app-keys.jks
storePassword = keystore-password

All platforms

  1. Make sure to use a recent version of bash. The default version in macOS (3.2.57) isn't supported.

  2. Get the latest stable Rust toolchain via rustup.rs.

  3. This can be skipped for Android builds.

    Any Node.js version above 16 and the latest npm version should work. The exact Node.js and NPM versions that we target are specified in package.json in the volta section. Those versions will be used automatically if volta is installed and setup.

    To install Volta on Linux and macOS, run:

    cargo install --git https://github.com/volta-cli/volta
    volta setup
    

    or follow the their instructions: https://github.com/volta-cli/volta.

    Windows

    Install the msi hosted here: https://github.com/volta-cli/volta.

    If installing Node.js manually then the latest version of npm can be installed by running:

    npm install -g npm
    
  4. Install Go (ideally version 1.18) by following the official instructions. Newer versions may work too. Since cgo is being used, make sure to have a C compiler in your path. On Windows mingw's gcc compiler should work. gcc on most Linux distributions should work, and clang for MacOS.

Building and packaging the app

Desktop

The simplest way to build the entire app and generate an installer is to just run the build script. --optimize can be added to enable compiler optimizations. This will take longer to build but will produce a smaller installer and installed binaries:

./build.sh [--optimize]

This should produce an installer exe, pkg or rpm+deb file in the dist/ directory.

Building this requires at least 1GB of memory.

macOS

By default, build.sh produces a pkg for your current architecture only. To build a universal app that works on both Intel and Apple Silicon macs, build with --universal.

Linux ARM64

To cross-compile for ARM64 rather than the current architecture, set the TARGETS environment variable to aarch64-unknown-linux-gnu:

TARGETS="aarch64-unknown-linux-gnu" ./build.sh
ARM64

Due to inability to build the management interface proto files on ARM64 (see this issue), building on ARM64 must be done in 2 stages:

  1. Build management interface proto files on a non-ARM64 platform
  2. Use the built proto files during the main build by setting the MANAGEMENT_INTERFACE_PROTO_BUILD_DIR environment variable to the path the proto files

To build the management interface proto files there is a script (execute it on a non-ARM64 platform):

cd gui/scripts
npm ci
./build-proto.sh

After that copy the files from gui/src/main/management_interface/ and gui/build/src/main/management_interface/ directories into a single directory, and set the value of MANAGEMENT_INTERFACE_PROTO_BUILD_DIR to that directory while running the main build.

Install protobuf. On macOS, this can be done using Homebrew:

brew install protobuf

When all is done run the main build. Assuming that you copied the proto files into /tmp/management_interface_proto directory, the build command will look as follows:

MANAGEMENT_INTERFACE_PROTO_BUILD_DIR=/tmp/management_interface_proto ./build.sh --dev-build

On Linux, you may also have to specify USE_SYSTEM_FPM=true to generate the deb/rpm packages.

If you want to build each component individually, or run in development mode, read the following sections.

Android

Running the build-apk.sh script will build the necessary Rust daemon for all supported ABIs and build the final APK:

./build-apk.sh

You may pass a --dev-build to build the Rust daemon and the UI in debug mode and sign the APK with automatically generated debug keys:

./build-apk.sh --dev-build

If the above fails with an error related to compression, try allowing more memory to the JVM:

echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties
./android/gradlew --stop

Building and running mullvad-daemon on desktop

  1. Firstly, on MacOS and Linux, one should source env.sh to set the default environment variables.

    source env.sh
  2. On Windows, make sure to start bash first (e.g., Git BASH). Then build the C++ libraries:

     ./build-windows-modules.sh
  3. Build the system daemon plus the other Rust tools and programs:

    cargo build
  4. Copy the OpenVPN binaries, and our plugin for it, to the directory we will use as resource directory. If you want to use any other directory, you would need to copy even more files.

    cp dist-assets/binaries/<platform>/openvpn[.exe] dist-assets/
    cp target/debug/*talpid_openvpn_plugin* dist-assets/
  5. On Windows, also copy wintun.dll to the build directory:

    cp dist-assets/binaries/x86_64-pc-windows-msvc/wintun.dll target/debug/
  6. On Windows, the daemon must be run as the SYSTEM user. You can use PsExec to launch an elevated bash instance before starting the daemon in it:

    psexec64 -i -s bash.exe
    
  7. Run the daemon with verbose logging (from the root directory of the project):

    sudo MULLVAD_RESOURCE_DIR="./dist-assets" ./target/debug/mullvad-daemon -vv

    Leave out sudo on Windows. The daemon must run as root since it modifies the firewall and sets up virtual network interfaces etc.

Environment variables controlling the execution

  • TALPID_FIREWALL_DEBUG - Helps debugging the firewall. Does different things depending on platform:

    • Linux: Set to "1" to add packet counters to all firewall rules.
    • macOS: Makes rules log the packets they match to the pflog0 interface.
      • Set to "all" to add logging to all rules.
      • Set to "pass" to add logging to rules allowing packets.
      • Set to "drop" to add logging to rules blocking packets.
  • TALPID_FIREWALL_DONT_SET_SRC_VALID_MARK - Forces the daemon to not set src_valid_mark config on Linux. The kernel config option is set because otherwise strict reverse path filtering may prevent relay traffic from reaching the daemon. If rp_filter is set to 1 on the interface that will be receiving relay traffic, and src_valid_mark is not set to 1, the daemon will not be able to receive relay traffic.

  • TALPID_DNS_MODULE - Allows changing the method that will be used for DNS configuration on Linux. By default this is automatically detected, but you can set it to one of the options below to choose a specific method:

    • "static-file": change the /etc/resolv.conf file directly
    • "resolvconf": use the resolvconf program
    • "systemd": use systemd's resolved service through DBus
    • "network-manager": use NetworkManager service through DBus
  • TALPID_FORCE_USERSPACE_WIREGUARD - Forces the daemon to use the userspace implementation of WireGuard on Linux.

  • TALPID_DISABLE_OFFLINE_MONITOR - Forces the daemon to always assume the host is online.

  • TALPID_NET_CLS_MOUNT_DIR - On Linux, forces the daemon to mount the net_cls controller in the specified directory if it isn't mounted already.

  • MULLVAD_MANAGEMENT_SOCKET_GROUP - On Linux and macOS, this restricts access to the management interface UDS socket to users in the specified group. This means that only users in that group can use the CLI and GUI. By default, everyone has access to the socket.

Dev builds only

  • MULLVAD_API_HOST - Set the hostname to use in API requests. E.g. api.mullvad.net.

  • MULLVAD_API_ADDR - Set the IP address and port to use in API requests. E.g. 10.10.1.2:443.

Setting environment variable

  • On Windows, one can use setx from an elevated shell, like so

    setx TALPID_DISABLE_OFFLINE 1 /m

    For the change to take effect, one must restart the daemon

    sc.exe stop mullvadvpn
    sc.exe start mullvadvpn
  • On Linux, one should edit the systemd unit file via systemctl edit mullvad-daemon.service and edit it like so

    [Service]
    Environment="TALPID_DISABLE_OFFLINE_MONITOR=1"
    

    For the change to take effect, one must restart the daemon

    sudo systemctl restart mullvad-daemon
  • On macOS, one can use launchctl like so

    sudo launchctl setenv TALPID_DISABLE_OFFLINE_MONITOR 1

    For the change to take effect, one must restart the daemon

    launchctl unload -w /Library/LaunchDaemons/net.mullvad.daemon.plist
    launchctl load -w /Library/LaunchDaemons/net.mullvad.daemon.plist

Building and running the desktop Electron GUI app

  1. Go to the gui directory

    cd gui
  2. Install all the JavaScript dependencies by running:

    npm install
  3. Start the GUI in development mode by running:

    npm run develop

If you change any javascript file while the development mode is running it will automatically transpile and reload the file so that the changes are visible almost immediately.

Please note that the GUI needs a running daemon to connect to in order to work. See Building and running mullvad-daemon for instruction on how to do that before starting the GUI.

Supported environment variables

  1. MULLVAD_PATH - Allows changing the path to the folder with the mullvad-problem-report tool when running in development mode. Defaults to: <repo>/target/debug/.
  2. MULLVAD_DISABLE_UPDATE_NOTIFICATION - If set to 1, GUI notification will be disabled when an update is available.

Making a release

When making a real release there are a couple of steps to follow. <VERSION> here will denote the version of the app you are going to release. For example 2018.3-beta1 or 2018.4.

  1. Follow the Install toolchains and dependencies steps if you have not already completed them.

  2. Make sure the CHANGELOG.md is up to date and has all the changes present in this release. Also change the [Unreleased] header into [<VERSION>] - <DATE> and add a new [Unreleased] header at the top. Push this, get it reviewed and merged.

  3. Run ./prepare_release.sh <VERSION>. This will do the following for you:

    1. Check if your repository is in a sane state and the given version has the correct format
    2. Update package.json with the new version and commit that
    3. Add a signed tag to the current commit with the release version in it

    Please verify that the script did the right thing before you push the commit and tag it created.

  4. When building for Windows or macOS, the following environment variables must be set: