Commit d70d4b10 authored by nanamicat's avatar nanamicat

docker

parent 474d54a0
FROM rust:alpine as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo install --path .
FROM alpine
RUN apk --no-cache add libgcc libstdc++ bash iproute2 iptables ipset netcat-openbsd
COPY --from=builder /usr/local/cargo/bin/tun1 /usr/local/bin/tun
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["tun"]
use pnet::packet::ipv4::Ipv4Packet; use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::Packet; use socket2::{Domain, Protocol, Socket, Type};
use socket2::{Domain, Protocol, SockAddr, Socket, Type};
use std::error::Error; use std::error::Error;
use std::io::{BufRead, Read, Write}; use std::io::{Read, Write};
use std::mem::{transmute, MaybeUninit}; use std::mem::{size_of, MaybeUninit};
use std::sync::{Arc, Mutex}; use std::net::ToSocketAddrs;
use std::process::Command;
use std::sync::{Arc, RwLock};
use std::{env, thread}; use std::{env, thread};
use std::net::{SocketAddr, SocketAddrV4};
use std::net::UdpSocket;
#[repr(C)] #[repr(C)]
pub struct Meta { pub struct Meta {
...@@ -23,17 +20,16 @@ struct Secret { ...@@ -23,17 +20,16 @@ struct Secret {
} }
impl Secret { impl Secret {
fn new(key: &String) -> Secret { fn new(key: &str) -> Self {
Secret { Self {
key: key.as_bytes().to_vec(), key: key.as_bytes().to_vec(),
} }
} }
fn encrypt(&self, data: &mut [u8]) { fn encrypt(&self, data: &mut [u8]) {
for (i, byte) in data.iter_mut().enumerate() { for (i, b) in data.iter_mut().enumerate() {
*byte ^= self.key[i % self.key.len()]; *b ^= self.key[i % self.key.len()];
} }
} }
fn decrypt(&self, data: &mut [u8]) { fn decrypt(&self, data: &mut [u8]) {
self.encrypt(data); self.encrypt(data);
} }
...@@ -44,108 +40,136 @@ fn main() -> Result<(), Box<dyn Error>> { ...@@ -44,108 +40,136 @@ fn main() -> Result<(), Box<dyn Error>> {
let remote_id: u8 = env::var("REMOTE_ID")?.parse()?; let remote_id: u8 = env::var("REMOTE_ID")?.parse()?;
let local_secret = Secret::new(&env::var("LOCAL_SECRET")?); let local_secret = Secret::new(&env::var("LOCAL_SECRET")?);
let remote_secret = Secret::new(&env::var("REMOTE_SECRET")?); let remote_secret = Secret::new(&env::var("REMOTE_SECRET")?);
let remote_addr: Arc<Mutex<Option<SockAddr>>> = Arc::new(Mutex::new( let proto: i32 = env::var("PROTO")?.parse()?;
match env::var("REMOTE_ADDR") { let up = env::var("UP_SCRIPT")?;
Ok(addr_str) => { let dev = env::var("DEV")?;
let parsed = addr_str.parse::<SocketAddr>()?; let family = if env::var("FAMILY")?.parse::<u8>()? == 6 {
Some(parsed.into()) Domain::IPV6
} } else {
Err(_) => None, 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,
}));
let mut config = tun::Configuration::default(); let mut config = tun::Configuration::default();
config config.tun_name(dev).up();
.address((10, 0, 0, local_id))
.netmask((255, 255, 255, 0))
.destination((10, 0, 0, remote_id))
.up();
#[cfg(target_os = "linux")]
config.platform_config(|config| {
config.ensure_root_privileges(true);
});
let dev = tun::create(&config)?; let dev = tun::create(&config)?;
let (mut reader, mut writer) = dev.split(); let (mut reader, mut writer) = dev.split();
// 创建用于接收的原始套接字,协议号为 144 // Create a raw socket with protocol number 144
let socket = Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::from(144)))?; let socket = Socket::new(family, Type::RAW, Some(Protocol::from(proto)))?;
let socket_arc = Arc::new(Mutex::new(socket)); #[cfg(target_os = "linux")]
let socket_for_inbound = Arc::clone(&socket_arc); socket.set_mark(env::var("MARK")?.parse()?);
let socket_clone = socket.try_clone()?;
let remote_addr_clone = Arc::clone(&remote_addr);
match Command::new(up).status() {
let inbound = thread::spawn(move || { Ok(status) => {
let mut recv_buf = [MaybeUninit::uninit(); 1500]; if !status.success() {
loop { eprintln!("Script exited with non-zero status: {}", status);
let sock_guard = socket_for_inbound.lock().unwrap(); }
match sock_guard.recv_from(&mut recv_buf) { }
Ok((len, addr1)) => { Err(e) => eprintln!("Failed to run script '{}'", e),
println!("recv from {:?}", recv_buf); }
let recv_buf2: &mut [u8] = unsafe { transmute(&mut recv_buf[..len]) };
if let Some(packet) = Ipv4Packet::new(recv_buf2) { // Thread for receiving from WAN (raw socket) and writing to TUN
let header_length = packet.get_header_length() as usize * 4; let inbound = {
let (header, data) = recv_buf2.split_at_mut(header_length); let remote_addr = Arc::clone(&endpoint);
let (meta1, payload) = data.split_at_mut(size_of::<Meta>()); let local_secret = local_secret;
let meta: &Meta = unsafe { transmute(&meta1) }; thread::spawn(move || {
if meta.src_id == remote_id && meta.dst_id == local_id && meta.reversed == 0 let mut recv_buf = [MaybeUninit::uninit(); 1500];
{ loop {
let mut addr_lock = remote_addr_clone.lock().unwrap(); match socket.recv_from(&mut recv_buf) {
*addr_lock = Some(addr1); Ok((len, addr)) => {
local_secret.decrypt(payload); // Safely interpret the uninit buffer up to `len` as bytes
writer.write(payload); 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) {
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);
} else {
// eprintln!("Dropping unexpected packet");
}
} }
} }
} Err(e) => eprintln!("Error receiving: {}", e),
Err(e) => {
eprintln!("接收数据包时出错: {:?}", e);
} }
} }
} })
}); };
let outbound = thread::spawn(move || { // Thread for reading from TUN, encrypting, and sending to WAN
let mut recv_buf = [0u8; 1500 - 20]; let outbound = {
let meta = Meta { let remote_addr = Arc::clone(&endpoint);
src_id: local_id, let remote_secret = remote_secret;
dst_id: remote_id, thread::spawn(move || {
reversed: 0, let mut buffer = [0u8; 1500 - 20]; // minus typical IP header space
}; let meta_size = size_of::<Meta>();
let meta_size = size_of::<Meta>();
// Pre-initialize with our Meta header (local -> remote)
unsafe { let meta = Meta {
src_id: local_id,
dst_id: remote_id,
reversed: 0,
};
// Turn the Meta struct into bytes
let meta_bytes = let meta_bytes =
std::slice::from_raw_parts(&meta as *const Meta as *const u8, meta_size); unsafe { std::slice::from_raw_parts(&meta as *const Meta as *const u8, meta_size) };
recv_buf[..meta_size].copy_from_slice(meta_bytes); buffer[..meta_size].copy_from_slice(meta_bytes);
}
loop { loop {
match reader.read(&mut recv_buf[meta_size..]) { match reader.read(&mut buffer[meta_size..]) {
Ok(len) => { Ok(n) if n > 0 => {
println!("recv from {:?}", &recv_buf[meta_size..meta_size + len]); // If we have a known remote address, encrypt and send
let maybe_remote = remote_addr.lock().unwrap().clone(); if let Some(ref addr) = *remote_addr.read().unwrap() {
println!("1"); remote_secret.encrypt(&mut buffer[meta_size..meta_size + n]);
if let Some(ref remote) = maybe_remote { if let Err(e) = socket_clone.send_to(&buffer[..meta_size + n], addr) {
println!("2"); eprintln!("Error sending packet: {}", e);
let sock_guard = socket_arc.lock().unwrap(); }
println!("3"); } else {
remote_secret.encrypt(&mut recv_buf[meta_size..meta_size + len]); eprintln!("No remote address set; packet dropped.");
println!("4");
if let Err(e) = sock_guard.send_to(&recv_buf[..meta_size + len], remote) {
println!("5");
eprintln!("Error sending packet: {:?}", e);
} }
} else {
eprintln!("No remote address available; packet discarded.");
} }
Err(e) => eprintln!("Error reading from TUN: {}", e),
_ => {}
} }
Err(_) => {}
} }
} })
}); };
inbound.join();
outbound.join();
let _ = inbound.join();
let _ = outbound.join();
Ok(()) Ok(())
} }
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