Commit 359aa7c6 authored by nanamicat's avatar nanamicat

new

parent bcce5562
...@@ -113,6 +113,56 @@ dependencies = [ ...@@ -113,6 +113,56 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "crossbeam"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.20" version = "0.8.20"
...@@ -612,6 +662,8 @@ name = "tun1" ...@@ -612,6 +662,8 @@ name = "tun1"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"base64", "base64",
"crossbeam",
"crossbeam-utils",
"lazy_static", "lazy_static",
"pnet", "pnet",
"pnet_macros", "pnet_macros",
......
...@@ -12,3 +12,5 @@ serde = { version = "1.0.217", features = ["derive"] } ...@@ -12,3 +12,5 @@ serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
base64 = "0.22.1" base64 = "0.22.1"
lazy_static = "1.5.0" lazy_static = "1.5.0"
crossbeam = "0.8.4"
crossbeam-utils = "0.8.20"
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct ConfigRouter {
pub remote_id: u8,
pub proto: i32,
pub family: u8,
pub mark: u32,
pub endpoint: String,
pub remote_secret: String,
pub dev: String,
pub up: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub local_id: u8,
pub local_secret: String,
pub routers: Vec<ConfigRouter>,
}
\ No newline at end of file
mod config; mod router;
mod Router;
use pnet::packet::ipv4::Ipv4Packet; use crate::router::{Router, SECRET_LENGTH};
use socket2::{Domain, Protocol, Socket, Type}; use std::collections::HashMap;
use std::env;
use std::error::Error; use std::error::Error;
use std::intrinsics::transmute;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::mem::{size_of, MaybeUninit}; use std::mem::MaybeUninit;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use std::process::Command; use std::sync::Arc;
use std::sync::{Arc, RwLock};
use std::{env, thread};
use crate::config::Config;
#[repr(C)] #[repr(C)]
pub struct Meta { pub struct Meta {
...@@ -19,110 +17,116 @@ pub struct Meta { ...@@ -19,110 +17,116 @@ pub struct Meta {
pub reversed: u16, pub reversed: u16,
} }
struct Secret { use serde::{Deserialize, Serialize};
key: Vec<u8>,
#[derive(Debug, Serialize, Deserialize)]
pub struct ConfigRouter {
pub remote_id: u8,
pub proto: i32,
pub family: u8,
pub mark: u32,
pub endpoint: String,
pub remote_secret: String,
pub dev: String,
pub up: String,
} }
impl Secret { #[derive(Debug, Serialize, Deserialize)]
fn new(key: &str) -> Self { pub struct Config {
Self { pub local_id: u8,
key: key.as_bytes().to_vec(), pub local_secret: String,
} pub routers: Vec<ConfigRouter>,
}
fn encrypt(&self, data: &mut [u8]) {
for (i, b) in data.iter_mut().enumerate() {
*b ^= self.key[i % self.key.len()];
}
}
fn decrypt(&self, data: &mut [u8]) {
self.encrypt(data);
}
} }
use crossbeam_utils::thread;
use lazy_static::lazy_static;
use pnet::packet::ipv4::Ipv4Packet;
use socket2::Socket;
fn main() -> Result<(), Box<dyn Error>> { lazy_static! {
static ref config: Config = serde_json::from_str(env::args().nth(0).unwrap().as_str()).unwrap();
let data = env::args().nth(0).unwrap(); static ref local_secret: [u8; SECRET_LENGTH] =
let config: Config = serde_json::from_str(data.as_str())?; Router::create_secret(config.local_secret.as_str()).unwrap();
}
let local_id: u8 = env::var("LOCAL_ID")?.parse()?;
let remote_id: u8 = env::var("REMOTE_ID")?.parse()?;
let local_secret = Secret::new(&env::var("LOCAL_SECRET")?);
let remote_secret = Secret::new(&env::var("REMOTE_SECRET")?);
let proto: i32 = env::var("PROTO")?.parse()?;
let up = env::var("UP_SCRIPT")?;
let dev = env::var("DEV")?;
let family = if env::var("FAMILY")?.parse::<u8>()? == 6 {
Domain::IPV6
} else {
Domain::IPV4
};
let endpoint = Arc::new(RwLock::new(match env::var("ENDPOINT") {
Ok(addr_str) => {
let parsed = addr_str.to_socket_addrs()?.next().unwrap();
Some(parsed.into())
}
Err(_) => None,
}));
// Create a raw socket with protocol number 144
let socket = Socket::new(family, Type::RAW, Some(Protocol::from(proto)))?;
#[cfg(target_os = "linux")]
socket.set_mark(env::var("MARK")?.parse()?);
let socket_clone = socket.try_clone()?;
match Command::new(up).status() { fn main() -> Result<(), Box<dyn Error>> {
Ok(status) => { let mut sockets: HashMap<u16, Arc<Socket>> = HashMap::new();
if !status.success() { let mut routers: HashMap<u8, Router> = config
eprintln!("Script exited with non-zero status: {}", status); .routers
} .iter()
.map(|c| Router::new(c, &mut sockets).map(|router| (c.remote_id, router)))
.collect::<Result<_, _>>()?;
thread::scope(|s| {
for router in routers.values_mut() {
s.spawn({
|_| {
let mut buffer = [0u8; 1500 - 20]; // minus typical IP header space
let meta_size = size_of::<Meta>();
// Pre-initialize with our Meta header (local -> remote)
let meta = Meta {
src_id: config.local_id,
dst_id: router.config.remote_id,
reversed: 0,
};
// Turn the Meta struct into bytes
let meta_bytes = unsafe {
std::slice::from_raw_parts(&meta as *const Meta as *const u8, meta_size)
};
buffer[..meta_size].copy_from_slice(meta_bytes);
loop {
match router.tun_reader.read(&mut buffer[meta_size..]) {
Ok(n) if n > 0 => {
// If we have a known remote address, encrypt and send
if let Some(ref addr) = router.endpoint {
router.encrypt(&mut buffer[meta_size..meta_size + n]);
#[cfg(target_os = "linux")]
router.socket.set_mark(router.config.mark)?;
if let Err(e) =
router.socket.send_to(&buffer[..meta_size + n], addr)
{
eprintln!("Error sending packet: {}", e);
}
} else {
eprintln!("No remote address set; packet dropped.");
}
}
Err(e) => eprintln!("Error reading from TUN: {}", e),
_ => {}
}
}
}
});
} }
Err(e) => eprintln!("Failed to run script '{}'", e),
}
// Thread for receiving from WAN (raw socket) and writing to TUN for socket in sockets.values() {
let inbound = {
let remote_addr = Arc::clone(&endpoint);
let local_secret = local_secret;
thread::spawn(move || {
let mut recv_buf = [MaybeUninit::uninit(); 1500]; let mut recv_buf = [MaybeUninit::uninit(); 1500];
loop { loop {
match socket.recv_from(&mut recv_buf) { match socket.recv_from(&mut recv_buf) {
Ok((len, addr)) => { Ok((len, addr)) => {
// Safely interpret the uninit buffer up to `len` as bytes let data: &mut [u8] = unsafe { transmute(&mut recv_buf[..len]) };
let data = unsafe {
std::slice::from_raw_parts_mut(recv_buf.as_mut_ptr() as *mut u8, len)
};
if let Some(packet) = Ipv4Packet::new(data) { if let Some(packet) = Ipv4Packet::new(data) {
let header_len = packet.get_header_length() as usize * 4; let header_len = packet.get_header_length() as usize * 4;
let (_ip_header, rest) = data.split_at_mut(header_len); let (_ip_header, rest) = data.split_at_mut(header_len);
if rest.len() < size_of::<Meta>() { if rest.len() < size_of::<Meta>() {
// Malformed packet
continue; continue;
} }
let (meta_bytes, payload) = rest.split_at_mut(size_of::<Meta>()); let (meta_bytes, payload) = rest.split_at_mut(size_of::<Meta>());
// Extract meta
let meta = Meta { let meta = Meta {
src_id: meta_bytes[0], src_id: meta_bytes[0],
dst_id: meta_bytes[1], dst_id: meta_bytes[1],
reversed: u16::from_le_bytes([meta_bytes[2], meta_bytes[3]]), reversed: u16::from_le_bytes([meta_bytes[2], meta_bytes[3]]),
}; };
// Check if it matches our expected IDs if let Some(router) = routers.get_mut(&meta.src_id) {
if meta.src_id == remote_id if meta.dst_id == config.local_id && meta.reversed == 0 {
&& meta.dst_id == local_id router.endpoint = Some(addr);
&& meta.reversed == 0 router.decrypt(payload);
{ router.tun_writer.write_all(payload).unwrap();
// Update remote address for outbound }
*remote_addr.write().unwrap() = Some(addr);
// Decrypt and push into TUN
local_secret.decrypt(payload);
let _ = writer.write_all(payload);
} else { } else {
// eprintln!("Dropping unexpected packet"); // eprintln!("Dropping unexpected packet");
} }
...@@ -131,49 +135,9 @@ fn main() -> Result<(), Box<dyn Error>> { ...@@ -131,49 +135,9 @@ fn main() -> Result<(), Box<dyn Error>> {
Err(e) => eprintln!("Error receiving: {}", e), Err(e) => eprintln!("Error receiving: {}", e),
} }
} }
}) }
}; })
.unwrap();
// Thread for reading from TUN, encrypting, and sending to WAN
let outbound = {
let remote_addr = Arc::clone(&endpoint);
let remote_secret = remote_secret;
thread::spawn(move || {
let mut buffer = [0u8; 1500 - 20]; // minus typical IP header space
let meta_size = size_of::<Meta>();
// Pre-initialize with our Meta header (local -> remote)
let meta = Meta {
src_id: local_id,
dst_id: remote_id,
reversed: 0,
};
// Turn the Meta struct into bytes
let meta_bytes =
unsafe { std::slice::from_raw_parts(&meta as *const Meta as *const u8, meta_size) };
buffer[..meta_size].copy_from_slice(meta_bytes);
loop {
match reader.read(&mut buffer[meta_size..]) {
Ok(n) if n > 0 => {
// If we have a known remote address, encrypt and send
if let Some(ref addr) = *remote_addr.read().unwrap() {
remote_secret.encrypt(&mut buffer[meta_size..meta_size + n]);
if let Err(e) = socket_clone.send_to(&buffer[..meta_size + n], addr) {
eprintln!("Error sending packet: {}", e);
}
} else {
eprintln!("No remote address set; packet dropped.");
}
}
Err(e) => eprintln!("Error reading from TUN: {}", e),
_ => {}
}
}
})
};
let _ = inbound.join();
let _ = outbound.join();
Ok(()) Ok(())
} }
use std::collections::HashMap;
use crate::config::ConfigRouter;
use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use socket2::{Domain, Protocol, SockAddr, Socket, Type};
use std::process::{Command, ExitStatus}; use std::collections::hash_map::Entry;
use tun::{Device, Reader, Writer}; use std::collections::HashMap;
const SECRET_LENGTH: usize = 32; use std::net::ToSocketAddrs;
use std::process::Command;
use std::sync::Arc;
use tun::{Reader, Writer};
pub const SECRET_LENGTH: usize = 32;
use crate::ConfigRouter;
use base64::prelude::*; use base64::prelude::*;
use lazy_static::lazy_static;
lazy_static! {
static ref sockets: HashMap<u16, Socket> = {
HashMap::new()
};
}
pub struct Router { pub struct Router {
pub config: ConfigRouter, pub config: &'static ConfigRouter,
pub secret: [u8; SECRET_LENGTH], pub secret: [u8; SECRET_LENGTH],
pub remote_addr: Option<SockAddr>, pub endpoint: Option<SockAddr>,
pub tun_reader: Reader, pub tun_reader: Reader,
pub tun_writer: Writer, pub tun_writer: Writer,
pub socket: Socket, pub socket: Arc<Socket>,
} }
impl Router { impl Router {
fn create_secret( pub(crate) fn create_secret(
config: &ConfigRouter, config: &str,
) -> Result<[u8; SECRET_LENGTH], Box<dyn std::error::Error>> { ) -> Result<[u8; SECRET_LENGTH], Box<dyn std::error::Error>> {
let mut secret = [0u8; SECRET_LENGTH]; let mut secret = [0u8; SECRET_LENGTH];
let decoded = BASE64_STANDARD.decode(config.remote_secret.as_str())?; let decoded = BASE64_STANDARD.decode(config)?;
let len = decoded.len().min(SECRET_LENGTH); let len = decoded.len().min(SECRET_LENGTH);
secret[..len].copy_from_slice(&decoded[..len]); secret[..len].copy_from_slice(&decoded[..len]);
Ok(secret) Ok(secret)
} }
fn create_raw_socket(config: &ConfigRouter) -> Result<Socket, Box<dyn std::error::Error>> { fn create_raw_socket(
config: &ConfigRouter,
sockets: &mut HashMap<u16, Arc<Socket>>,
) -> Result<Arc<Socket>, Box<dyn std::error::Error>> {
let key = (config.family as u16) << 8 | config.proto as u16; let key = (config.family as u16) << 8 | config.proto as u16;
match sockets.get(&key) { let result = match sockets.entry(key) {
Some(socket) => println!("{book}: {review}"), Entry::Occupied(entry) => entry.get().clone(),
None => println!("{book} is unreviewed.") Entry::Vacant(entry) => entry
} .insert(Arc::new(Socket::new(
if config.family == 6 {
Domain::IPV6
let socket = Socket::new( } else {
if config.family == 6 { Domain::IPV4
Domain::IPV6 },
} else { Type::RAW,
Domain::IPV4 Some(Protocol::from(config.proto)),
}, )?))
Type::RAW, .clone(),
Some(Protocol::from(config.proto)), };
)?; Ok(result)
Ok(socket)
} }
fn create_tun_device( fn create_tun_device(
config: &ConfigRouter, config: &ConfigRouter,
...@@ -64,16 +62,28 @@ impl Router { ...@@ -64,16 +62,28 @@ impl Router {
Command::new(config.up.as_str()).status()?; Command::new(config.up.as_str()).status()?;
Ok(()) Ok(())
} }
pub fn new(config: ConfigRouter) -> Result<Router, Box<dyn std::error::Error>> {
let secret = Self::create_secret(&config)?; fn create_endpoint(
let socket = Self::create_raw_socket(&config)?; config: &ConfigRouter,
) -> Result<Option<SockAddr>, Box<dyn std::error::Error>> {
let parsed = config.endpoint.to_socket_addrs()?.next().unwrap();
Ok(Some(parsed.into()))
}
pub fn new(
config: &'static ConfigRouter,
sockets: &mut HashMap<u16, Arc<Socket>>,
) -> Result<Router, Box<dyn std::error::Error>> {
let secret = Self::create_secret(config.remote_secret.as_str())?;
let endpoint = Self::create_endpoint(&config)?;
let socket = Self::create_raw_socket(&config, sockets)?;
let (tun_reader, tun_writer) = Self::create_tun_device(&config)?; let (tun_reader, tun_writer) = Self::create_tun_device(&config)?;
Self::run_up_script(&config)?; Self::run_up_script(&config)?;
let router = Router { let router = Router {
config, config,
secret, secret,
remote_addr: None, endpoint,
tun_reader, tun_reader,
tun_writer, tun_writer,
socket, socket,
...@@ -81,4 +91,13 @@ impl Router { ...@@ -81,4 +91,13 @@ impl Router {
Ok(router) Ok(router)
} }
pub(crate) fn encrypt(&self, data: &mut [u8]) {
for (i, b) in data.iter_mut().enumerate() {
*b ^= self.secret[i % SECRET_LENGTH];
}
}
pub(crate) fn decrypt(&self, data: &mut [u8]) {
self.encrypt(data);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment