summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-05-24 15:50:37 +0200
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-06-25 17:31:37 +0200
commit7c63a2eed57529f2ac19990f0b529087846a0839 (patch)
tree5bbb7aaad793e6fb2c0016fe905679c578ad80fa
parent3b1246c9a94690687f0bb60ee865797643c53ea1 (diff)
downloadmullvadvpn-7c63a2eed57529f2ac19990f0b529087846a0839.tar.xz
mullvadvpn-7c63a2eed57529f2ac19990f0b529087846a0839.zip
Link statically against libwg
Co-authored-by: David Lönnhager <david.l@mullvad.net>
-rw-r--r--Cargo.lock75
-rw-r--r--README.md6
-rw-r--r--talpid-wireguard/Cargo.toml2
-rw-r--r--wireguard-go-rs/Cargo.toml9
-rw-r--r--wireguard-go-rs/README.md9
-rwxr-xr-xwireguard-go-rs/build-wireguard-go.sh35
-rw-r--r--wireguard-go-rs/build.rs24
-rwxr-xr-xwireguard-go-rs/libwg/build-android.sh2
-rw-r--r--wireguard-go-rs/src/lib.rs4
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",
]
diff --git a/README.md b/README.md
index 3450ad0ba8..8788e3c859 100644
--- a/README.md
+++ b/README.md
@@ -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.