This commit is contained in:
Aram 🍐 2021-10-10 20:49:40 -04:00
parent 65032b2311
commit f3976be852
3 changed files with 172 additions and 25 deletions

86
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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<Vec<u8>> {
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<UdpSocket>,
endpoint_addr: SocketAddr,
peer_addr: IpAddr,
) -> anyhow::Result<usize> {
// 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)
}