From f3976be8527c6c601552de25c07c24d899e9f541 Mon Sep 17 00:00:00 2001 From: Aram Peres Date: Sun, 10 Oct 2021 20:49:40 -0400 Subject: [PATCH] WIP --- Cargo.lock | 86 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + src/main.rs | 109 ++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 172 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48b7712..328c8a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,6 +277,15 @@ dependencies = [ "quick-error", ] +[[package]] +name = "hwaddr" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e414433a9e4338f4e87fa29d0670c883a5e73e7955c45f4a49130c0aa992c85b" +dependencies = [ + "phf", +] + [[package]] name = "instant" version = "0.1.11" @@ -367,6 +376,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "managed" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577" + [[package]] name = "memchr" version = "2.4.1" @@ -425,7 +440,21 @@ dependencies = [ "boringtun", "clap", "log", + "packet", "pretty_env_logger", + "smoltcp", +] + +[[package]] +name = "packet" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c136c7ad0619ed4f88894aecf66ad86c80683e7b5d707996e6a3a7e0e3916944" +dependencies = [ + "bitflags", + "byteorder", + "hwaddr", + "thiserror", ] [[package]] @@ -453,6 +482,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + [[package]] name = "pretty_env_logger" version = "0.3.1" @@ -566,6 +613,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + [[package]] name = "slog" version = "2.7.0" @@ -591,6 +644,19 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +[[package]] +name = "smoltcp" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3" +dependencies = [ + "bitflags", + "byteorder", + "libc", + "log", + "managed", +] + [[package]] name = "spin" version = "0.5.2" @@ -643,6 +709,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.3" diff --git a/Cargo.toml b/Cargo.toml index 3e126c1..6753127 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,5 @@ clap = { version = "2.33", default-features = false, features = ["suggestions"] log = "0.4" pretty_env_logger = "0.3" anyhow = "1" +smoltcp = "0.7.5" +packet = "0.1.4" diff --git a/src/main.rs b/src/main.rs index 64783ef..db74fe4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate log; -use std::net::{IpAddr, SocketAddr, UdpSocket}; +use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Barrier}; use std::thread; @@ -12,6 +12,9 @@ use boringtun::crypto::{X25519PublicKey, X25519SecretKey}; use boringtun::device::peer::Peer; use boringtun::noise::{Tunn, TunnResult}; use clap::{App, Arg}; +use packet::ip::Protocol; +use packet::Builder; +use smoltcp::wire::Ipv4Packet; use crate::config::Config; @@ -46,7 +49,8 @@ fn main() -> anyhow::Result<()> { let endpoint_addr = config.endpoint_addr; - let peer_ip = config.source_peer_ip; + let source_peer_addr = SocketAddr::new(config.source_peer_ip, 1234); + let destination_addr = config.dest_addr; let close = Arc::new(AtomicBool::new(false)); @@ -74,23 +78,15 @@ fn main() -> anyhow::Result<()> { } }; - debug!("Got packet from endpoint sock: {} bytes", n); - - match peer.decapsulate(None, &recv_buf[..n], &mut send_buf) { + let data = &recv_buf[..n]; + match peer.decapsulate(None, data, &mut send_buf) { TunnResult::WriteToNetwork(packet) => { - send_mocked_packet(packet, endpoint_sock.clone(), endpoint_addr, peer_ip) - .unwrap(); + send_packet(packet, endpoint_sock.clone(), endpoint_addr).unwrap(); loop { let mut send_buf = [0u8; MAX_PACKET]; match peer.decapsulate(None, &[], &mut send_buf) { TunnResult::WriteToNetwork(packet) => { - send_mocked_packet( - packet, - endpoint_sock.clone(), - endpoint_addr, - peer_ip, - ) - .unwrap(); + send_packet(packet, endpoint_sock.clone(), endpoint_addr).unwrap(); } _ => { break; @@ -130,14 +126,25 @@ fn main() -> anyhow::Result<()> { } }; - debug!("Got packet from source sock: {} bytes", n); + let data = &recv_buf[..n]; - match peer.encapsulate(&recv_buf[..n], &mut send_buf) { + // TODO: Support TCP + let ip_packet = + wrap_data_packet(Protocol::Udp, data, source_peer_addr, destination_addr) + .expect("Failed to wrap data packet"); + + debug!("Crafted IP packet: {:#?}", ip_packet); + + match peer.encapsulate(ip_packet.as_slice(), &mut send_buf) { TunnResult::WriteToNetwork(packet) => { - send_mocked_packet(packet, endpoint_sock.clone(), endpoint_addr, peer_ip) - .unwrap(); + send_packet(packet, endpoint_sock.clone(), endpoint_addr).unwrap(); + } + TunnResult::Err(e) => { + error!("Failed to encapsulate: {:?}", e); + } + other => { + error!("Unexpected TunnResult during encapsulation: {:?}", other); } - _ => {} } })); } @@ -156,8 +163,7 @@ fn main() -> anyhow::Result<()> { let mut send_buf = [0u8; MAX_PACKET]; match peer.update_timers(&mut send_buf) { TunnResult::WriteToNetwork(packet) => { - send_mocked_packet(packet, endpoint_sock.clone(), endpoint_addr, peer_ip) - .unwrap(); + send_packet(packet, endpoint_sock.clone(), endpoint_addr).unwrap(); } _ => {} } @@ -178,14 +184,67 @@ fn main() -> anyhow::Result<()> { Ok(()) } -fn send_mocked_packet( +// wraps a UDP packet with an IP layer packet with the wanted source & destination addresses +fn wrap_data_packet( + proto: Protocol, + data: &[u8], + source: SocketAddr, + destination: SocketAddr, +) -> anyhow::Result> { + match source { + SocketAddr::V4(source) => { + let mut builder = packet::ip::v4::Builder::default(); + + builder = builder + .source(*source.ip()) + .with_context(|| "Failed to set packet source")?; + builder = builder + .payload(data) + .with_context(|| "Failed to set packet payload")?; + builder = builder + .protocol(proto) + .with_context(|| "Failed to set packet protocol")?; + builder = builder + .dscp(0) + .with_context(|| "Failed to set packet dcsp")?; + builder = builder + .id(12345) + .with_context(|| "Failed to set packet ID")?; + builder = builder + .ttl(16) + .with_context(|| "Failed to set packet TTL")?; + + match destination { + SocketAddr::V4(destination) => { + builder = builder + .destination(*destination.ip()) + .with_context(|| "Failed to set packet destination")?; + } + SocketAddr::V6(_) => { + return Err(anyhow::anyhow!( + "cannot use ipv6 destination with ipv4 source" + )); + } + } + + builder + .build() + .with_context(|| "Failed to build ipv4 packet") + } + SocketAddr::V6(_) => { + todo!("ipv6 support") + } + } +} + +fn send_packet( packet: &[u8], endpoint_socket: Arc, endpoint_addr: SocketAddr, - peer_addr: IpAddr, ) -> anyhow::Result { // todo: replace addr with peer_addr - endpoint_socket + let size = endpoint_socket .send_to(packet, endpoint_addr) - .with_context(|| "Failed to send mocked packet") + .with_context(|| "Failed to send packet")?; + Ok(size) }