start, reverse guard, cli-frontend for server and client

This commit is contained in:
2026-01-01 18:54:36 +03:00
commit 5fbb32d243
30 changed files with 4700 additions and 0 deletions

12
osn/Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "osn"
version.workspace = true
edition.workspace = true
[dependencies]
tokio.workspace = true
bytes.workspace = true
anyhow.workspace = true
thiserror.workspace = true
tracing.workspace = true
async-trait = "0.1"

3
osn/src/lib.rs Normal file
View File

@@ -0,0 +1,3 @@
pub mod tun;
pub use tun::{DummyTun, Router, TunConfig, TunDevice, TunError};

95
osn/src/tun.rs Normal file
View File

@@ -0,0 +1,95 @@
//! Virtual network interface (TUN/TAP) abstraction
use bytes::Bytes;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum TunError {
#[error("failed to create interface: {0}")]
Create(String),
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("interface not ready")]
NotReady,
}
/// TUN device configuration
#[derive(Debug, Clone)]
pub struct TunConfig {
pub name: String,
pub address: [u8; 4],
pub netmask: [u8; 4],
pub mtu: u16,
}
impl Default for TunConfig {
fn default() -> Self {
Self {
name: "ostp0".into(),
address: [10, 0, 0, 1],
netmask: [255, 255, 255, 0],
mtu: 1400,
}
}
}
/// Abstract TUN device trait
#[async_trait::async_trait]
pub trait TunDevice: Send + Sync {
async fn read(&self) -> Result<Bytes, TunError>;
async fn write(&self, data: &[u8]) -> Result<usize, TunError>;
fn mtu(&self) -> u16;
}
/// Placeholder TUN implementation (platform-specific impl needed)
pub struct DummyTun {
config: TunConfig,
}
impl DummyTun {
pub fn new(config: TunConfig) -> Self {
Self { config }
}
}
#[async_trait::async_trait]
impl TunDevice for DummyTun {
async fn read(&self) -> Result<Bytes, TunError> {
// Platform-specific: use wintun on Windows, tun-tap on Linux
Err(TunError::NotReady)
}
async fn write(&self, _data: &[u8]) -> Result<usize, TunError> {
Err(TunError::NotReady)
}
fn mtu(&self) -> u16 {
self.config.mtu
}
}
/// IP packet routing helper
pub struct Router {
default_gateway: [u8; 4],
}
impl Router {
pub fn new(gateway: [u8; 4]) -> Self {
Self {
default_gateway: gateway,
}
}
/// Check if IP should be tunneled
pub fn should_tunnel(&self, dest_ip: &[u8; 4]) -> bool {
// Don't tunnel local/private ranges by default
!matches!(
dest_ip,
[10, ..] | [127, ..] | [192, 168, ..] | [172, 16..=31, ..]
)
}
pub fn gateway(&self) -> [u8; 4] {
self.default_gateway
}
}