Add new dependencies and implement TUN interface initialization
- Updated Cargo.toml to include `etherparse` and enable async feature for `tun-rs`. - Added `ip_match_network` function in network module for IP matching. - Implemented TUN interface initialization in `tun.rs`. - Enhanced client handling in `client.rs` to support new features and improved message handling. - Refactored router messages to use a structured `VpnPacket`. - Updated settings for spell checking in VSCode.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use anyhow::Result;
|
||||
use chrono::Utc;
|
||||
use clap::Args;
|
||||
use ipnet::Ipv4Net;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -11,7 +10,21 @@ use tokio::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use crate::router::{CLIENT_REGISTER_TIMEOUT, CliRegMessages, RouterMessages, SERVER_PACKET_SIZE};
|
||||
use crate::{
|
||||
network::ip_match_network,
|
||||
router::{CLIENT_REGISTER_TIMEOUT, CliRegMessages, RouterMessages, SERVER_PACKET_SIZE},
|
||||
tun::inti_tun_interface,
|
||||
};
|
||||
|
||||
pub struct ClientStaTistic {
|
||||
pub last_keep_alive: Option<chrono::DateTime<Utc>>,
|
||||
pub keep_alive_count: usize,
|
||||
pub total_data_received: usize,
|
||||
pub total_data_sent: usize,
|
||||
pub last_data_received: Option<chrono::DateTime<Utc>>,
|
||||
pub last_data_sent: Option<chrono::DateTime<Utc>>,
|
||||
pub latency_ms: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Args)]
|
||||
pub struct ClientCfg {
|
||||
@@ -19,9 +32,9 @@ pub struct ClientCfg {
|
||||
#[arg(long, short)]
|
||||
pub server: String,
|
||||
|
||||
/// The local interface IP address (example: 10.8.0.2).
|
||||
/// The local interface IP address (example: 10.8.0.2/32).
|
||||
#[arg(long = "interface-ip")]
|
||||
pub interface_ip: IpAddr,
|
||||
pub interface_ip: Ipv4Net,
|
||||
|
||||
/// The local interface name.
|
||||
#[arg(long = "interface-name", default_value = "xvpn0")]
|
||||
@@ -31,6 +44,10 @@ pub struct ClientCfg {
|
||||
/// Example: --local-route 1.1.1.1/32,10.0.0.0/24
|
||||
#[arg(long = "local-route", visible_alias = "lr", value_delimiter = ',')]
|
||||
pub local_routes: Vec<Ipv4Net>,
|
||||
/// MTU for the TUN interface.
|
||||
/// If not specified, the default MTU of the system will be used.
|
||||
#[arg(long = "mtu", default_value = "1400")]
|
||||
pub mtu: u16,
|
||||
}
|
||||
|
||||
pub async fn start(config: ClientCfg) -> Result<()> {
|
||||
@@ -41,27 +58,51 @@ pub async fn start(config: ClientCfg) -> Result<()> {
|
||||
let (mut rx, mut tx) = stream.into_split();
|
||||
// let client_stream = ClientStream::new(tx);
|
||||
|
||||
let mut buf = vec![0u8; SERVER_PACKET_SIZE];
|
||||
register_client(&mut rx, &mut tx, config, &mut buf).await?;
|
||||
let mut vpn_buf = vec![0u8; SERVER_PACKET_SIZE];
|
||||
let mut tun_buf = vec![0u8; config.mtu as usize];
|
||||
register_client(&mut rx, &mut tx, &config, &mut vpn_buf).await?;
|
||||
let tun_device = inti_tun_interface(&config).await?;
|
||||
|
||||
println!("Client registration successful. Entering main loop to receive messages from router...");
|
||||
loop {
|
||||
tokio::select! {
|
||||
msg = rx.read(&mut buf) => {
|
||||
msg = rx.read(&mut vpn_buf) => {
|
||||
match msg {
|
||||
Ok(0) => {
|
||||
println!("Connection to router closed by peer.");
|
||||
return Ok(());
|
||||
}
|
||||
Ok(n) => {
|
||||
println!("Received {} bytes from router: {:?}", n, RouterMessages::from_slice(&buf[..n]));
|
||||
match RouterMessages::from_slice(&vpn_buf[..n]){
|
||||
RouterMessages::KeepAlive(timestamp) => {
|
||||
println!("Received keep-alive message from router with timestamp: {}, delta {} ms", timestamp, (Utc::now().timestamp_micros() - timestamp).abs() as f64 / 1000.0);
|
||||
}
|
||||
|
||||
_ => println!("Received message from router: {:?}", RouterMessages::from_slice(&vpn_buf[..n]))
|
||||
};
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from router: {}", e);
|
||||
return Err(anyhow::anyhow!(format!("Error reading from router: {}", e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data = tun_device.recv(&mut tun_buf) => {
|
||||
match data {
|
||||
Ok(n) => {
|
||||
let packet = etherparse::Ipv4HeaderSlice::from_slice(&tun_buf[..n])?;
|
||||
let src = packet.source_addr();
|
||||
match ip_match_network(src, &config.local_routes).await {
|
||||
Some(net) => println!("Source IP {} matches local route {}", src, net),
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from TUN interface: {}", e);
|
||||
return Err(anyhow::anyhow!(format!("Error reading from TUN interface: {}", e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +112,10 @@ pub async fn start(config: ClientCfg) -> Result<()> {
|
||||
pub async fn register_client(
|
||||
rx: &mut OwnedReadHalf,
|
||||
tx: &mut OwnedWriteHalf,
|
||||
config: ClientCfg,
|
||||
config: &ClientCfg,
|
||||
buf: &mut [u8],
|
||||
) -> Result<()> {
|
||||
let register_msg = RouterMessages::CliReg(CliRegMessages::Reg(config));
|
||||
let register_msg = RouterMessages::CliReg(CliRegMessages::Reg(config.clone()));
|
||||
let mut client_registration_timeout =
|
||||
tokio::time::interval_at(Instant::now() + CLIENT_REGISTER_TIMEOUT, CLIENT_REGISTER_TIMEOUT);
|
||||
tx.write_all(®ister_msg.to_bytes()).await?;
|
||||
|
||||
Reference in New Issue
Block a user