From 653c314409c017e47f3338552e7998196a3b6de9 Mon Sep 17 00:00:00 2001 From: George Hopkins Date: Mon, 2 Oct 2023 16:24:37 +0200 Subject: [PATCH 1/3] Support pre-shared key --- Cargo.toml | 1 + src/config.rs | 24 ++++++++++++++++++++++++ src/wg.rs | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6ec0b5e..4dee3d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ async-trait = "0.1" priority-queue = "1.3.0" smoltcp = { version = "0.8.2", default-features = false, features = ["std", "log", "medium-ip", "proto-ipv4", "proto-ipv6", "socket-udp", "socket-tcp"] } bytes = "1" +base64 = "0.21" # forward boringtuns tracing events to log tracing = { version = "0.1", default-features = false, features = ["log"] } diff --git a/src/config.rs b/src/config.rs index 93d9129..54839cf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,6 +6,7 @@ use std::net::{IpAddr, SocketAddr, ToSocketAddrs}; use std::sync::Arc; use anyhow::Context; +use base64::prelude::{Engine as _, BASE64_STANDARD}; pub use boringtun::crypto::{X25519PublicKey, X25519SecretKey}; const DEFAULT_PORT_FORWARD_SOURCE: &str = "127.0.0.1"; @@ -17,6 +18,7 @@ pub struct Config { pub remote_port_forwards: Vec, pub private_key: Arc, pub endpoint_public_key: Arc, + pub endpoint_preshared_key: Option<[u8; 32]>, pub endpoint_addr: SocketAddr, pub endpoint_bind_addr: SocketAddr, pub source_peer_ip: IpAddr, @@ -73,6 +75,12 @@ impl Config { .long("endpoint-public-key") .env("ONETUN_ENDPOINT_PUBLIC_KEY") .help("The public key of the WireGuard endpoint (remote)."), + Arg::with_name("endpoint-preshared-key") + .required(false) + .takes_value(true) + .long("endpoint-preshared-key") + .env("ONETUN_ENDPOINT_PRESHARED_KEY") + .help("The pre-shared key of the WireGuard endpoint (remote)."), Arg::with_name("endpoint-addr") .required(true) .takes_value(true) @@ -264,6 +272,9 @@ impl Config { parse_public_key(matches.value_of("endpoint-public-key")) .with_context(|| "Invalid endpoint public key")?, ), + endpoint_preshared_key: parse_preshared_key( + matches.value_of("endpoint-preshared-key"), + )?, endpoint_addr, endpoint_bind_addr, source_peer_ip, @@ -304,6 +315,19 @@ fn parse_public_key(s: Option<&str>) -> anyhow::Result { .with_context(|| "Invalid public key") } +fn parse_preshared_key(s: Option<&str>) -> anyhow::Result> { + if let Some(s) = s { + let psk = BASE64_STANDARD + .decode(s) + .with_context(|| "Invalid pre-shared key")?; + Ok(Some(psk.try_into().map_err(|_| { + anyhow::anyhow!("Unsupported pre-shared key") + })?)) + } else { + Ok(None) + } +} + fn parse_keep_alive(s: Option<&str>) -> anyhow::Result> { if let Some(s) = s { let parsed: u16 = s.parse().with_context(|| { diff --git a/src/wg.rs b/src/wg.rs index 0646606..0f2278a 100644 --- a/src/wg.rs +++ b/src/wg.rs @@ -221,7 +221,7 @@ impl WireGuardTunnel { Tunn::new( config.private_key.clone(), config.endpoint_public_key.clone(), - None, + config.endpoint_preshared_key, config.keepalive_seconds, 0, None, From 6f143280d1712ef57cff29402ab1d436d7b2d395 Mon Sep 17 00:00:00 2001 From: Aram Peres <6775216+aramperes@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:07:37 -0400 Subject: [PATCH 2/3] Pin older version of base64 for now --- Cargo.lock | 1 + Cargo.toml | 2 +- src/config.rs | 5 +---- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8aa0ac..3578048 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,6 +445,7 @@ dependencies = [ "anyhow", "async-recursion", "async-trait", + "base64", "boringtun", "bytes", "clap", diff --git a/Cargo.toml b/Cargo.toml index 4dee3d7..e9054eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ async-trait = "0.1" priority-queue = "1.3.0" smoltcp = { version = "0.8.2", default-features = false, features = ["std", "log", "medium-ip", "proto-ipv4", "proto-ipv6", "socket-udp", "socket-tcp"] } bytes = "1" -base64 = "0.21" +base64 = "0.13" # forward boringtuns tracing events to log tracing = { version = "0.1", default-features = false, features = ["log"] } diff --git a/src/config.rs b/src/config.rs index 54839cf..576923a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,7 +6,6 @@ use std::net::{IpAddr, SocketAddr, ToSocketAddrs}; use std::sync::Arc; use anyhow::Context; -use base64::prelude::{Engine as _, BASE64_STANDARD}; pub use boringtun::crypto::{X25519PublicKey, X25519SecretKey}; const DEFAULT_PORT_FORWARD_SOURCE: &str = "127.0.0.1"; @@ -317,9 +316,7 @@ fn parse_public_key(s: Option<&str>) -> anyhow::Result { fn parse_preshared_key(s: Option<&str>) -> anyhow::Result> { if let Some(s) = s { - let psk = BASE64_STANDARD - .decode(s) - .with_context(|| "Invalid pre-shared key")?; + let psk = base64::decode(s).with_context(|| "Invalid pre-shared key")?; Ok(Some(psk.try_into().map_err(|_| { anyhow::anyhow!("Unsupported pre-shared key") })?)) From 1333ea8a7cfb384b6676b1d3b747d6318c1b7aad Mon Sep 17 00:00:00 2001 From: Aram Peres <6775216+aramperes@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:21:32 -0400 Subject: [PATCH 3/3] Rename option to --preshared-key and add to README --- README.md | 7 +++++++ src/config.rs | 14 ++++++-------- src/wg.rs | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index eab9f07..077034f 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,13 @@ You can bind to a static address instead using `--endpoint-bind-addr`: onetun --endpoint-bind-addr 0.0.0.0:51820 --endpoint-addr 140.30.3.182:51820 [...] ``` +The security of the WireGuard connection can be further enhanced with a **pre-shared key** (PSK). You can generate such a key with the `wg genpsk` command, and provide it using `--preshared-key`. +The peer must also have this key configured using the `PresharedKey` option. + +```shell +onetun --preshared-key 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' [...] +``` + ## Architecture **In short:** onetun uses [smoltcp's](https://github.com/smoltcp-rs/smoltcp) TCP/IP and UDP stack to generate IP packets diff --git a/src/config.rs b/src/config.rs index 576923a..467cf01 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,7 +17,7 @@ pub struct Config { pub remote_port_forwards: Vec, pub private_key: Arc, pub endpoint_public_key: Arc, - pub endpoint_preshared_key: Option<[u8; 32]>, + pub preshared_key: Option<[u8; 32]>, pub endpoint_addr: SocketAddr, pub endpoint_bind_addr: SocketAddr, pub source_peer_ip: IpAddr, @@ -74,12 +74,12 @@ impl Config { .long("endpoint-public-key") .env("ONETUN_ENDPOINT_PUBLIC_KEY") .help("The public key of the WireGuard endpoint (remote)."), - Arg::with_name("endpoint-preshared-key") + Arg::with_name("preshared-key") .required(false) .takes_value(true) - .long("endpoint-preshared-key") - .env("ONETUN_ENDPOINT_PRESHARED_KEY") - .help("The pre-shared key of the WireGuard endpoint (remote)."), + .long("preshared-key") + .env("ONETUN_PRESHARED_KEY") + .help("The pre-shared key (PSK) as configured with the peer."), Arg::with_name("endpoint-addr") .required(true) .takes_value(true) @@ -271,9 +271,7 @@ impl Config { parse_public_key(matches.value_of("endpoint-public-key")) .with_context(|| "Invalid endpoint public key")?, ), - endpoint_preshared_key: parse_preshared_key( - matches.value_of("endpoint-preshared-key"), - )?, + preshared_key: parse_preshared_key(matches.value_of("preshared-key"))?, endpoint_addr, endpoint_bind_addr, source_peer_ip, diff --git a/src/wg.rs b/src/wg.rs index 0f2278a..14efa23 100644 --- a/src/wg.rs +++ b/src/wg.rs @@ -221,7 +221,7 @@ impl WireGuardTunnel { Tunn::new( config.private_key.clone(), config.endpoint_public_key.clone(), - config.endpoint_preshared_key, + config.preshared_key, config.keepalive_seconds, 0, None,