113 lines
4.6 KiB
Rust
113 lines
4.6 KiB
Rust
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, sync::Mutex};
|
|
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 tun = Arc::new(Mutex::new(
|
|
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();
|
|
info!("packet: {:?}", packet);
|
|
let dst_addr = Tunn::dst_address(&buf[..len]);
|
|
debug!("dst_addr: {:?}", dst_addr);
|
|
let result = {
|
|
let mut t = tun.lock().await;
|
|
t.decapsulate(dst_addr, &buf[..len], &mut dst)
|
|
};
|
|
|
|
loop {
|
|
let tun = Arc::clone(&tun);
|
|
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);
|
|
let mut t = tun.lock().await;
|
|
t.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");
|
|
let mut t = tun.lock().await;
|
|
sock.send_to(&empty_packet(&mut t), addr).await.unwrap();
|
|
break;
|
|
}
|
|
TunnResult::WriteToTunnelV6(ref _r, _addy) => {
|
|
// These are very spammy
|
|
debug!("WriteToTunnelV6");
|
|
let mut t = tun.lock().await;
|
|
sock.send_to(&empty_packet(&mut t), addr).await.unwrap();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn empty_packet(tun: &mut Tunn) -> [u8; 128] {
|
|
let mut dst = [0; 128];
|
|
tun.encapsulate(&[], &mut dst);
|
|
dst
|
|
}
|