Wireguard POC

This commit is contained in:
durch
2023-06-27 11:45:25 +02:00
parent 0134030341
commit ebfecba933
4 changed files with 256 additions and 14 deletions
Generated
+128 -11
View File
@@ -542,6 +542,29 @@ dependencies = [
"zeroize",
]
[[package]]
name = "boringtun"
version = "0.5.2"
source = "git+https://github.com/durch/boringtun.git#a65d78339157dcedca1dd97de23a4b111f4da0b1"
dependencies = [
"aead",
"base64 0.13.1",
"blake2 0.10.6",
"chacha20poly1305",
"hex",
"hmac 0.12.1",
"ip_network",
"ip_network_table",
"libc",
"nix",
"parking_lot 0.12.1",
"rand_core 0.6.4",
"ring",
"tracing",
"untrusted 0.9.0",
"x25519-dalek 2.0.0-rc.3",
]
[[package]]
name = "bs58"
version = "0.4.0"
@@ -1308,6 +1331,33 @@ dependencies = [
"zeroize",
]
[[package]]
name = "curve25519-dalek"
version = "4.0.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"fiat-crypto",
"platforms",
"rustc_version 0.4.0",
"subtle 2.4.1",
"zeroize",
]
[[package]]
name = "curve25519-dalek-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
]
[[package]]
name = "cw-controllers"
version = "0.13.4"
@@ -1603,7 +1653,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"ed25519",
"rand 0.7.3",
"serde",
@@ -1618,7 +1668,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6"
dependencies = [
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"hashbrown 0.12.3",
"hex",
"rand_core 0.6.4",
@@ -1832,6 +1882,12 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "fiat-crypto"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
[[package]]
name = "figment"
version = "0.10.8"
@@ -2763,6 +2819,28 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "ip_network"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1"
[[package]]
name = "ip_network_table"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0"
dependencies = [
"ip_network",
"ip_network_table-deps-treebitmap",
]
[[package]]
name = "ip_network_table-deps-treebitmap"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d"
[[package]]
name = "ipnet"
version = "2.7.2"
@@ -3226,6 +3304,18 @@ dependencies = [
"tempfile",
]
[[package]]
name = "nix"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
dependencies = [
"autocfg 1.1.0",
"bitflags",
"cfg-if",
"libc",
]
[[package]]
name = "no-std-compat"
version = "0.4.1"
@@ -3762,7 +3852,7 @@ dependencies = [
"serde_bytes",
"subtle-encoding",
"thiserror",
"x25519-dalek",
"x25519-dalek 1.1.1",
"zeroize",
]
@@ -3804,7 +3894,9 @@ dependencies = [
"anyhow",
"async-trait",
"atty",
"base64 0.21.2",
"bip39",
"boringtun",
"bs58",
"clap 4.2.7",
"colored",
@@ -3844,6 +3936,7 @@ dependencies = [
"tokio-tungstenite 0.14.0",
"tokio-util",
"url",
"x25519-dalek 2.0.0-rc.3",
"zeroize",
]
@@ -4184,7 +4277,7 @@ dependencies = [
"chacha20",
"chacha20poly1305",
"criterion",
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"fastrand",
"getrandom 0.2.10",
"log",
@@ -5164,6 +5257,12 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "platforms"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
[[package]]
name = "plotters"
version = "0.3.4"
@@ -5795,7 +5894,7 @@ dependencies = [
"libc",
"once_cell",
"spin 0.5.2",
"untrusted",
"untrusted 0.7.1",
"web-sys",
"winapi",
]
@@ -6119,7 +6218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]
@@ -6129,7 +6228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]
@@ -6500,7 +6599,7 @@ dependencies = [
"bs58",
"byteorder",
"chacha",
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"digest 0.9.0",
"hkdf 0.11.0",
"hmac 0.11.0",
@@ -7691,6 +7790,12 @@ 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"
[[package]]
name = "unwind_safe"
version = "0.1.0"
@@ -7937,7 +8042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]
@@ -7947,7 +8052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]
@@ -8208,12 +8313,24 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
dependencies = [
"curve25519-dalek",
"curve25519-dalek 3.2.0",
"rand_core 0.5.1",
"serde",
"zeroize",
]
[[package]]
name = "x25519-dalek"
version = "2.0.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7fae07da688e17059d5886712c933bb0520f15eff2e09cfa18e30968f4e63a"
dependencies = [
"curve25519-dalek 4.0.0-rc.3",
"rand_core 0.6.4",
"serde",
"zeroize",
]
[[package]]
name = "yansi"
version = "0.5.1"
+24 -3
View File
@@ -34,16 +34,35 @@ pretty_env_logger = "0.4"
rand = "0.7"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sqlx = { version = "0.5", features = [ "runtime-tokio-rustls", "sqlite", "macros", "migrate", ] }
sqlx = { version = "0.5", features = [
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
] }
subtle-encoding = { version = "0.5", features = ["bech32-preview"] }
thiserror = "1"
tokio = { version = "1.24.1", features = [ "rt-multi-thread", "net", "signal", "fs", ] }
tokio = { version = "1.24.1", features = [
"rt-multi-thread",
"net",
"signal",
"fs",
] }
tokio-stream = { version = "0.1.11", features = ["fs"] }
tokio-tungstenite = "0.14"
tokio-util = { version = "0.7.4", features = ["codec"] }
url = { version = "2.2", features = ["serde"] }
zeroize = { workspace = true }
# wireguard
# Forked it to be able to bump x25519-dalek to rc.3
boringtun = { git = "https://github.com/durch/boringtun.git" }
base64 = "0.21"
x25519-dalek = { version = "=2.0.0-rc.3", features = [
"reusable_secrets",
"static_secrets",
] }
# internal
nym-api-requests = { path = "../nym-api/nym-api-requests" }
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
@@ -60,7 +79,9 @@ nym-sphinx = { path = "../common/nymsphinx" }
nym-statistics-common = { path = "../common/statistics" }
nym-task = { path = "../common/task" }
nym-types = { path = "../common/types" }
nym-validator-client = { path = "../common/client-libs/validator-client", features = [ "nyxd-client" ] }
nym-validator-client = { path = "../common/client-libs/validator-client", features = [
"nyxd-client",
] }
[build-dependencies]
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
+4
View File
@@ -10,6 +10,7 @@ use crate::node::client_handling::websocket::connection_handler::coconut::Coconu
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
use crate::node::statistics::collector::GatewayStatisticsCollector;
use crate::node::storage::Storage;
use crate::node::wireguard::wireguard;
use log::*;
use nym_bin_common::output_format::OutputFormat;
use nym_crypto::asymmetric::{encryption, identity};
@@ -28,6 +29,7 @@ pub(crate) mod client_handling;
pub(crate) mod mixnet_handling;
pub(crate) mod statistics;
pub(crate) mod storage;
pub (crate) mod wireguard;
/// Wire up and create Gateway instance
pub(crate) async fn create_gateway(config: Config) -> Gateway<PersistentStorage> {
@@ -297,6 +299,8 @@ impl<St> Gateway<St> {
Arc::new(coconut_verifier),
);
tokio::spawn(wireguard());
info!("Finished nym gateway startup procedure - it should now be able to receive mix and client traffic!");
self.wait_for_interrupt(shutdown).await
+100
View File
@@ -0,0 +1,100 @@
use std::sync::Arc;
use base64::engine::general_purpose;
use base64::Engine as _;
use boringtun::noise::{rate_limiter::RateLimiter, Tunn, TunnResult};
use log::{debug, error, info};
use tokio::net::UdpSocket;
use x25519_dalek::{PublicKey, StaticSecret};
pub async fn wireguard() {
let wg_address = "127.0.0.1:51820";
let sock = UdpSocket::bind(wg_address).await.unwrap();
info!("wg listening on {wg_address}");
// Secret key ofthe gateway, we'll need a way to generate this from the IdentityKey, might be enough to do some base58 -> base64 conversion
let secret_bytes: [u8; 32] = general_purpose::STANDARD
.decode("MBbPChSpmC/FXwIWNROltjd6cOywC81GNEgH9jMOOFk=")
.unwrap()
.try_into()
.unwrap();
// Hardcoded peer public key, we'll need a way to register those, private key for that one is `aMUcuAgTiFCHQ/fHqEQRvpLWBxh8sKA7f7lSyWymrGE=`
// Wireguard configuration that works with this setup is below, this needs to be put into the wireguard client of choice.
// Working in this case means that they go through the handshake, and client
// starts sending data packets to the gateway.
//
// [Interface]
// PrivateKey = aMUcuAgTiFCHQ/fHqEQRvpLWBxh8sKA7f7lSyWymrGE=
// Address = 10.8.0.0/24
// DNS = 1.1.1.1
//
// [Peer]
// PublicKey = y6/iGYraJjON6pw9fcBa5vLRbGsQqprFLfWKyJQnlWs=
// AllowedIPs = 0.0.0.0/0
// Endpoint = 127.0.0.1:51820
let peer_public_bytes: [u8; 32] = general_purpose::STANDARD
.decode("JpJzoO1DY6HZbn2h33GQJg0GLnxfdpOeV9C/rvdZ5Cs=")
.unwrap()
.try_into()
.unwrap();
let peer_public = PublicKey::from(peer_public_bytes);
let secret = StaticSecret::try_from(secret_bytes).unwrap();
let public = PublicKey::from(&secret);
info!(
"wg public key: {}",
general_purpose::STANDARD.encode(public)
);
// Rate limiter is global for the gateway
let rate_limiter = Arc::new(RateLimiter::new(&public, 1024));
let mut tun = Tunn::new(secret, peer_public, None, None, 0, Some(rate_limiter)).unwrap();
// Here we have a pretty suboptimal implementation of the UDP communication, for one client
loop {
let mut buf = [0; 1024];
let mut dst = vec![0; 1024];
let (len, addr) = sock.recv_from(&mut buf).await.unwrap();
let packet = Tunn::parse_incoming_packet(&buf[..len]).unwrap();
debug!("packet: {:?}", packet);
let dst_addr = Tunn::dst_address(&buf[..len]);
debug!("dst_addr: {:?}", dst_addr);
let result = tun.decapsulate(dst_addr, &buf[..len], &mut dst);
loop {
debug!("result: {:?}", result);
match result {
TunnResult::Done => break,
// We'll get here during the handshake process, if the reponse is WriteToNetwork we should call decapsulate again with an
// empty datagram until we get a Done response
TunnResult::WriteToNetwork(p) => {
let len = sock.send_to(p, addr).await.unwrap();
debug!("{} bytes sent to {}", len, addr);
tun.decapsulate(dst_addr, &[], p);
break;
}
TunnResult::Err(e) => {
error!("error: {:?}", e);
break;
}
// We've recieved some DataPackets we need to forward and send response back to the initiating client
// if no data packets are available we should send an empty packet as an ack.
// For now this just logs that it received the packet, and send and ack back to the client.
TunnResult::WriteToTunnelV4(ref _r, _addy) => {
// These are very spammy
debug!("WriteToTunnelV4");
sock.send_to(&empty_packet(&mut tun), addr).await.unwrap();
}
TunnResult::WriteToTunnelV6(ref _r, _addy) => {
// These are very spammy
debug!("WriteToTunnelV6");
sock.send_to(&empty_packet(&mut tun), addr).await.unwrap();
}
}
}
}
}
fn empty_packet(tun: &mut Tunn) -> [u8; 128] {
let mut dst = [0; 128];
tun.encapsulate(&[], &mut dst);
dst
}