Commit 359aa7c6 authored by nanamicat's avatar nanamicat

new

parent bcce5562
......@@ -113,6 +113,56 @@ dependencies = [
"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]]
name = "crossbeam-utils"
version = "0.8.20"
......@@ -612,6 +662,8 @@ name = "tun1"
version = "0.1.0"
dependencies = [
"base64",
"crossbeam",
"crossbeam-utils",
"lazy_static",
"pnet",
"pnet_macros",
......
......@@ -12,3 +12,5 @@ serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0"
base64 = "0.22.1"
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 socket2::{Domain, Protocol, Socket, Type};
use crate::router::{Router, SECRET_LENGTH};
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::intrinsics::transmute;
use std::io::{Read, Write};
use std::mem::{size_of, MaybeUninit};
use std::mem::MaybeUninit;
use std::net::ToSocketAddrs;
use std::process::Command;
use std::sync::{Arc, RwLock};
use std::{env, thread};
use crate::config::Config;
use std::sync::Arc;
#[repr(C)]
pub struct Meta {
......@@ -19,110 +17,116 @@ pub struct Meta {
pub reversed: u16,
}
struct Secret {
key: Vec<u8>,
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,
}
impl Secret {
fn new(key: &str) -> Self {
Self {
key: key.as_bytes().to_vec(),
}
}
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);
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub local_id: u8,
pub local_secret: String,
pub routers: Vec<ConfigRouter>,
}
use crossbeam_utils::thread;
use lazy_static::lazy_static;
use pnet::packet::ipv4::Ipv4Packet;
use socket2::Socket;
fn main() -> Result<(), Box<dyn Error>> {
let data = env::args().nth(0).unwrap();
let config: Config = serde_json::from_str(data.as_str())?;
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()?;
lazy_static! {
static ref config: Config = serde_json::from_str(env::args().nth(0).unwrap().as_str()).unwrap();
static ref local_secret: [u8; SECRET_LENGTH] =
Router::create_secret(config.local_secret.as_str()).unwrap();
}
match Command::new(up).status() {
Ok(status) => {
if !status.success() {
eprintln!("Script exited with non-zero status: {}", status);
}
fn main() -> Result<(), Box<dyn Error>> {
let mut sockets: HashMap<u16, Arc<Socket>> = HashMap::new();
let mut routers: HashMap<u8, Router> = config
.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
let inbound = {
let remote_addr = Arc::clone(&endpoint);
let local_secret = local_secret;
thread::spawn(move || {
for socket in sockets.values() {
let mut recv_buf = [MaybeUninit::uninit(); 1500];
loop {
match socket.recv_from(&mut recv_buf) {
Ok((len, addr)) => {
// Safely interpret the uninit buffer up to `len` as bytes
let data = unsafe {
std::slice::from_raw_parts_mut(recv_buf.as_mut_ptr() as *mut u8, len)
};
let data: &mut [u8] = unsafe { transmute(&mut recv_buf[..len]) };
if let Some(packet) = Ipv4Packet::new(data) {
let header_len = packet.get_header_length() as usize * 4;
let (_ip_header, rest) = data.split_at_mut(header_len);
if rest.len() < size_of::<Meta>() {
// Malformed packet
continue;
}
let (meta_bytes, payload) = rest.split_at_mut(size_of::<Meta>());
// Extract meta
let meta = Meta {
src_id: meta_bytes[0],
dst_id: meta_bytes[1],
reversed: u16::from_le_bytes([meta_bytes[2], meta_bytes[3]]),
};
// Check if it matches our expected IDs
if meta.src_id == remote_id
&& meta.dst_id == local_id
&& meta.reversed == 0
{
// 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);
if let Some(router) = routers.get_mut(&meta.src_id) {
if meta.dst_id == config.local_id && meta.reversed == 0 {
router.endpoint = Some(addr);
router.decrypt(payload);
router.tun_writer.write_all(payload).unwrap();
}
} else {
// eprintln!("Dropping unexpected packet");
}
......@@ -131,49 +135,9 @@ fn main() -> Result<(), Box<dyn Error>> {
Err(e) => eprintln!("Error receiving: {}", e),
}
}
})
};
// 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),
_ => {}
}
}
})
};
}
})
.unwrap();
let _ = inbound.join();
let _ = outbound.join();
Ok(())
}
use std::collections::HashMap;
use crate::config::ConfigRouter;
use socket2::{Domain, Protocol, SockAddr, Socket, Type};
use std::process::{Command, ExitStatus};
use tun::{Device, Reader, Writer};
const SECRET_LENGTH: usize = 32;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
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 lazy_static::lazy_static;
lazy_static! {
static ref sockets: HashMap<u16, Socket> = {
HashMap::new()
};
}
pub struct Router {
pub config: ConfigRouter,
pub config: &'static ConfigRouter,
pub secret: [u8; SECRET_LENGTH],
pub remote_addr: Option<SockAddr>,
pub endpoint: Option<SockAddr>,
pub tun_reader: Reader,
pub tun_writer: Writer,
pub socket: Socket,
pub socket: Arc<Socket>,
}
impl Router {
fn create_secret(
config: &ConfigRouter,
pub(crate) fn create_secret(
config: &str,
) -> Result<[u8; SECRET_LENGTH], Box<dyn std::error::Error>> {
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);
secret[..len].copy_from_slice(&decoded[..len]);
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;
match sockets.get(&key) {
Some(socket) => println!("{book}: {review}"),
None => println!("{book} is unreviewed.")
}
let socket = Socket::new(
if config.family == 6 {
Domain::IPV6
} else {
Domain::IPV4
},
Type::RAW,
Some(Protocol::from(config.proto)),
)?;
Ok(socket)
let result = match sockets.entry(key) {
Entry::Occupied(entry) => entry.get().clone(),
Entry::Vacant(entry) => entry
.insert(Arc::new(Socket::new(
if config.family == 6 {
Domain::IPV6
} else {
Domain::IPV4
},
Type::RAW,
Some(Protocol::from(config.proto)),
)?))
.clone(),
};
Ok(result)
}
fn create_tun_device(
config: &ConfigRouter,
......@@ -64,16 +62,28 @@ impl Router {
Command::new(config.up.as_str()).status()?;
Ok(())
}
pub fn new(config: ConfigRouter) -> Result<Router, Box<dyn std::error::Error>> {
let secret = Self::create_secret(&config)?;
let socket = Self::create_raw_socket(&config)?;
fn create_endpoint(
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)?;
Self::run_up_script(&config)?;
let router = Router {
config,
secret,
remote_addr: None,
endpoint,
tun_reader,
tun_writer,
socket,
......@@ -81,4 +91,13 @@ impl 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