This commit is contained in:
2026-02-27 10:18:23 +00:00
commit 3f63d19173
36 changed files with 14285 additions and 0 deletions

79
rust/src/tunnel.rs Normal file
View File

@@ -0,0 +1,79 @@
use anyhow::Result;
use std::net::Ipv4Addr;
use tracing::info;
/// Configuration for creating a TUN device.
pub struct TunConfig {
pub name: String,
pub address: Ipv4Addr,
pub netmask: Ipv4Addr,
pub mtu: u16,
}
impl Default for TunConfig {
fn default() -> Self {
Self {
name: "smartvpn0".to_string(),
address: Ipv4Addr::new(10, 8, 0, 1),
netmask: Ipv4Addr::new(255, 255, 255, 0),
mtu: 1420,
}
}
}
/// Create and configure a TUN device.
/// Returns an async TUN device handle.
pub fn create_tun(config: &TunConfig) -> Result<tun::AsyncDevice> {
let mut tun_config = tun::Configuration::default();
tun_config
.tun_name(&config.name)
.address(config.address)
.netmask(config.netmask)
.mtu(config.mtu as u16)
.up();
#[cfg(target_os = "linux")]
tun_config.platform_config(|p| {
p.ensure_root_privileges(true);
});
let device = tun::create_as_async(&tun_config)?;
info!(
"TUN device {} created: addr={}, mtu={}",
config.name, config.address, config.mtu
);
Ok(device)
}
/// Set up routing: add a route for the VPN subnet through the TUN device.
pub async fn add_route(subnet: &str, device_name: &str) -> Result<()> {
let output = tokio::process::Command::new("ip")
.args(["route", "add", subnet, "dev", device_name])
.output()
.await?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
// Ignore "File exists" errors (route already set)
if !stderr.contains("File exists") {
anyhow::bail!("Failed to add route: {}", stderr);
}
}
info!("Added route {} via {}", subnet, device_name);
Ok(())
}
/// Remove a route.
pub async fn remove_route(subnet: &str, device_name: &str) -> Result<()> {
let output = tokio::process::Command::new("ip")
.args(["route", "del", subnet, "dev", device_name])
.output()
.await?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
tracing::warn!("Failed to remove route (may not exist): {}", stderr);
}
Ok(())
}