From 9b1710e590bd9c7f3d9889e8a6f792d3b17bdb05 Mon Sep 17 00:00:00 2001 From: asxalex Date: Wed, 23 Oct 2024 20:36:51 +0800 Subject: [PATCH] message --- Cargo.toml | 3 + Makefile | 5 +- message.proto | 18 +-- src/network/async_main.rs | 106 +----------------- src/network/node.rs | 8 +- src/network/packet.rs | 4 +- src/network/tun_linux.rs | 227 +++++++++++++++++++++++++++++++++++--- src/network/tuntap.rs | 3 +- src/pb/message.rs | 26 +---- 9 files changed, 240 insertions(+), 160 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6ce65bc..54d252d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,6 @@ tracing = "0.1.40" [target.'cfg(windows)'.dependencies] wintun = "0.4.0" + +[features] +tap = [] diff --git a/Makefile b/Makefile index a33e48a..dfad5c5 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ linux: - RUSTFLAGS="-L ." cargo build --release + RUSTFLAGS="-L ." cargo build --features "tap" --release + +linux-tun: + RUSTFLAGS="-L ." cargo build --features "tap" --release pb: cargo run --bin build_pb diff --git a/message.proto b/message.proto index cf45ab1..348fe24 100644 --- a/message.proto +++ b/message.proto @@ -38,10 +38,9 @@ message SDLRegisterSuper { message SDLRegisterSuperAck { SDLDevAddr dev_addr = 1; bytes aes_key = 2; - map known_macs = 3; - uint32 upgrade_type = 4; - optional string upgrade_prompt = 5; - optional string upgrade_address = 6; + uint32 upgrade_type = 3; + optional string upgrade_prompt = 4; + optional string upgrade_address = 5; } message SDLRegisterSuperNak { @@ -63,16 +62,6 @@ message SDLPeerInfo { // 事件定义 -message SDLKnownMacEvent { - bytes mac = 1; - uint32 ip = 2; -} - -message SDLDropMacEvent { - bytes mac = 1; - uint32 ip = 2; -} - message SDLNatChangedEvent { bytes mac = 1; uint32 ip = 2; @@ -94,7 +83,6 @@ message SDLNetworkShutdownEvent { message SDLChangeNetworkCommand { SDLDevAddr dev_addr = 1; bytes aes_key = 2; - map known_macs = 3; } message SDLCommandAck { diff --git a/src/network/async_main.rs b/src/network/async_main.rs index 681fb5c..9360156 100644 --- a/src/network/async_main.rs +++ b/src/network/async_main.rs @@ -7,7 +7,8 @@ use crate::config::{NULL_MAC, TCP_PING_TIME}; use crate::network::ipv6::run_ipv6; use crate::network::{ generate_arp_request, get_edge, ping_to_sn, read_and_parse_packet, send_arp_request, ArpHdr, - ArpRequestInfo, ArpResponse, RegisterSuperFeedback, ARP_REPLY, ARP_REQUEST, + ArpRequestInfo, ArpResponse, RegisterSuperFeedback, TunTapPacketHandler, ARP_REPLY, + ARP_REQUEST, }; use crate::pb::{ encode_to_tcp_message, encode_to_udp_message, SdlData, SdlDevAddr, SdlRegisterSuper, @@ -598,106 +599,9 @@ async fn edge_send_packet_to_net(eee: &Node, data: &[u8]) { error!("drop tun packet due to encrypt key len is 0"); return; } - let src_mac = eee.device_config.get_mac(); - - match IpHeaders::from_slice(&data) { - Ok((iphdr, _payload)) => { - let Some(ipv4hdr) = iphdr.ipv4() else { - debug!("ipv6 packet ignored"); - return; - }; - let dstip = u32::from_be_bytes(ipv4hdr.0.destination); - debug!("packet dst ip: {:?}", ipv4hdr.0.destination); - let src = u32::from_be_bytes(ipv4hdr.0.source); - debug!("packet src ip: {:?}", ipv4hdr.0.source); - // packet should be sent to dev - debug!("got {} bytes from tun", data.len()); - if (!eee.config.allow_routing) && (src != eee.device_config.get_ip()) { - info!("dropping routed packet"); - return; - } - if !eee.is_authorized() { - debug!("drop tun packet due to not authed"); - return; - } - match send_arp_request(ArpRequestInfo::Lookup { ip: dstip }).await { - ArpResponse::LookupResp { - mac, - ip, - do_arp_request, - } => { - if do_arp_request { - println!( - "find ip: {:?} => {:?}", - src.to_be_bytes(), - dstip.to_be_bytes() - ); - let arp_msg = generate_arp_request(src_mac, ip, eee.device_config.get_ip()); - let Ok(encrypted) = aes_encrypt(&encrypt_key, &arp_msg) else { - error!("failed to encrypt arp request"); - return; - }; - // println!("arp_msg: {:?}", arp_msg); - let data = SdlData { - network_id: eee.network_id.load(Ordering::Relaxed), - src_mac: Vec::from(src_mac), - dst_mac: Vec::from([0xff; 6]), - is_p2p: true, - ttl: SDLAN_DEFAULT_TTL as u32, - data: encrypted, - }; - let data = - encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); - debug!("sending arp"); - // let data = marshal_message(&data); - send_packet_to_net(eee, BROADCAST_MAC, &data, arp_msg.len() as u64).await; - // edge.sock.send(data).await; - // println!("should send arp"); - return; - } - - // prepend the ether header - let mut etherheader = Ethernet2Header::default(); - etherheader.destination = mac; - etherheader.ether_type = etherparse::EtherType::IPV4; - etherheader.source = src_mac; - let mut packet = Vec::with_capacity(14 + data.len() + 4); - packet.extend_from_slice(ðerheader.to_bytes()[..]); - packet.extend_from_slice(&data); - let crc = CRC_HASH.checksum(&packet); - packet.extend_from_slice(&crc.to_be_bytes()); - - let pkt_size = packet.len(); - // println!("sending data with mac"); - - let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { - error!("failed to encrypt packet request"); - return; - }; - let data = SdlData { - is_p2p: true, - network_id: eee.network_id.load(Ordering::Relaxed), - ttl: SDLAN_DEFAULT_TTL as u32, - src_mac: Vec::from(src_mac), - dst_mac: Vec::from(mac), - data: Vec::from(encrypted), - }; - let msg = encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); - let size = msg.len(); - send_packet_to_net(eee, mac, &msg, pkt_size as u64).await; - // let dstip = u32::from_be_bytes(ipv4hdr.0.destination); - println!( - "{:?} => {:?}, size={}", - ipv4hdr.0.source, ipv4hdr.0.destination, size - ); - } - _ => {} - } - } - Err(e) => { - error!("failed to parse ip packet: {}", e.to_string()); - } - } + eee.device + .handle_packet_from_device(data, encrypt_key.as_slice()) + .await; } pub async fn send_packet_to_net(eee: &Node, dst_mac: Mac, pkt: &[u8], size: u64) { diff --git a/src/network/node.rs b/src/network/node.rs index d81bc45..a2f79ba 100644 --- a/src/network/node.rs +++ b/src/network/node.rs @@ -242,6 +242,12 @@ impl Node { tcp_pong: Arc, start_stop: Sender, ) -> Self { + let mode = if cfg!(feature = "tap") { + Mode::Tap + } else { + Mode::Tun + }; + Self { packet_id: AtomicU32::new(1), network_id: AtomicU32::new(0), @@ -254,7 +260,7 @@ impl Node { nat_type: Mutex::new(NatType::Blocked), device_config: DeviceConfig::new(), - device: new_iface("dev", Mode::Tun), + device: new_iface("dev", mode), authorized: AtomicBool::new(false), encrypt_key: RwLock::new(Arc::new(Vec::new())), diff --git a/src/network/packet.rs b/src/network/packet.rs index 4601ee3..dc26199 100644 --- a/src/network/packet.rs +++ b/src/network/packet.rs @@ -746,7 +746,9 @@ async fn handle_tun_packet( } let data = origin.unwrap(); debug!("ether size is {}", data.len()); - eee.device.handle_packet(&data, key.as_slice()).await; + eee.device + .handle_packet_from_net(&data, key.as_slice()) + .await; /* let msg_size = data.len() as u64; diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index caa025b..c48dd94 100644 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -1,8 +1,10 @@ use etherparse::ether_type::ARP; use etherparse::{Ethernet2Header, IpHeaders}; +use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL; use sdlan_sn_rs::utils::{ - aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask, SDLanError, + aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask, SDLanError, BROADCAST_MAC, }; +use std::error::Error; use std::ffi::CStr; use std::ffi::{c_char, c_int}; use std::fs::OpenOptions; @@ -12,12 +14,15 @@ use std::sync::atomic::Ordering; use sdlan_sn_rs::utils::Result; use std::io::{Read, Write}; use std::os::fd::AsRawFd; -use std::process::Command; +use std::process::{Command, Output}; -use tracing::{debug, error}; +use tracing::{debug, error, info}; use crate::get_edge; -use crate::network::{send_arp_request, send_packet_to_net, ArpHdr, ArpRequestInfo, ARP_REPLY}; +use crate::network::{ + generate_arp_request, send_arp_request, send_packet_to_net, ArpHdr, ArpRequestInfo, + ArpResponse, ARP_REPLY, +}; use crate::pb::{encode_to_udp_message, SdlData}; use crate::tcp::PacketType; use crate::utils::{mac_to_string, CRC_HASH}; @@ -111,19 +116,46 @@ impl Iface { let ip = ip_to_string(&ip); let netbit = ip_to_string(&net_bit_len_to_mask(netbit)); - let res = Command::new("ifconfig") - .arg(&self.name) - .arg(ip) - .arg("netmask") - .arg(&netbit) - .arg("up") - .output(); - match res { - Ok(_) => { - debug!("ifconfig ok"); + if cfg!(feature = "tap") { + println!("set tap device"); + let mac = device_config.get_mac(); + let res = Command::new("ifconfig") + .arg(&self.name) + .arg(ip) + .arg("netmask") + .arg(&netbit) + .arg("hw") + .arg("ether") + .arg(format!( + "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] + )) + .arg("up") + .output(); + match res { + Ok(_) => { + debug!("ifconfig ok"); + } + Err(e) => { + error!("failed to run ifconfig: {}", e.to_string()); + } } - Err(e) => { - error!("failed to run ifconfig: {}", e.to_string()); + } else { + println!("set tun device"); + let res = Command::new("ifconfig") + .arg(&self.name) + .arg(ip) + .arg("netmask") + .arg(&netbit) + .arg("up") + .output(); + match res { + Ok(_) => { + debug!("ifconfig ok"); + } + Err(e) => { + error!("failed to run ifconfig: {}", e.to_string()); + } } } } @@ -137,8 +169,56 @@ impl Iface { } } +#[cfg(feature = "tap")] impl TunTapPacketHandler for Iface { - async fn handle_packet(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> { + async fn handle_packet_from_net(&self, data: &[u8], _: &[u8]) -> std::io::Result<()> { + debug!("in tap mode"); + match self.send(data) { + Err(e) => { + error!("failed to write to tap: {}", e.to_string()); + return Err(e); + } + Ok(_) => return Ok(()), + } + } + async fn handle_packet_from_device( + &self, + data: &[u8], + encrypt_key: &[u8], + ) -> std::io::Result<()> { + debug!("in tap mode2"); + let edge = get_edge(); + match Ethernet2Header::from_slice(data) { + Ok((hdr, _)) => { + let target = hdr.destination; + let size = data.len(); + + let Ok(encrypted) = aes_encrypt(encrypt_key, data) else { + error!("failed to encrypt packet request"); + return Ok(()); + }; + 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: Vec::from(encrypted), + }; + let msg = encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); + + send_packet_to_net(edge, target, &msg, size as u64).await; + } + Err(e) => {} + }; + Ok(()) + } +} + +#[cfg(not(feature = "tap"))] +impl TunTapPacketHandler for Iface { + async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> { + debug!("in tun mode"); // got layer 2 frame match Ethernet2Header::from_slice(&data) { Ok((hdr, rest)) => { @@ -287,6 +367,119 @@ impl TunTapPacketHandler for Iface { Ok(()) } + + async fn handle_packet_from_device( + &self, + data: &[u8], + encrypt_key: &[u8], + ) -> std::io::Result<()> { + let eee = get_edge(); + + let src_mac = eee.device_config.get_mac(); + + match IpHeaders::from_slice(&data) { + Ok((iphdr, _payload)) => { + let Some(ipv4hdr) = iphdr.ipv4() else { + debug!("ipv6 packet ignored"); + return Ok(()); + }; + let dstip = u32::from_be_bytes(ipv4hdr.0.destination); + debug!("packet dst ip: {:?}", ipv4hdr.0.destination); + let src = u32::from_be_bytes(ipv4hdr.0.source); + debug!("packet src ip: {:?}", ipv4hdr.0.source); + // packet should be sent to dev + debug!("got {} bytes from tun", data.len()); + if (!eee.config.allow_routing) && (src != eee.device_config.get_ip()) { + info!("dropping routed packet"); + return Ok(()); + } + if !eee.is_authorized() { + debug!("drop tun packet due to not authed"); + return Ok(()); + } + match send_arp_request(ArpRequestInfo::Lookup { ip: dstip }).await { + ArpResponse::LookupResp { + mac, + ip, + do_arp_request, + } => { + if do_arp_request { + println!( + "find ip: {:?} => {:?}", + src.to_be_bytes(), + dstip.to_be_bytes() + ); + let arp_msg = + generate_arp_request(src_mac, ip, eee.device_config.get_ip()); + let Ok(encrypted) = aes_encrypt(&encrypt_key, &arp_msg) else { + error!("failed to encrypt arp request"); + return Ok(()); + }; + // println!("arp_msg: {:?}", arp_msg); + let data = SdlData { + network_id: eee.network_id.load(Ordering::Relaxed), + src_mac: Vec::from(src_mac), + dst_mac: Vec::from([0xff; 6]), + is_p2p: true, + ttl: SDLAN_DEFAULT_TTL as u32, + data: encrypted, + }; + let data = + encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); + debug!("sending arp"); + // let data = marshal_message(&data); + send_packet_to_net(eee, BROADCAST_MAC, &data, arp_msg.len() as u64) + .await; + // edge.sock.send(data).await; + // println!("should send arp"); + return Ok(()); + } + + // prepend the ether header + let mut etherheader = Ethernet2Header::default(); + etherheader.destination = mac; + etherheader.ether_type = etherparse::EtherType::IPV4; + etherheader.source = src_mac; + let mut packet = Vec::with_capacity(14 + data.len() + 4); + packet.extend_from_slice(ðerheader.to_bytes()[..]); + packet.extend_from_slice(&data); + let crc = CRC_HASH.checksum(&packet); + packet.extend_from_slice(&crc.to_be_bytes()); + + let pkt_size = packet.len(); + // println!("sending data with mac"); + + let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { + error!("failed to encrypt packet request"); + return Ok(()); + }; + let data = SdlData { + is_p2p: true, + network_id: eee.network_id.load(Ordering::Relaxed), + ttl: SDLAN_DEFAULT_TTL as u32, + src_mac: Vec::from(src_mac), + dst_mac: Vec::from(mac), + data: Vec::from(encrypted), + }; + let msg = + encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); + let size = msg.len(); + send_packet_to_net(eee, mac, &msg, pkt_size as u64).await; + // let dstip = u32::from_be_bytes(ipv4hdr.0.destination); + println!( + "{:?} => {:?}, size={}", + ipv4hdr.0.source, ipv4hdr.0.destination, size + ); + } + _ => {} + } + } + Err(e) => { + error!("failed to parse ip packet: {}", e.to_string()); + } + } + Ok(()) + } } pub fn get_install_channel() -> String { diff --git a/src/network/tuntap.rs b/src/network/tuntap.rs index 07e97ae..cada2f0 100644 --- a/src/network/tuntap.rs +++ b/src/network/tuntap.rs @@ -1,3 +1,4 @@ pub trait TunTapPacketHandler { - async fn handle_packet(&self, data: &[u8], key: &[u8]) -> std::io::Result<()>; + async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()>; + async fn handle_packet_from_device(&self, data: &[u8], key: &[u8]) -> std::io::Result<()>; } diff --git a/src/pb/message.rs b/src/pb/message.rs index 66f6a05..c4ec1f0 100644 --- a/src/pb/message.rs +++ b/src/pb/message.rs @@ -57,13 +57,11 @@ pub struct SdlRegisterSuperAck { pub dev_addr: ::core::option::Option, #[prost(bytes = "vec", tag = "2")] pub aes_key: ::prost::alloc::vec::Vec, - #[prost(map = "uint32, bytes", tag = "3")] - pub known_macs: ::std::collections::HashMap>, - #[prost(uint32, tag = "4")] + #[prost(uint32, tag = "3")] pub upgrade_type: u32, - #[prost(string, optional, tag = "5")] + #[prost(string, optional, tag = "4")] pub upgrade_prompt: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "6")] + #[prost(string, optional, tag = "5")] pub upgrade_address: ::core::option::Option<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] @@ -92,22 +90,6 @@ pub struct SdlPeerInfo { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlKnownMacEvent { - #[prost(bytes = "vec", tag = "1")] - pub mac: ::prost::alloc::vec::Vec, - #[prost(uint32, tag = "2")] - pub ip: u32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SdlDropMacEvent { - #[prost(bytes = "vec", tag = "1")] - pub mac: ::prost::alloc::vec::Vec, - #[prost(uint32, tag = "2")] - pub ip: u32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] pub struct SdlNatChangedEvent { #[prost(bytes = "vec", tag = "1")] pub mac: ::prost::alloc::vec::Vec, @@ -139,8 +121,6 @@ pub struct SdlChangeNetworkCommand { pub dev_addr: ::core::option::Option, #[prost(bytes = "vec", tag = "2")] pub aes_key: ::prost::alloc::vec::Vec, - #[prost(map = "uint32, bytes", tag = "3")] - pub known_macs: ::std::collections::HashMap>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)]