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")?;
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) => { Ok(addr_str) => {
let parsed = addr_str.parse::<SocketAddr>()?; let parsed = addr_str.to_socket_addrs()?.next().unwrap();
Some(parsed.into()) Some(parsed.into())
} }
Err(_) => None, 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() {
Ok(status) => {
if !status.success() {
eprintln!("Script exited with non-zero status: {}", status);
}
}
Err(e) => eprintln!("Failed to run script '{}'", e),
}
let inbound = thread::spawn(move || { // 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 || {
let mut recv_buf = [MaybeUninit::uninit(); 1500]; let mut recv_buf = [MaybeUninit::uninit(); 1500];
loop { loop {
let sock_guard = socket_for_inbound.lock().unwrap(); match socket.recv_from(&mut recv_buf) {
match sock_guard.recv_from(&mut recv_buf) { Ok((len, addr)) => {
Ok((len, addr1)) => { // Safely interpret the uninit buffer up to `len` as bytes
println!("recv from {:?}", recv_buf); let data = unsafe {
let recv_buf2: &mut [u8] = unsafe { transmute(&mut recv_buf[..len]) }; std::slice::from_raw_parts_mut(recv_buf.as_mut_ptr() as *mut u8, len)
if let Some(packet) = Ipv4Packet::new(recv_buf2) { };
let header_length = packet.get_header_length() as usize * 4;
let (header, data) = recv_buf2.split_at_mut(header_length); if let Some(packet) = Ipv4Packet::new(data) {
let (meta1, payload) = data.split_at_mut(size_of::<Meta>()); let header_len = packet.get_header_length() as usize * 4;
let meta: &Meta = unsafe { transmute(&meta1) }; let (_ip_header, rest) = data.split_at_mut(header_len);
if meta.src_id == remote_id && meta.dst_id == local_id && meta.reversed == 0 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
{ {
let mut addr_lock = remote_addr_clone.lock().unwrap(); // Update remote address for outbound
*addr_lock = Some(addr1); *remote_addr.write().unwrap() = Some(addr);
// Decrypt and push into TUN
local_secret.decrypt(payload); local_secret.decrypt(payload);
writer.write(payload); let _ = writer.write_all(payload);
} } else {
// eprintln!("Dropping unexpected packet");
} }
} }
Err(e) => {
eprintln!("接收数据包时出错: {:?}", e);
} }
Err(e) => eprintln!("Error receiving: {}", 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 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 { let meta = Meta {
src_id: local_id, src_id: local_id,
dst_id: remote_id, dst_id: remote_id,
reversed: 0, reversed: 0,
}; };
let meta_size = size_of::<Meta>(); // Turn the Meta struct into bytes
unsafe {
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");
remote_secret.encrypt(&mut recv_buf[meta_size..meta_size + len]);
println!("4");
if let Err(e) = sock_guard.send_to(&recv_buf[..meta_size + len], remote) {
println!("5");
eprintln!("Error sending packet: {:?}", e);
} }
} else { } else {
eprintln!("No remote address available; packet discarded."); eprintln!("No remote address set; packet dropped.");
} }
} }
Err(_) => {} Err(e) => eprintln!("Error reading from TUN: {}", e),
_ => {}
} }
} }
}); })
};
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