mirror of
https://github.com/aramperes/onetun.git
synced 2025-09-09 12:18:31 -04:00
Basic implementation (source ip not set)
This commit is contained in:
parent
d82b496937
commit
65032b2311
1 changed files with 170 additions and 6 deletions
176
src/main.rs
176
src/main.rs
|
@ -1,27 +1,191 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use std::net::UdpSocket;
|
use std::net::{IpAddr, SocketAddr, UdpSocket};
|
||||||
use std::sync::Arc;
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::{Arc, Barrier};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use boringtun::crypto::{X25519PublicKey, X25519SecretKey};
|
use boringtun::crypto::{X25519PublicKey, X25519SecretKey};
|
||||||
use boringtun::device::peer::Peer;
|
use boringtun::device::peer::Peer;
|
||||||
use boringtun::noise::Tunn;
|
use boringtun::noise::{Tunn, TunnResult};
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
|
const MAX_PACKET: usize = 65536;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
pretty_env_logger::init_custom_env("ONETUN_LOG");
|
pretty_env_logger::init_custom_env("ONETUN_LOG");
|
||||||
let config = Config::from_args().with_context(|| "Failed to read config")?;
|
let config = Config::from_args().with_context(|| "Failed to read config")?;
|
||||||
debug!("Parsed arguments: {:?}", config);
|
debug!("Parsed arguments: {:?}", config);
|
||||||
|
|
||||||
// TODO
|
let peer = Arc::new(
|
||||||
// 1. Listen on source addr (sA) -> encapsulate packets with peer IP -> send to endpoint IP (sB)
|
Tunn::new(
|
||||||
// 2. Connect to endpoint IP (sB) -> decapsulate packets -> send to source addr (sA)
|
config.private_key.clone(),
|
||||||
|
config.endpoint_public_key.clone(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.map_err(|s| anyhow::anyhow!("{}", s))
|
||||||
|
.with_context(|| "Failed to initialize peer")?,
|
||||||
|
);
|
||||||
|
|
||||||
|
let source_sock = Arc::new(
|
||||||
|
UdpSocket::bind(&config.source_addr).with_context(|| "Failed to bind source socket")?,
|
||||||
|
);
|
||||||
|
|
||||||
|
let endpoint_sock =
|
||||||
|
Arc::new(UdpSocket::bind("0.0.0.0:0").with_context(|| "Failed to bind endpoint socket")?);
|
||||||
|
|
||||||
|
let endpoint_addr = config.endpoint_addr;
|
||||||
|
|
||||||
|
let peer_ip = config.source_peer_ip;
|
||||||
|
|
||||||
|
let close = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
|
let mut handles = Vec::with_capacity(3);
|
||||||
|
|
||||||
|
// thread 1: read from endpoint, forward to peer
|
||||||
|
{
|
||||||
|
let close = close.clone();
|
||||||
|
let peer = peer.clone();
|
||||||
|
let source_sock = source_sock.clone();
|
||||||
|
let endpoint_sock = endpoint_sock.clone();
|
||||||
|
|
||||||
|
handles.push(thread::spawn(move || loop {
|
||||||
|
// Listen on the network
|
||||||
|
let mut recv_buf = [0u8; MAX_PACKET];
|
||||||
|
let mut send_buf = [0u8; MAX_PACKET];
|
||||||
|
|
||||||
|
let n = match endpoint_sock.recv(&mut recv_buf) {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(_) => {
|
||||||
|
if close.load(Ordering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("Got packet from endpoint sock: {} bytes", n);
|
||||||
|
|
||||||
|
match peer.decapsulate(None, &recv_buf[..n], &mut send_buf) {
|
||||||
|
TunnResult::WriteToNetwork(packet) => {
|
||||||
|
send_mocked_packet(packet, endpoint_sock.clone(), endpoint_addr, peer_ip)
|
||||||
|
.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();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TunnResult::WriteToTunnelV4(packet, _) => {
|
||||||
|
source_sock.send(packet).unwrap();
|
||||||
|
}
|
||||||
|
TunnResult::WriteToTunnelV6(packet, _) => {
|
||||||
|
source_sock.send(packet).unwrap();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// thread 2: read from peer socket
|
||||||
|
{
|
||||||
|
let close = close.clone();
|
||||||
|
let peer = peer.clone();
|
||||||
|
let source_sock = source_sock.clone();
|
||||||
|
let endpoint_sock = endpoint_sock.clone();
|
||||||
|
|
||||||
|
handles.push(thread::spawn(move || loop {
|
||||||
|
let mut recv_buf = [0u8; MAX_PACKET];
|
||||||
|
let mut send_buf = [0u8; MAX_PACKET];
|
||||||
|
|
||||||
|
let n = match source_sock.recv(&mut recv_buf) {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(_) => {
|
||||||
|
if close.load(Ordering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("Got packet from source sock: {} bytes", n);
|
||||||
|
|
||||||
|
match peer.encapsulate(&recv_buf[..n], &mut send_buf) {
|
||||||
|
TunnResult::WriteToNetwork(packet) => {
|
||||||
|
send_mocked_packet(packet, endpoint_sock.clone(), endpoint_addr, peer_ip)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// thread 3: maintenance
|
||||||
|
{
|
||||||
|
let close = close.clone();
|
||||||
|
let peer = peer.clone();
|
||||||
|
let endpoint_sock = endpoint_sock.clone();
|
||||||
|
|
||||||
|
handles.push(thread::spawn(move || loop {
|
||||||
|
if close.load(Ordering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_millis(200));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Tunnelling [{}]->[{}] (via [{}] as peer {})",
|
||||||
|
&config.source_addr, &config.dest_addr, &config.endpoint_addr, &config.source_peer_ip
|
||||||
|
);
|
||||||
|
|
||||||
|
for handle in handles {
|
||||||
|
handle.join().expect("Failed to join thread")
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_mocked_packet(
|
||||||
|
packet: &[u8],
|
||||||
|
endpoint_socket: Arc<UdpSocket>,
|
||||||
|
endpoint_addr: SocketAddr,
|
||||||
|
peer_addr: IpAddr,
|
||||||
|
) -> anyhow::Result<usize> {
|
||||||
|
// todo: replace addr with peer_addr
|
||||||
|
endpoint_socket
|
||||||
|
.send_to(packet, endpoint_addr)
|
||||||
|
.with_context(|| "Failed to send mocked packet")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue