Compare commits

...

4 Commits

10 changed files with 850 additions and 489 deletions

View File

@ -1,6 +1,5 @@
{ {
// "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu", // "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu",
// "rust-analyzer.cargo.target": "x86_64-unknown-linux-gnu", "rust-analyzer.cargo.target": "x86_64-unknown-linux-gnu",
// "rust-analyzer.cargo.features": ["tun"] // "rust-analyzer.cargo.features": ["tun"]
} }

581
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,7 @@ default-net = "0.22.0"
socket2 = "0.6.3" socket2 = "0.6.3"
hostname = "0.4.2" hostname = "0.4.2"
sysinfo = "0.38.4" sysinfo = "0.38.4"
tun-rs = { version = "2.8.5", features = ["async"] }
# rolling-file = { path = "../rolling-file" } # rolling-file = { path = "../rolling-file" }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]

View File

@ -1,22 +1,20 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::atomic::{Ordering}; use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use crate::config::{TCP_PING_TIME}; use crate::config::TCP_PING_TIME;
use crate::network::ipv6::run_ipv6; use crate::network::ipv6::run_ipv6;
use crate::network::{ use crate::network::{get_edge, ping_to_sn, read_and_parse_packet, TunTapPacketHandler};
get_edge, ping_to_sn, read_and_parse_packet, TunTapPacketHandler,
};
use crate::tcp::{init_quic_conn, send_stun_request}; use crate::tcp::{init_quic_conn, send_stun_request};
use crate::utils::{send_to_sock, CommandLine}; use crate::utils::{send_to_sock, CommandLine};
use crate::{ConnectionInfo}; use crate::ConnectionInfo;
use bytes::BytesMut; use bytes::BytesMut;
use etherparse::{PacketBuilder}; use etherparse::PacketBuilder;
use sdlan_sn_rs::peer::{SdlanSock}; use sdlan_sn_rs::peer::SdlanSock;
use sdlan_sn_rs::utils::{get_current_timestamp, ip_to_string, is_multi_broadcast}; use sdlan_sn_rs::utils::{get_current_timestamp, ip_to_string, is_multi_broadcast};
use sdlan_sn_rs::utils::{Mac, Result}; use sdlan_sn_rs::utils::{Mac, Result};
use tokio::net::{UdpSocket}; use tokio::net::UdpSocket;
use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
@ -120,7 +118,11 @@ pub async fn async_main(
Ok(()) Ok(())
} }
async fn run_edge_loop(eee: &'static Node, global_dns_rx: Receiver<(Vec<u8>, SocketAddr)>, cancel: CancellationToken) { async fn run_edge_loop(
eee: &'static Node,
global_dns_rx: Receiver<(Vec<u8>, SocketAddr)>,
cancel: CancellationToken,
) {
ping_to_sn().await; ping_to_sn().await;
{ {
let cancel2 = cancel.clone(); let cancel2 = cancel.clone();
@ -214,7 +216,11 @@ async fn receive_dns_reply(sock: &Arc<UdpSocket>) -> Option<Vec<u8>> {
None None
} }
async fn loop_tap(eee: &'static Node, mut dns_rx: Receiver<(Vec<u8>, SocketAddr)>, cancel: CancellationToken) { async fn loop_tap(
eee: &'static Node,
mut dns_rx: Receiver<(Vec<u8>, SocketAddr)>,
cancel: CancellationToken,
) {
debug!("loop tap"); debug!("loop tap");
let (tx, mut rx) = channel(10); let (tx, mut rx) = channel(10);
tokio::spawn(async { tokio::spawn(async {
@ -293,23 +299,23 @@ async fn loop_tap(eee: &'static Node, mut dns_rx: Receiver<(Vec<u8>, SocketAddr)
} }
#[cfg(any(feature = "tun", target_os = "windows"))] #[cfg(any(feature = "tun", target_os = "windows"))]
fn get_data_from_tun_with_layer2_zeroed(eee: &Node) -> BytesMut { async fn get_data_from_tun_with_layer2_zeroed(eee: &Node) -> BytesMut {
let mut temp = BytesMut::zeroed(1514); let mut temp = BytesMut::zeroed(1514);
// let mut temp = BytesMut::with_capacity(1514); // let mut temp = BytesMut::with_capacity(1514);
let mut data_buf = temp.split_off(14); let mut data_buf = temp.split_off(14);
let Ok(size) = eee.device.recv(&mut data_buf).await else {
let Ok(size) = eee.device.recv(&mut data_buf) else {
return BytesMut::new(); return BytesMut::new();
}; };
data_buf.truncate(size); data_buf.truncate(size);
temp.unsplit(data_buf); temp.unsplit(data_buf);
temp temp
} }
#[cfg(not(feature = "tun"))] #[cfg(not(feature = "tun"))]
fn get_data_from_tap_with_layer2(eee: &Node) -> BytesMut { async fn get_data_from_tap_with_layer2(eee: &Node) -> BytesMut {
let mut buf = BytesMut::zeroed(1514); let mut buf = BytesMut::zeroed(1514);
let Ok(size) = eee.device.recv(&mut buf) else { let Ok(size) = eee.device.recv(&mut buf).await else {
return BytesMut::new(); return BytesMut::new();
}; };
buf.truncate(size); buf.truncate(size);
@ -318,16 +324,14 @@ fn get_data_from_tap_with_layer2(eee: &Node) -> BytesMut {
async fn get_tun_flow(eee: &'static Node, tx: Sender<BytesMut>) { async fn get_tun_flow(eee: &'static Node, tx: Sender<BytesMut>) {
loop { loop {
let buf = tokio::task::spawn_blocking(|| { let buf = {
#[cfg(any(feature = "tun", target_os = "windows"))] #[cfg(any(feature = "tun", target_os = "windows"))]
let data = get_data_from_tun_with_layer2_zeroed(eee); let data = get_data_from_tun_with_layer2_zeroed(eee).await;
#[cfg(all(not(feature = "tun"), not(target_os = "windows")))] #[cfg(all(not(feature = "tun"), not(target_os = "windows")))]
let data = get_data_from_tap_with_layer2(eee); let data = get_data_from_tap_with_layer2(eee).await;
data data
}) };
.await
.unwrap();
if buf.len() == 0 { if buf.len() == 0 {
return; return;
@ -367,11 +371,7 @@ async fn edge_send_packet_to_net(eee: &Node, data: BytesMut) {
return; return;
} }
*/ */
if let Err(e) = eee if let Err(e) = eee.device.handle_packet_from_device(data).await {
.device
.handle_packet_from_device(data)
.await
{
error!("failed to handle packet from device: {}", e.to_string()); error!("failed to handle packet from device: {}", e.to_string());
} }
} }

View File

@ -17,16 +17,17 @@ use tokio::sync::mpsc::Sender;
use tracing::{debug, error, warn}; use tracing::{debug, error, warn};
use crate::network::{ArpTable, RouteTable2}; use crate::network::{ArpTable, RouteTable2};
use crate::utils::DynamicDNSClient;
use crate::pb::{ use crate::pb::{
encode_to_tcp_message, encode_to_udp_message, SdlArpRequest, SdlEmpty, SdlStunProbe, encode_to_tcp_message, encode_to_udp_message, SdlArpRequest, SdlEmpty, SdlStunProbe,
SdlStunProbeReply, SdlStunProbeReply,
}; };
use crate::quic::quic_init; use crate::quic::quic_init;
use crate::tcp::{get_quic_write_conn, NatType, PacketType, StunProbeAttr}; use crate::tcp::{get_quic_write_conn, NatType, PacketType, StunProbeAttr};
use crate::utils::DynamicDNSClient;
use crate::utils::Socket; use crate::utils::Socket;
use crate::{ use crate::{
CommandLine, ConnectionInfo, DNSMatcher, ErrorReport, ErrorSeverity, MyEncryptor, RuleCache, get_base_dir, get_default_interface get_base_dir, get_default_interface, CommandLine, ConnectionInfo, DNSMatcher, ErrorReport,
ErrorSeverity, MyEncryptor, RuleCache,
}; };
use sdlan_sn_rs::peer::{IpSubnet, V6Info}; use sdlan_sn_rs::peer::{IpSubnet, V6Info};
@ -111,27 +112,23 @@ pub async fn init_edge(
// let tcpsock = TCPSocket::build("121.4.79.234:1234").await?; // let tcpsock = TCPSocket::build("121.4.79.234:1234").await?;
let tcp_pong = Arc::new(AtomicU64::new(0)); let tcp_pong = Arc::new(AtomicU64::new(0));
let iface = match new_iface("dev") {
let mode = if cfg!(not(feature = "tun")) {
Mode::Tap
} else {
Mode::Tun
};
let iface = match new_iface("dev", mode) {
Ok(iface) => iface, Ok(iface) => iface,
Err(e) => { Err(e) => {
if let Some(ref chan) = error_report_channel { if let Some(ref chan) = error_report_channel {
println!("sending one panic"); println!("sending one panic");
chan.send(ErrorReport { severity: ErrorSeverity::Panic, message: e.to_string() }).await; chan.send(ErrorReport {
severity: ErrorSeverity::Panic,
message: e.to_string(),
})
.await;
return Err(e.into()); return Err(e.into());
} else { } else {
panic!("new iface failed: {}", e.to_string()); panic!("new iface failed: {}", e.to_string());
} }
}, }
}; };
let edge = Node::new( let edge = Node::new(
mac, mac,
pubkey, pubkey,
@ -320,7 +317,6 @@ pub struct Node {
//cookie_match: DashMap<u32, oneshot::Sender<SdlStunProbeReply>>, //cookie_match: DashMap<u32, oneshot::Sender<SdlStunProbeReply>>,
pub cookie_match: Queryer, pub cookie_match: Queryer,
// packet_id_match: DashMap<u32, oneshot::Sender<RegisterSuperFeedback>>, // packet_id_match: DashMap<u32, oneshot::Sender<RegisterSuperFeedback>>,
exclusive_tcp: TcpListener, exclusive_tcp: TcpListener,
} }
@ -478,7 +474,6 @@ impl Node {
virtual_iface: Iface, virtual_iface: Iface,
tcp_listener: TcpListener, tcp_listener: TcpListener,
) -> Self { ) -> Self {
Self { Self {
#[cfg(any(feature = "tun", target_os = "windows"))] #[cfg(any(feature = "tun", target_os = "windows"))]
arp_table: ArpTable::new(), arp_table: ArpTable::new(),

View File

@ -550,7 +550,7 @@ pub async fn check_peer_registration_needed(
_v6_info: &Option<V6Info>, _v6_info: &Option<V6Info>,
peer_sock: &SdlanSock, peer_sock: &SdlanSock,
) { ) {
let p = eee.known_peers.peers.get(&src_mac); let mut p = eee.known_peers.peers.get_mut(&src_mac);
let last_seen; let last_seen;
let now; let now;
match p { match p {
@ -561,7 +561,7 @@ pub async fn check_peer_registration_needed(
return; return;
// unimplemented!(); // unimplemented!();
} }
Some(k) => { Some(ref mut k) => {
// let mut ipv4_to_ipv6 = false; // let mut ipv4_to_ipv6 = false;
now = get_current_timestamp(); now = get_current_timestamp();
if !from_sn { if !from_sn {
@ -569,8 +569,14 @@ pub async fn check_peer_registration_needed(
} }
let origin_family = k.sock.family; let origin_family = k.sock.family;
if origin_family != peer_sock.family { if origin_family != peer_sock.family {
if peer_sock.family == AF_INET6 && origin_family == AF_INET {
info!("Upgrading peer {} from IPv4 to IPv6 P2P", mac_to_string(&src_mac));
k.sock = peer_sock.deepcopy();
k.last_seen.store(now, Ordering::Relaxed);
} else {
return; return;
} }
}
/* /*
if peer_sock.family == AF_INET6 && k.sock.read().unwrap().family == AF_INET { if peer_sock.family == AF_INET6 && k.sock.read().unwrap().family == AF_INET {
println!("changing to ipv6"); println!("changing to ipv6");

View File

@ -15,6 +15,8 @@ use sdlan_sn_rs::utils::{ip_to_string, is_ipv6_multicast, net_bit_len_to_mask, M
use std::ffi::CStr; use std::ffi::CStr;
use std::ffi::{c_char, c_int}; use std::ffi::{c_char, c_int};
use std::fs::{self, OpenOptions}; use std::fs::{self, OpenOptions};
#[cfg(feature = "tun")]
use std::hint::L3;
#[cfg(not(feature = "tun"))] #[cfg(not(feature = "tun"))]
use std::net::IpAddr; use std::net::IpAddr;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
@ -25,7 +27,7 @@ use std::sync::atomic::Ordering;
use sdlan_sn_rs::utils::Result; use sdlan_sn_rs::utils::Result;
use std::io::{BufRead, BufReader, ErrorKind, Read, Write}; use std::io::{BufRead, BufReader, ErrorKind, Read, Write};
use std::os::fd::AsRawFd; use std::os::fd::{AsFd, AsRawFd};
use std::process::Command; use std::process::Command;
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
@ -33,11 +35,11 @@ use tracing::{debug, error, info, warn};
#[cfg(feature = "tun")] #[cfg(feature = "tun")]
use crate::caculate_crc; use crate::caculate_crc;
use crate::get_edge; use crate::get_edge;
#[cfg(feature = "tun")]
use crate::network::parse_dns_payload;
#[cfg(not(feature = "tun"))] #[cfg(not(feature = "tun"))]
use crate::network::{parse_dns_payload, ArpHdr, EthHdr, ARP_REPLY}; use crate::network::{parse_dns_payload, ArpHdr, EthHdr, ARP_REPLY};
use crate::network::{send_packet_to_net, Node}; #[cfg(feature = "tun")]
use crate::network::{parse_dns_payload, LAYER};
use crate::network::{send_packet_to_net, Node, LAYER};
#[cfg(not(feature = "tun"))] #[cfg(not(feature = "tun"))]
use crate::pb::SdlArpResponse; use crate::pb::SdlArpResponse;
#[cfg(feature = "tun")] #[cfg(feature = "tun")]
@ -52,97 +54,46 @@ const RESOLV_FILE: &'static str = "/etc/resolv.conf";
const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak"; const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak";
use crate::network::DNS_IP; use crate::network::DNS_IP;
// #[link(name = "tuntap", kind="static")]
#[link(name = "tuntap")]
extern "C" {
fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int;
}
#[allow(unused)] #[allow(unused)]
pub struct Iface { pub struct Iface {
fd: std::fs::File, dev: tun_rs::AsyncDevice,
mode: Mode,
name: String, name: String,
has_resolvectl: bool, has_resolvectl: bool,
} }
pub fn new_iface(tunname: &str, mode: Mode) -> std::io::Result<Iface> { pub fn new_iface(tunname: &str) -> std::io::Result<Iface> {
match Iface::without_packet_info(tunname, mode) { match tun_rs::DeviceBuilder::new()
Err(e) => { // .offload(true)
error!("failed to create tun: {}", e.as_str()); .layer(LAYER)
Err(std::io::Error::new(ErrorKind::Other, "failed to create virtial device, is run with root?")) .enable(true)
.name(tunname)
.mtu(1280)
.packet_information(false)
.build_async()
{
Ok(dev) => {
let name = dev.name().unwrap().clone();
Ok(Iface {
dev,
name,
has_resolvectl: check_has_resolvectl(),
})
}
Err(e) => {
error!("failed to create tun: {}", e);
Err(std::io::Error::new(
ErrorKind::Other,
"failed to create virtial device, is run with root?",
))
} }
Ok(iface) => Ok(iface),
} }
} }
impl Iface { impl Iface {
pub fn get_if_idx(&self) -> u32 { pub fn get_if_idx(&self) -> u32 {
0 0
} }
#[allow(unused)]
pub fn with_packet_info(ifname: &str, mode: Mode) -> Result<Self> {
Iface::open_tun(ifname, mode, true)
}
pub fn without_packet_info(ifname: &str, mode: Mode) -> Result<Self> {
Iface::open_tun(ifname, mode, false)
}
fn open_tun(ifname: &str, mode: Mode, need_packet_info: bool) -> Result<Self> {
let fs = match OpenOptions::new()
.read(true)
.write(true)
.open("/dev/net/tun")
{
Ok(fs) => fs,
Err(e) => panic!("failed to open tun: {}", e),
};
let mut name_ptr: *mut u8 = null_mut();
let mut success = false;
let mut _name = Vec::new();
for i in 0..16 {
_name.clear();
_name.extend_from_slice(ifname.as_bytes());
_name.extend_from_slice(i.to_string().as_bytes());
_name.extend_from_slice(&[0; 33]);
name_ptr = _name.as_mut_ptr();
let result = unsafe {
tuntap_setup(
fs.as_raw_fd(),
name_ptr,
mode as c_int,
if need_packet_info { 1 } else { 0 },
)
};
if result >= 0 {
success = true;
break;
}
}
if success {
let name = unsafe {
CStr::from_ptr(name_ptr as *const c_char)
.to_string_lossy()
.into_owned()
};
let has_resolvectl = check_has_resolvectl();
Ok(Iface {
fd: fs,
mode,
name,
has_resolvectl,
})
} else {
Err(SDLanError::NormalError("failed to setup tun"))
}
}
pub fn reload_config(&self, node: &Node, device_config: &DeviceConfig, network_domain: &str) { pub fn reload_config(&self, node: &Node, device_config: &DeviceConfig, network_domain: &str) {
let netbit = device_config.get_net_bit(); let netbit = device_config.get_net_bit();
let ip = device_config.get_ip(); let ip = device_config.get_ip();
@ -197,7 +148,13 @@ impl Iface {
} }
// TODO: set dns should be opened // TODO: set dns should be opened
if let Err(e) = set_dns(self, node.take_over_dns, &self.name, network_domain, &ip_to_string(&default_gw)) { if let Err(e) = set_dns(
self,
node.take_over_dns,
&self.name,
network_domain,
&ip_to_string(&default_gw),
) {
error!("failed to set dns: {}", e.as_str()); error!("failed to set dns: {}", e.as_str());
} }
} else { } else {
@ -224,18 +181,24 @@ impl Iface {
} }
} }
if let Err(e) = set_dns(self, node.take_over_dns, &self.name, network_domain, &ip_to_string(&default_gw)) { if let Err(e) = set_dns(
self,
node.take_over_dns,
&self.name,
network_domain,
&ip_to_string(&default_gw),
) {
error!("failed to set dns: {}", e.as_str()); error!("failed to set dns: {}", e.as_str());
} }
} }
} }
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> { pub async fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
(&self.fd).read(buf) self.dev.recv(buf).await
} }
pub fn send(&self, content: &[u8]) -> std::io::Result<usize> { pub async fn send(&self, content: &[u8]) -> std::io::Result<usize> {
(&self.fd).write(content) self.dev.send(content).await
} }
} }
@ -243,7 +206,7 @@ impl Iface {
impl TunTapPacketHandler for Iface { impl TunTapPacketHandler for Iface {
async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> { async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> {
// debug!("in tap mode, got data: {:?}", data); // debug!("in tap mode, got data: {:?}", data);
match self.send(data) { match self.send(data).await {
Err(e) => { Err(e) => {
error!("failed to write to tap: {}", e.to_string()); error!("failed to write to tap: {}", e.to_string());
return Err(e); return Err(e);
@ -252,158 +215,6 @@ impl TunTapPacketHandler for Iface {
} }
} }
#[cfg(feature = "abc")]
async fn handle_packet_from_device(
&self,
data: BytesMut,
// encrypt_key: &[u8],
) -> std::io::Result<()> {
use etherparse::PacketHeaders;
debug!("in tap mode2");
let edge = get_edge();
let Ok(headers) = PacketHeaders::from_ethernet_slice(&data) else {
error!("failed to parse packet");
return Ok(());
};
if let Some(eth) = headers.link {
use etherparse::EtherType;
if let Some(hdr) = eth.ethernet2() {
use bytes::Bytes;
if hdr.ether_type == EtherType::ARP {
use crate::network::{ArpHdr, ARP_REQUEST};
let arp = ArpHdr::from_slice(&data);
match arp.opcode {
ARP_REQUEST => {
let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32;
if edge.device_config.contains(&Ipv4Addr::from_bits(dest_ip)) {
let _ = edge.send_arp_request(dest_ip, dest_ip).await;
} else {
if let Some((_, real_ip)) = edge.route_table.lookup(dest_ip) {
let real_ip = u32::from_be_bytes(real_ip.octets());
let _ = edge.send_arp_request(dest_ip, real_ip).await;
}
}
/*
let request = SdlArpRequest {
pkt_id: edge.get_next_packet_id(),
target_ip: dest_ip,
};
let req = encode_to_tcp_message(Some(request), PacketType::ArpRequest as u8).unwrap();
let conn = get_quic_write_conn();
debug!("sending arp request");
let _ = conn.send(req).await;
*/
return Ok(());
}
_other => {
// just do the following logic
}
}
}
if let Some(ip) = headers.net {
match ip {
etherparse::NetHeaders::Ipv4(ipv4, _) => {
use crate::FiveTuple;
use etherparse::IpNumber;
if let Some(transport) = headers.transport {
match ipv4.protocol {
IpNumber::TCP => {
if let Some(tcp) = transport.tcp() {
let out_five_tuple = FiveTuple {
src_ip: ipv4.source.into(),
dst_ip: ipv4.destination.into(),
src_port: tcp.source_port,
dst_port: tcp.destination_port,
proto: IpNumber::TCP.0,
};
edge.rule_cache.touch_packet(out_five_tuple);
}
// is tcp
}
IpNumber::UDP => {
if let Some(udp) = transport.udp() {
let out_five_tuple = FiveTuple {
src_ip: ipv4.source.into(),
dst_ip: ipv4.destination.into(),
src_port: udp.source_port,
dst_port: udp.destination_port,
proto: IpNumber::UDP.0,
};
edge.rule_cache.touch_packet(out_five_tuple);
}
}
_other => {}
}
}
if u32::from_be_bytes(ipv4.destination) == DNS_IP {
// should send to dns
parse_dns_payload(edge, &headers.payload.slice());
if let Err(e) = edge
.udp_sock_for_dns
.send_to(&data[14..], format!("{}:15353", edge.server_ip))
.await
{
error!("failed to send request to 15353: {}", e);
}
// edge.udp_sock_for_dns.send_to()
return Ok(());
}
}
_other => {
// just ignore
}
}
}
let target = hdr.destination;
if is_ipv6_multicast(&target) {
return Ok(());
}
let size = data.len();
let Ok(encrypted) = edge.encryptor.load().encrypt(&data) else {
// let Ok(encrypted) = edge.encryptor.read().unwrap().encrypt(&data) else {
// let Ok(encrypted) = aes_encrypt(encrypt_key, &data) else {
error!("failed to encrypt packet request");
return Ok(());
};
let data_bytes = Bytes::from(encrypted);
let data = SdlData {
is_p2p: true,
network_id: edge.network_id.load(Ordering::Relaxed),
ttl: SDLAN_DEFAULT_TTL as u32,
src_mac: Vec::from(edge.device_config.get_mac()),
dst_mac: Vec::from(target),
data: data_bytes,
identity_id: edge.identity_id.load(),
session_token: edge.session_token.get(),
};
let msg = encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap();
send_packet_to_net(edge, target, &msg, size as u64).await;
} else {
error!("erro 2");
}
} else {
error!("erro 1");
}
Ok(())
}
async fn handle_packet_from_device( async fn handle_packet_from_device(
&self, &self,
data: BytesMut, data: BytesMut,
@ -433,7 +244,7 @@ impl TunTapPacketHandler for Iface {
if dest_ip == DNS_IP { if dest_ip == DNS_IP {
error!("got dns ip"); error!("got dns ip");
edge.device_config.dns_mac; edge.device_config.dns_mac;
write_arp_to_device(edge, edge.device_config.dns_mac, DNS_IP); write_arp_to_device(edge, edge.device_config.dns_mac, DNS_IP).await;
return Ok(()); return Ok(());
} }
@ -906,26 +717,39 @@ fn add_resolvectl(name: &str, network_domain: &str) -> Result<()> {
.arg("dns") .arg("dns")
.arg(name) .arg(name)
.arg("100.100.100.100") .arg("100.100.100.100")
.output()?.status.success() { .output()?
.status
.success()
{
error!("faield to run resolvectl dns"); error!("faield to run resolvectl dns");
return Err(SDLanError::IOError("failed to resolvectl dns".to_owned())) return Err(SDLanError::IOError("failed to resolvectl dns".to_owned()));
} }
if !Command::new("resolvectl") if !Command::new("resolvectl")
.arg("domain") .arg("domain")
.arg(name) .arg(name)
// .arg(format!("~{}", network_domain)) // .arg(format!("~{}", network_domain))
.arg("~.") .arg("~.")
.output()?.status.success() { .output()?
.status
.success()
{
error!("failed to run resolvectl domain"); error!("failed to run resolvectl domain");
return Err(SDLanError::IOError("failed to resolvectl domain".to_owned())) return Err(SDLanError::IOError(
"failed to resolvectl domain".to_owned(),
));
} }
Ok(()) Ok(())
} }
fn set_dns(iface: &Iface, take_over_dns: bool, name: &str, network_domain: &str, gw: &str) -> Result<()> { fn set_dns(
iface: &Iface,
take_over_dns: bool,
name: &str,
network_domain: &str,
gw: &str,
) -> Result<()> {
error!("network_domain = {}", network_domain); error!("network_domain = {}", network_domain);
if iface.has_resolvectl { if iface.has_resolvectl {
add_resolvectl(name, network_domain)?; add_resolvectl(name, network_domain)?;
@ -1126,9 +950,11 @@ pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
.arg(net.to_string()) .arg(net.to_string())
.arg("gw") .arg("gw")
.arg(gw.to_string()) .arg(gw.to_string())
.output()?.status.success() { .output()?
.status
return Err(SDLanError::IOError("failed to delete route".to_owned())) .success()
{
return Err(SDLanError::IOError("failed to delete route".to_owned()));
} }
Ok(()) Ok(())
@ -1141,8 +967,11 @@ pub fn add_route(net: &Ipv4Net, gw: &Ipv4Addr, _ifidx: u32) -> Result<()> {
.arg(net.to_string()) .arg(net.to_string())
.arg("gw") .arg("gw")
.arg(gw.to_string()) .arg(gw.to_string())
.output()?.status.success() { .output()?
return Err(SDLanError::IOError("failed to delete route".to_owned())) .status
.success()
{
return Err(SDLanError::IOError("failed to delete route".to_owned()));
} }
Ok(()) Ok(())
@ -1152,9 +981,13 @@ pub fn set_disallow_routing() -> Result<()> {
if !Command::new("sysctl") if !Command::new("sysctl")
.arg("-w") .arg("-w")
.arg("net.ipv4.ip_forward=0") .arg("net.ipv4.ip_forward=0")
.output()?.status.success() { .output()?
.status
return Err(SDLanError::IOError("failed to set ip_forward to 0".to_owned())) .success()
{
return Err(SDLanError::IOError(
"failed to set ip_forward to 0".to_owned(),
));
} }
if !Command::new("iptables") if !Command::new("iptables")
@ -1164,9 +997,13 @@ pub fn set_disallow_routing() -> Result<()> {
.arg("POSTROUTING") .arg("POSTROUTING")
.arg("-j") .arg("-j")
.arg("MASQUERADE") .arg("MASQUERADE")
.output()?.status.success() { .output()?
.status
return Err(SDLanError::IOError("failed to delete masquerade".to_owned())) .success()
{
return Err(SDLanError::IOError(
"failed to delete masquerade".to_owned(),
));
} }
Ok(()) Ok(())
@ -1176,8 +1013,13 @@ pub fn set_allow_routing() -> Result<()>{
if !Command::new("sysctl") if !Command::new("sysctl")
.arg("-w") .arg("-w")
.arg("net.ipv4.ip_forward=1") .arg("net.ipv4.ip_forward=1")
.output()?.status.success() { .output()?
return Err(SDLanError::IOError("failed to set ip_forward to 1".to_owned())) .status
.success()
{
return Err(SDLanError::IOError(
"failed to set ip_forward to 1".to_owned(),
));
} }
if !Command::new("iptables") if !Command::new("iptables")
@ -1187,9 +1029,11 @@ pub fn set_allow_routing() -> Result<()>{
.arg("POSTROUTING") .arg("POSTROUTING")
.arg("-j") .arg("-j")
.arg("MASQUERADE") .arg("MASQUERADE")
.output()?.status.success() { .output()?
.status
return Err(SDLanError::IOError("failed to clear masquerade".to_owned())) .success()
{
return Err(SDLanError::IOError("failed to clear masquerade".to_owned()));
} }
if !Command::new("iptables") if !Command::new("iptables")
@ -1199,8 +1043,11 @@ pub fn set_allow_routing() -> Result<()>{
.arg("POSTROUTING") .arg("POSTROUTING")
.arg("-j") .arg("-j")
.arg("MASQUERADE") .arg("MASQUERADE")
.output()?.status.success() { .output()?
return Err(SDLanError::IOError("failed to add masquerade".to_owned())) .status
.success()
{
return Err(SDLanError::IOError("failed to add masquerade".to_owned()));
} }
Ok(()) Ok(())
} }
@ -1242,11 +1089,11 @@ pub async fn arp_reply_arrived(edge: &Node, data: SdlArpResponse) {
let src_ip = data.origin_ip; let src_ip = data.origin_ip;
write_arp_to_device(edge, src_mac, src_ip); write_arp_to_device(edge, src_mac, src_ip).await;
} }
#[cfg(not(feature = "tun"))] #[cfg(not(feature = "tun"))]
pub fn write_arp_to_device(edge: &Node, src_mac: Mac, src_ip: u32) { pub async fn write_arp_to_device(edge: &Node, src_mac: Mac, src_ip: u32) {
let dst_mac = edge.device_config.get_mac(); let dst_mac = edge.device_config.get_mac();
let dst_ip = edge.device_config.get_ip(); let dst_ip = edge.device_config.get_ip();
@ -1271,7 +1118,7 @@ pub fn write_arp_to_device(edge: &Node, src_mac: Mac, src_ip: u32) {
}; };
let data = hdr.marshal_to_bytes(); let data = hdr.marshal_to_bytes();
if let Err(_e) = edge.device.send(&data) { if let Err(_e) = edge.device.send(&data).await {
error!("failed to write arp response to device"); error!("failed to write arp response to device");
} }
} }

View File

@ -4,7 +4,8 @@ use etherparse::{Ethernet2Header, IpHeaders, NetSlice, SlicedPacket, TransportSl
use ipnet::Ipv4Net; use ipnet::Ipv4Net;
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL; use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
use sdlan_sn_rs::utils::{ use sdlan_sn_rs::utils::{
BROADCAST_MAC, Result, SDLanError, aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask, Result, SDLanError,
BROADCAST_MAC,
}; };
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
@ -13,11 +14,12 @@ use std::process::Command;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use tun_rs::AsyncDevice;
use wintun; use wintun;
use crate::network::{ use crate::network::{
form_ethernet_packet, generate_arp_request, parse_dns_payload, send_packet_to_net, ArpHdr, form_ethernet_packet, generate_arp_request, parse_dns_payload, send_packet_to_net, ArpHdr,
Node, ARP_REPLY, ARP_REQUEST, DNS_IP, Node, ARP_REPLY, ARP_REQUEST, DNS_IP, LAYER,
}; };
use crate::pb::{encode_to_udp_message, SdlArpResponse, SdlData}; use crate::pb::{encode_to_udp_message, SdlArpResponse, SdlData};
use crate::tcp::PacketType; use crate::tcp::PacketType;
@ -28,13 +30,131 @@ use super::device::{DeviceConfig, Mode};
use super::TunTapPacketHandler; use super::TunTapPacketHandler;
pub struct Iface { pub struct Iface {
device: AsyncDevice,
if_idx: u32,
name: String,
}
impl Iface {
fn new(path: &str, name: &str) -> Self {
let dev = tun_rs::DeviceBuilder::new()
.wintun_file(path.to_string())
.name(name)
.layer(LAYER)
.mtu(1280)
.build_async()
.expect("failed to create tun");
let idx = dev.if_index().expect("failed to get if index");
Self {
device: dev,
if_idx: idx,
name: name.to_string(),
}
}
}
impl Iface {
pub fn get_if_idx(&self) -> u32 {
self.if_idx
}
pub async fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
self.device.recv(buf).await
}
pub async fn send(&self, content: &[u8]) -> std::io::Result<usize> {
self.device.send(content).await
}
pub fn reload_config(&self, node: &Node, device_config: &DeviceConfig, network_domain: &str) {
let netbit = device_config.get_net_bit();
let ip = device_config.get_ip();
if netbit == 0 || ip == 0 {
error!("reload config's ip is 0");
return;
}
let mask = net_bit_len_to_mask(netbit);
let ip = ip_to_string(&ip);
let netbit = ip_to_string(&net_bit_len_to_mask(netbit));
let mut cmd = Command::new("netsh");
debug!("name={}, addr={}, mask={}", self.name, ip, netbit);
let command = cmd
.creation_flags(0x08000000)
.arg("interface")
.arg("ip")
.arg("set")
.arg("address")
.arg(&format!("name=\"{}\"", self.name))
.arg("source=static")
.arg(&format!("addr={}", ip))
.arg(&format!("mask={}", netbit));
let res = command.status();
// let res = command.output();
match res {
Ok(r) => {
if r.success() {
debug!("netsh ok");
} else {
error!("failed to run netsh, returned {:?}", r.code())
}
}
Err(e) => {
error!("failed to run netsh: {}", e.to_string());
}
}
let mut cmd = Command::new("netsh");
let command = cmd
.creation_flags(0x08000000)
.arg("interface")
.arg("ipv4")
.arg("set")
.arg("subinterface")
.arg(&format!("\"{}\"", self.name))
.arg(format!("mtu={}", device_config.mtu))
.arg("store=persistent");
let res = command.status();
match res {
Ok(r) => {
if r.success() {
debug!("netsh2 ok");
} else {
error!("failed to run netsh set mtu, returned {:?}", r.code())
}
}
Err(e) => {
error!("failed to run netsh2: {}", e.to_string());
}
}
// let gw = ip_to_string(&default_gw);
// debug!("gw = {}", ip);
if let Err(e) = set_dns(&self.name, network_domain, &ip, self.if_idx) {
error!("failed to set dns: {:?}", e);
} else {
debug!("set dns ok");
}
node.route_table.apply_system(self.if_idx);
}
}
pub struct IfaceOld {
if_idx: u32, if_idx: u32,
name: String, name: String,
_adapter: Arc<wintun::Adapter>, _adapter: Arc<wintun::Adapter>,
session: Arc<wintun::Session>, session: Arc<wintun::Session>,
} }
impl Iface { impl IfaceOld {
pub fn get_if_idx(&self) -> u32 { pub fn get_if_idx(&self) -> u32 {
self.if_idx self.if_idx
} }
@ -55,11 +175,12 @@ impl Iface {
} }
pub fn send(&self, content: &[u8]) -> std::io::Result<usize> { pub fn send(&self, content: &[u8]) -> std::io::Result<usize> {
let Ok(mut pkt) = self let Ok(mut pkt) = self.session.allocate_send_packet(content.len() as u16) else {
.session
.allocate_send_packet(content.len() as u16) else {
error!("failed to allocate send packet"); error!("failed to allocate send packet");
return Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to allocate send packet")); return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to allocate send packet",
));
}; };
let buf: &mut [u8] = pkt.bytes_mut(); let buf: &mut [u8] = pkt.bytes_mut();
buf.copy_from_slice(content); buf.copy_from_slice(content);
@ -310,7 +431,7 @@ impl TunTapPacketHandler for Iface {
// println!("got ip packet"); // println!("got ip packet");
// println!("got data: {:?}", rest); // println!("got data: {:?}", rest);
match edge.device.send(rest) { match edge.device.send(rest).await {
Ok(size) => { Ok(size) => {
debug!("send to tun {} bytes", size); debug!("send to tun {} bytes", size);
} }
@ -730,13 +851,18 @@ impl TunTapPacketHandler for Iface {
} }
fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> { fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
Ok(Iface::new(path, name))
/*
let wt = unsafe { wintun::load_from_path(path) }.expect("failed to load wintun"); let wt = unsafe { wintun::load_from_path(path) }.expect("failed to load wintun");
let adapter = match wintun::Adapter::open(&wt, name) { let adapter = match wintun::Adapter::open(&wt, name) {
Ok(a) => a, Ok(a) => a,
Err(_e) => { Err(_e) => {
let Ok(adapt) = wintun::Adapter::create(&wt, name, "Punchnet", None) else { let Ok(adapt) = wintun::Adapter::create(&wt, name, "Punchnet", None) else {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to create Punch adapter")); return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to create Punch adapter",
));
}; };
adapt adapt
} }
@ -746,7 +872,10 @@ fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
.expect("failed to get adapter index"); .expect("failed to get adapter index");
// println!("idx = {}", idx); // println!("idx = {}", idx);
let Ok(sess) = adapter.start_session(wintun::MAX_RING_CAPACITY) else { let Ok(sess) = adapter.start_session(wintun::MAX_RING_CAPACITY) else {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to start session, maybe one process is running, or not running with admin?")); return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to start session, maybe one process is running, or not running with admin?",
));
}; };
let session = Arc::new(sess); let session = Arc::new(sess);
Ok(Iface { Ok(Iface {
@ -755,6 +884,7 @@ fn create_wintun(path: &str, name: &str) -> std::io::Result<Iface> {
session, session,
name: name.to_owned(), name: name.to_owned(),
}) })
*/
} }
pub fn new_iface(name: &str, _mode: Mode) -> std::io::Result<Iface> { pub fn new_iface(name: &str, _mode: Mode) -> std::io::Result<Iface> {
@ -778,8 +908,13 @@ pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> Resul
.creation_flags(0x08000000) .creation_flags(0x08000000)
.status()?; .status()?;
if !res.success() { if !res.success() {
error!("failed to add route for dns 100.100.100.100: {:?}", res.code()); error!(
return Err(SDLanError::IOError("failed to add route for dns".to_owned())); "failed to add route for dns 100.100.100.100: {:?}",
res.code()
);
return Err(SDLanError::IOError(
"failed to add route for dns".to_owned(),
));
} }
//println!("res1: {}", res.status.success()); //println!("res1: {}", res.status.success());

View File

@ -8,9 +8,17 @@ use sdlan_sn_rs::{
utils::{get_current_timestamp, ip_to_string, Mac, Result}, utils::{get_current_timestamp, ip_to_string, Mac, Result},
}; };
#[cfg(feature = "tun")]
pub const LAYER: tun_rs::Layer = tun_rs::Layer::L3;
#[cfg(not(feature = "tun"))]
pub const LAYER: tun_rs::Layer = tun_rs::Layer::L2;
use tracing::{debug, warn}; use tracing::{debug, warn};
use tracing::error; use tracing::error;
#[cfg(feature = "tun")]
use tun_rs::Layer;
use crate::{ use crate::{
network::{form_ethernet_packet, send_packet_to_net, Node, RouteInfo}, network::{form_ethernet_packet, send_packet_to_net, Node, RouteInfo},

View File

@ -1,8 +1,10 @@
use std::{sync::atomic::{AtomicU32, Ordering}, time::{SystemTime, UNIX_EPOCH}}; use std::{
sync::atomic::{AtomicU32, Ordering},
time::{SystemTime, UNIX_EPOCH},
};
use chacha20poly1305::{aead::Aead, ChaCha20Poly1305, KeyInit};
use chacha20poly1305::{KeyInit, aead::Aead}; use sdlan_sn_rs::utils::{aes_decrypt, aes_encrypt, Result, SDLanError};
use sdlan_sn_rs::utils::{Result, SDLanError, aes_decrypt, aes_encrypt};
const COUNTER_MASK: u32 = (1 << 24) - 1; const COUNTER_MASK: u32 = (1 << 24) - 1;
@ -27,12 +29,8 @@ impl MyEncryptor {
pub fn is_setted(&self) -> bool { pub fn is_setted(&self) -> bool {
match self { match self {
Self::Invalid => false, Self::Invalid => false,
Self::Aes(aes) => { Self::Aes(aes) => aes.is_setted(),
aes.is_setted() Self::ChaChao20(cha) => cha.is_setted(),
}
Self::ChaChao20(cha) => {
cha.is_setted()
}
} }
} }
@ -50,33 +48,22 @@ impl MyEncryptor {
pub fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> { pub fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
match self { match self {
Self::Invalid => { Self::Invalid => Err(SDLanError::EncryptError("invalid encryptor".to_owned())),
Err(SDLanError::EncryptError("invalid encryptor".to_owned())) Self::Aes(aes) => aes.encrypt(data),
} Self::ChaChao20(cha) => cha.encrypt(data),
Self::Aes(aes) => {
aes.encrypt(data)
}
Self::ChaChao20(cha) => {
cha.encrypt(data)
}
} }
} }
pub fn decrypt(&self, ciphered: &[u8]) -> Result<Vec<u8>> { pub fn decrypt(&self, ciphered: &[u8]) -> Result<Vec<u8>> {
match self { match self {
Self::Invalid => { Self::Invalid => Err(SDLanError::EncryptError("invalid encryptor".to_owned())),
Err(SDLanError::EncryptError("invalid encryptor".to_owned())) Self::Aes(aes) => aes.decrypt(ciphered),
} Self::ChaChao20(cha) => cha.decrypt(ciphered),
Self::Aes(aes) => {
aes.decrypt(ciphered)
}
Self::ChaChao20(cha) => {
cha.decrypt(ciphered)
}
} }
} }
} }
pub struct Chacha20Encryptor { pub struct Chacha20Encryptor {
cipher: ChaCha20Poly1305,
key: Vec<u8>, key: Vec<u8>,
is_setted: bool, is_setted: bool,
next_counter: AtomicU32, next_counter: AtomicU32,
@ -86,6 +73,7 @@ pub struct Chacha20Encryptor {
impl Chacha20Encryptor { impl Chacha20Encryptor {
pub fn new(key: Vec<u8>, region_id: u32) -> Self { pub fn new(key: Vec<u8>, region_id: u32) -> Self {
Self { Self {
cipher: chacha20poly1305::ChaCha20Poly1305::new(key.as_slice().into()),
key, key,
is_setted: true, is_setted: true,
next_counter: AtomicU32::new(0), next_counter: AtomicU32::new(0),
@ -96,17 +84,24 @@ impl Chacha20Encryptor {
impl Encryptor for Chacha20Encryptor { impl Encryptor for Chacha20Encryptor {
fn set_key(&mut self, region_id: u32, key: Vec<u8>) { fn set_key(&mut self, region_id: u32, key: Vec<u8>) {
self.cipher = chacha20poly1305::ChaCha20Poly1305::new(key.as_slice().into());
self.key = key; self.key = key;
self.region_id = region_id; self.region_id = region_id;
} }
fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> { fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
let cipher = chacha20poly1305::ChaCha20Poly1305::new(self.key.as_slice().into()); // let cipher = chacha20poly1305::ChaCha20Poly1305::new(self.key.as_slice().into());
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64; let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
let next_counter = self.next_counter.fetch_update(Ordering::Release, Ordering::Acquire, |current| { let next_counter = self
.next_counter
.fetch_update(Ordering::Release, Ordering::Acquire, |current| {
Some((current + 1) & COUNTER_MASK) Some((current + 1) & COUNTER_MASK)
}).unwrap() as u64; })
.unwrap() as u64;
let mut nonce = Vec::new(); let mut nonce = Vec::new();
let region_id = self.region_id.to_be_bytes(); let region_id = self.region_id.to_be_bytes();
@ -114,28 +109,29 @@ impl Encryptor for Chacha20Encryptor {
let next_data = (now << 24) | next_counter; let next_data = (now << 24) | next_counter;
nonce.extend_from_slice(&next_data.to_be_bytes()); nonce.extend_from_slice(&next_data.to_be_bytes());
match cipher.encrypt(nonce.as_slice().into(), data) { match self.cipher.encrypt(nonce.as_slice().into(), data) {
Ok(data) => { Ok(data) => {
nonce.extend_from_slice(&data); nonce.extend_from_slice(&data);
Ok(nonce) Ok(nonce)
},
Err(e) => {
Err(SDLanError::EncryptError(e.to_string()))
} }
Err(e) => Err(SDLanError::EncryptError(e.to_string())),
} }
} }
fn decrypt(&self, ciphered: &[u8]) -> Result<Vec<u8>> { fn decrypt(&self, ciphered: &[u8]) -> Result<Vec<u8>> {
if ciphered.len() < 12 { if ciphered.len() < 12 {
return Err(SDLanError::EncryptError("ciphered text size error".to_owned())) return Err(SDLanError::EncryptError(
"ciphered text size error".to_owned(),
));
} }
let cipher = chacha20poly1305::ChaCha20Poly1305::new(self.key.as_slice().into()); // let cipher = chacha20poly1305::ChaCha20Poly1305::new(self.key.as_slice().into());
let nonce = &ciphered[0..12]; let nonce = &ciphered[0..12];
match cipher.decrypt(nonce.into(), &ciphered[12..]) { match self.cipher.decrypt(nonce.into(), &ciphered[12..]) {
Ok(data) => Ok(data), Ok(data) => Ok(data),
Err(e) => { Err(e) => Err(SDLanError::EncryptError(format!(
Err(SDLanError::EncryptError(format!("failed to decyrpt: {}", e.to_string()))) "failed to decyrpt: {}",
} e.to_string()
))),
} }
} }
@ -176,4 +172,3 @@ impl Encryptor for AesEncryptor {
self.is_setted = true; self.is_setted = true;
} }
} }