diff options
| author | Markus Pettersson <markus.pettersson@mullvad.net> | 2024-05-24 15:50:37 +0200 |
|---|---|---|
| committer | Markus Pettersson <markus.pettersson@mullvad.net> | 2024-06-25 17:31:37 +0200 |
| commit | 7c63a2eed57529f2ac19990f0b529087846a0839 (patch) | |
| tree | 5bbb7aaad793e6fb2c0016fe905679c578ad80fa | |
| parent | 3b1246c9a94690687f0bb60ee865797643c53ea1 (diff) | |
| download | mullvadvpn-7c63a2eed57529f2ac19990f0b529087846a0839.tar.xz mullvadvpn-7c63a2eed57529f2ac19990f0b529087846a0839.zip | |
Link statically against libwg
Co-authored-by: David Lönnhager <david.l@mullvad.net>
| -rw-r--r-- | Cargo.lock | 75 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | talpid-wireguard/Cargo.toml | 2 | ||||
| -rw-r--r-- | wireguard-go-rs/Cargo.toml | 9 | ||||
| -rw-r--r-- | wireguard-go-rs/README.md | 9 | ||||
| -rwxr-xr-x | wireguard-go-rs/build-wireguard-go.sh | 35 | ||||
| -rw-r--r-- | wireguard-go-rs/build.rs | 24 | ||||
| -rwxr-xr-x | wireguard-go-rs/libwg/build-android.sh | 2 | ||||
| -rw-r--r-- | wireguard-go-rs/src/lib.rs | 4 |
9 files changed, 82 insertions, 84 deletions
diff --git a/Cargo.lock b/Cargo.lock index 8709388967..898d998491 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1932,7 +1932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -2026,21 +2026,30 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maybenot" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7fe205734d700937dabf0b8687e290f8574fac996f8a9d04bd7a62d7c2c1dad" +checksum = "e308ea251c8fe965732a020db1aa182a1df0cfb551da0d422bf83016d0f10153" dependencies = [ "byteorder", "hex", "libflate", "rand 0.8.5", "rand_distr", - "ring 0.16.20", + "ring", "serde", "simple-error", ] [[package]] +name = "maybenot-ffi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a95dd874046b87f98b3a54e6beed8a63db6354088efd0ae7dc23c0f23931ce" +dependencies = [ + "maybenot", +] + +[[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3279,21 +3288,6 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" @@ -3302,8 +3296,8 @@ dependencies = [ "cfg-if", "getrandom 0.2.14", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] @@ -3322,7 +3316,7 @@ dependencies = [ "p384", "pkcs8", "rand_core 0.6.4", - "ring 0.17.8", + "ring", "signature", ] @@ -3388,7 +3382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-webpki", "sct", ] @@ -3408,8 +3402,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3457,8 +3451,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3592,7 +3586,7 @@ dependencies = [ "serde_urlencoded", "shadowsocks-crypto", "socket2", - "spin 0.9.8", + "spin", "thiserror", "tokio", "tokio-tfo", @@ -3661,7 +3655,7 @@ dependencies = [ "serde", "shadowsocks", "socket2", - "spin 0.9.8", + "spin", "thiserror", "tokio", "windows-sys 0.52.0", @@ -3750,12 +3744,6 @@ dependencies = [ [[package]] name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" @@ -4585,12 +4573,6 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" @@ -4724,16 +4706,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5084,6 +5056,7 @@ name = "wireguard-go-rs" version = "0.0.0" dependencies = [ "log", + "maybenot-ffi", "thiserror", "zeroize", ] @@ -91,6 +91,12 @@ cd mullvadvpn-app git submodule update --init ``` +On Android, Linux and macOS you also want to checkout the wireguard-go submodule recursively: +```bash +git submodule update --init --recursive --depth=1 wireguard-go-rs +``` +Further details on why this is necessary can be found in the [wireguard-go-rs crate](./wireguard-go-rs/README.md). + We sign every commit on the `main` 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]. diff --git a/talpid-wireguard/Cargo.toml b/talpid-wireguard/Cargo.toml index e7db72cac6..1b103f9d1d 100644 --- a/talpid-wireguard/Cargo.toml +++ b/talpid-wireguard/Cargo.toml @@ -57,7 +57,7 @@ talpid-dbus = { path = "../talpid-dbus" } bitflags = "1.2" talpid-windows = { path = "../talpid-windows" } widestring = "1.0" -maybenot = "1.0" +maybenot = "1.1.2" # TODO: Figure out which features are needed and which are not [target.'cfg(windows)'.dependencies.windows-sys] diff --git a/wireguard-go-rs/Cargo.toml b/wireguard-go-rs/Cargo.toml index 3725787bf6..9b09df4f75 100644 --- a/wireguard-go-rs/Cargo.toml +++ b/wireguard-go-rs/Cargo.toml @@ -4,7 +4,14 @@ description = "Rust bindings to wireguard-go with DAITA support" edition = "2021" license.workspace = true -[dependencies] +[target.'cfg(unix)'.dependencies] thiserror.workspace = true log.workspace = true zeroize = "1.8.1" + +[target.'cfg(target_os = "linux")'.dependencies] +# The app does not depend on maybenot-ffi itself, but adds it as a dependency to expose FFI symbols to wireguard-go. +# This is done, instead of using the makefile in wireguard-go to build maybenot-ffi into its archive, to prevent +# name clashes induced by link-time optimization. +# NOTE: the version of maybenot-ffi below must be the same as the version checked into the wireguard-go submodule +maybenot-ffi = "1.0.0" diff --git a/wireguard-go-rs/README.md b/wireguard-go-rs/README.md index 24a08fa54b..948c1d0390 100644 --- a/wireguard-go-rs/README.md +++ b/wireguard-go-rs/README.md @@ -1,10 +1,11 @@ # `wireguard-go-rs` -This crate wraps `libwg`, which in turn wraps [Mullvad VPN's fork of wireguard-go](https://github.com/mullvad/wireguard-go) which extends `wireguard-go` with [DAITA](https://mullvad.net/en/blog/introducing-defense-against-ai-guided-traffic-analysis-daita). +This crate is a Rust-friendly wrapper around `wireguard-go`. +It wraps `libwg`, which in turn wraps [Mullvad VPN's fork of wireguard-go](https://github.com/mullvad/wireguard-go) that extends `wireguard-go` with [DAITA](https://mullvad.net/en/blog/introducing-defense-against-ai-guided-traffic-analysis-daita). ## Known limitation -To extend `wireguard-go` with DAITA capabilities, it statically links against [maybenot](https://github.com/maybenot-io/maybenot/), which at the time of writing will cause issues if it in turn is statically linked from another Rust crate: https://github.com/rust-lang/rust/issues/104707. -As such, `libwg` is built as a shared object which you have to link to dynamically. -To get rid of this limitation, you could compile `wireguard-go` without DAITA support. See [build-wireguard-go.sh](./build-wireguard-go.sh) for details. +To extend `wireguard-go` with DAITA capabilities, `wireguard-go` links against [maybenot](https://github.com/maybenot-io/maybenot/). This is done statically, which at the time of writing will cause issues if `wireguard-go` in turn is statically linked from another Rust crate: https://github.com/rust-lang/rust/issues/104707. +As such `libwg` is built as a shared object which you can link to dynamically, which circumvents this issue. +To get rid of this limitation, you can compile `wireguard-go` without DAITA support. See [build-wireguard-go.sh](./build-wireguard-go.sh) for details on how to do that. ## Upgrading `wireguard-go` Upgrading `wireguard-go` involves updating the git submodule found in `libwg/wireguard-go`. This module uses [Mullvad VPN's fork of wireguard-go](https://github.com/mullvad/wireguard-go). diff --git a/wireguard-go-rs/build-wireguard-go.sh b/wireguard-go-rs/build-wireguard-go.sh index e270fb8219..35bb9413f2 100755 --- a/wireguard-go-rs/build-wireguard-go.sh +++ b/wireguard-go-rs/build-wireguard-go.sh @@ -1,22 +1,30 @@ #!/usr/bin/env bash - -# This script is used to build wireguard-go libraries for all the platforms. # -# If "DAITA" support should be enabled, pass the `--daita` flag when invoking this script. +# This script is used to build libwg (wireguard-go as an FFI-friendly library) for different platforms. +# +# Supported arguments: +# * --android +# If libwg should be built for an Android target. +# * --daita +# Build libwg with "DAITA" support. +# set -eu +# If the target OS is Android. +ANDROID="false" # If Wireguard-go should be built with DAITA-support. DAITA="false" -# If the target OS is Adnroid. -ANDROID="false" + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BUILD_DIR="$SCRIPT_DIR/../build" while [[ "$#" -gt 0 ]]; do case $1 in --android) ANDROID="true";; --daita) DAITA="true";; *) - log_error "Unknown parameter: $1" + echo "Unknown parameter: $1" exit 1 ;; esac @@ -45,7 +53,6 @@ function unix_target_triple { function build_unix { - # TODO: consider using `log_header` here echo "Building wireguard-go for $1" # Flags for cross compiling @@ -79,16 +86,16 @@ function build_unix { fi - # Build wiregaurd-go as a library + # Build wireguard-go as a library + mkdir -p "$BUILD_DIR/lib/$TARGET" pushd libwg + if [[ "$DAITA" == "true" ]]; then - pushd wireguard-go - make libmaybenot.a LIBDEST="$OUT_DIR" - popd - go build -v --tags daita -o "$OUT_DIR"/libwg.a -buildmode c-archive + go build -v --tags daita -o "$BUILD_DIR/lib/$TARGET"/libwg.a -buildmode c-archive else - go build -v -o "$OUT_DIR"/libwg.a -buildmode c-archive + go build -v -o "$BUILD_DIR/lib/$TARGET"/libwg.a -buildmode c-archive fi + popd } @@ -107,7 +114,7 @@ function build_wireguard_go { local platform platform="$(uname -s)"; case "$platform" in - Linux*|Darwin*) build_unix "${1:-$(unix_target_triple)}";; + Linux*|Darwin*) build_unix "${TARGET:-$(unix_target_triple)}";; *) echo "Unsupported platform" return 1 diff --git a/wireguard-go-rs/build.rs b/wireguard-go-rs/build.rs index 9986e9778c..b82fa0eb5f 100644 --- a/wireguard-go-rs/build.rs +++ b/wireguard-go-rs/build.rs @@ -3,7 +3,7 @@ use std::{env, path::PathBuf}; fn main() { let out_dir = env::var("OUT_DIR").expect("Missing OUT_DIR"); - eprintln!("OUT_DIR: {out_dir}"); + // Add DAITA as a conditional configuration println!("cargo::rustc-check-cfg=cfg(daita)"); @@ -13,7 +13,7 @@ fn main() { match target_os.as_str() { "linux" => { - // Enable DAITA & Tell rustc to link libmaybenot + // Enable DAITA println!(r#"cargo::rustc-cfg=daita"#); // Tell the build script to build wireguard-go with DAITA support cmd.arg("--daita"); @@ -36,19 +36,21 @@ fn main() { panic!(); } - if target_os == "android" { - // NOTE: Go programs does not support being statically linked on android - // so we need to dynamically link to libwg - println!("cargo::rustc-link-lib=wg"); - declare_libs_dir("../build/lib"); - } else { - // other platforms can statically link to libwg just fine - // TODO: consider doing dynamic linking everywhere, to keep things simpler + if target_os.as_str() != "android" { println!("cargo::rustc-link-lib=static=wg"); - println!("cargo::rustc-link-search={out_dir}"); + } else { + // NOTE: Link dynamically to libwg on Android, as go cannot produce archives + println!("cargo::rustc-link-lib=dylib=wg"); } + declare_libs_dir("../build/lib"); println!("cargo::rerun-if-changed=libwg"); + + // Add `OUT_DIR` to the library search path to facilitate linking of libwg for debug artifacts, + // such as test binaries. + if cfg!(debug_assertions) { + println!("cargo::rustc-link-search={out_dir}"); + } } /// Tell linker to check `base`/$TARGET for shared libraries. diff --git a/wireguard-go-rs/libwg/build-android.sh b/wireguard-go-rs/libwg/build-android.sh index 750438c503..0c2336185a 100755 --- a/wireguard-go-rs/libwg/build-android.sh +++ b/wireguard-go-rs/libwg/build-android.sh @@ -57,8 +57,6 @@ for arch in ${ARCHITECTURES:-armv7 aarch64 x86_64 i686}; do # Set permissions so that the build server can clean the outputs afterwards chmod 777 "$STRIPPED_LIB_PATH" - - rm -rf build done # ensure `git clean -fd` does not require root permissions diff --git a/wireguard-go-rs/src/lib.rs b/wireguard-go-rs/src/lib.rs index 0251899754..b5b4000a80 100644 --- a/wireguard-go-rs/src/lib.rs +++ b/wireguard-go-rs/src/lib.rs @@ -26,6 +26,10 @@ pub type LoggingContext = u64; pub type LoggingCallback = unsafe extern "system" fn(level: WgLogLevel, msg: *const c_char, context: LoggingContext); +// Make symbols from maybenot-ffi visible to wireguard-go +#[cfg(daita)] +use maybenot_ffi as _; + /// A wireguard-go tunnel pub struct Tunnel { /// wireguard-go handle to the tunnel. |
