This commit is contained in:
asxalex 2024-10-23 20:36:51 +08:00
parent 7c4bb64bd4
commit 9b1710e590
9 changed files with 240 additions and 160 deletions

View File

@ -25,3 +25,6 @@ tracing = "0.1.40"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
wintun = "0.4.0" wintun = "0.4.0"
[features]
tap = []

View File

@ -1,5 +1,8 @@
linux: linux:
RUSTFLAGS="-L ." cargo build --release RUSTFLAGS="-L ." cargo build --features "tap" --release
linux-tun:
RUSTFLAGS="-L ." cargo build --features "tap" --release
pb: pb:
cargo run --bin build_pb cargo run --bin build_pb

View File

@ -38,10 +38,9 @@ message SDLRegisterSuper {
message SDLRegisterSuperAck { message SDLRegisterSuperAck {
SDLDevAddr dev_addr = 1; SDLDevAddr dev_addr = 1;
bytes aes_key = 2; bytes aes_key = 2;
map<uint32, bytes> known_macs = 3; uint32 upgrade_type = 3;
uint32 upgrade_type = 4; optional string upgrade_prompt = 4;
optional string upgrade_prompt = 5; optional string upgrade_address = 5;
optional string upgrade_address = 6;
} }
message SDLRegisterSuperNak { 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 { message SDLNatChangedEvent {
bytes mac = 1; bytes mac = 1;
uint32 ip = 2; uint32 ip = 2;
@ -94,7 +83,6 @@ message SDLNetworkShutdownEvent {
message SDLChangeNetworkCommand { message SDLChangeNetworkCommand {
SDLDevAddr dev_addr = 1; SDLDevAddr dev_addr = 1;
bytes aes_key = 2; bytes aes_key = 2;
map<uint32, bytes> known_macs = 3;
} }
message SDLCommandAck { message SDLCommandAck {

View File

@ -7,7 +7,8 @@ use crate::config::{NULL_MAC, TCP_PING_TIME};
use crate::network::ipv6::run_ipv6; use crate::network::ipv6::run_ipv6;
use crate::network::{ use crate::network::{
generate_arp_request, get_edge, ping_to_sn, read_and_parse_packet, send_arp_request, ArpHdr, 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::{ use crate::pb::{
encode_to_tcp_message, encode_to_udp_message, SdlData, SdlDevAddr, SdlRegisterSuper, 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"); error!("drop tun packet due to encrypt key len is 0");
return; return;
} }
let src_mac = eee.device_config.get_mac(); eee.device
.handle_packet_from_device(data, encrypt_key.as_slice())
match IpHeaders::from_slice(&data) { .await;
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(&etherheader.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());
}
}
} }
pub async fn send_packet_to_net(eee: &Node, dst_mac: Mac, pkt: &[u8], size: u64) { pub async fn send_packet_to_net(eee: &Node, dst_mac: Mac, pkt: &[u8], size: u64) {

View File

@ -242,6 +242,12 @@ impl Node {
tcp_pong: Arc<AtomicU64>, tcp_pong: Arc<AtomicU64>,
start_stop: Sender<StartStopInfo>, start_stop: Sender<StartStopInfo>,
) -> Self { ) -> Self {
let mode = if cfg!(feature = "tap") {
Mode::Tap
} else {
Mode::Tun
};
Self { Self {
packet_id: AtomicU32::new(1), packet_id: AtomicU32::new(1),
network_id: AtomicU32::new(0), network_id: AtomicU32::new(0),
@ -254,7 +260,7 @@ impl Node {
nat_type: Mutex::new(NatType::Blocked), nat_type: Mutex::new(NatType::Blocked),
device_config: DeviceConfig::new(), device_config: DeviceConfig::new(),
device: new_iface("dev", Mode::Tun), device: new_iface("dev", mode),
authorized: AtomicBool::new(false), authorized: AtomicBool::new(false),
encrypt_key: RwLock::new(Arc::new(Vec::new())), encrypt_key: RwLock::new(Arc::new(Vec::new())),

View File

@ -746,7 +746,9 @@ async fn handle_tun_packet(
} }
let data = origin.unwrap(); let data = origin.unwrap();
debug!("ether size is {}", data.len()); 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; let msg_size = data.len() as u64;

View File

@ -1,8 +1,10 @@
use etherparse::ether_type::ARP; use etherparse::ether_type::ARP;
use etherparse::{Ethernet2Header, IpHeaders}; use etherparse::{Ethernet2Header, IpHeaders};
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
use sdlan_sn_rs::utils::{ 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::CStr;
use std::ffi::{c_char, c_int}; use std::ffi::{c_char, c_int};
use std::fs::OpenOptions; use std::fs::OpenOptions;
@ -12,12 +14,15 @@ use std::sync::atomic::Ordering;
use sdlan_sn_rs::utils::Result; use sdlan_sn_rs::utils::Result;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::os::fd::AsRawFd; 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::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::pb::{encode_to_udp_message, SdlData};
use crate::tcp::PacketType; use crate::tcp::PacketType;
use crate::utils::{mac_to_string, CRC_HASH}; use crate::utils::{mac_to_string, CRC_HASH};
@ -111,6 +116,32 @@ impl Iface {
let ip = ip_to_string(&ip); let ip = ip_to_string(&ip);
let netbit = ip_to_string(&net_bit_len_to_mask(netbit)); let netbit = ip_to_string(&net_bit_len_to_mask(netbit));
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());
}
}
} else {
println!("set tun device");
let res = Command::new("ifconfig") let res = Command::new("ifconfig")
.arg(&self.name) .arg(&self.name)
.arg(ip) .arg(ip)
@ -127,6 +158,7 @@ impl Iface {
} }
} }
} }
}
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> { pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
(&self.fd).read(buf) (&self.fd).read(buf)
@ -137,8 +169,56 @@ impl Iface {
} }
} }
#[cfg(feature = "tap")]
impl TunTapPacketHandler for Iface { 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 // got layer 2 frame
match Ethernet2Header::from_slice(&data) { match Ethernet2Header::from_slice(&data) {
Ok((hdr, rest)) => { Ok((hdr, rest)) => {
@ -287,6 +367,119 @@ impl TunTapPacketHandler for Iface {
Ok(()) 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(&etherheader.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 { pub fn get_install_channel() -> String {

View File

@ -1,3 +1,4 @@
pub trait TunTapPacketHandler { 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<()>;
} }

View File

@ -57,13 +57,11 @@ pub struct SdlRegisterSuperAck {
pub dev_addr: ::core::option::Option<SdlDevAddr>, pub dev_addr: ::core::option::Option<SdlDevAddr>,
#[prost(bytes = "vec", tag = "2")] #[prost(bytes = "vec", tag = "2")]
pub aes_key: ::prost::alloc::vec::Vec<u8>, pub aes_key: ::prost::alloc::vec::Vec<u8>,
#[prost(map = "uint32, bytes", tag = "3")] #[prost(uint32, tag = "3")]
pub known_macs: ::std::collections::HashMap<u32, ::prost::alloc::vec::Vec<u8>>,
#[prost(uint32, tag = "4")]
pub upgrade_type: u32, pub upgrade_type: u32,
#[prost(string, optional, tag = "5")] #[prost(string, optional, tag = "4")]
pub upgrade_prompt: ::core::option::Option<::prost::alloc::string::String>, 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>, pub upgrade_address: ::core::option::Option<::prost::alloc::string::String>,
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
@ -92,22 +90,6 @@ pub struct SdlPeerInfo {
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct SdlKnownMacEvent {
#[prost(bytes = "vec", tag = "1")]
pub mac: ::prost::alloc::vec::Vec<u8>,
#[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<u8>,
#[prost(uint32, tag = "2")]
pub ip: u32,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SdlNatChangedEvent { pub struct SdlNatChangedEvent {
#[prost(bytes = "vec", tag = "1")] #[prost(bytes = "vec", tag = "1")]
pub mac: ::prost::alloc::vec::Vec<u8>, pub mac: ::prost::alloc::vec::Vec<u8>,
@ -139,8 +121,6 @@ pub struct SdlChangeNetworkCommand {
pub dev_addr: ::core::option::Option<SdlDevAddr>, pub dev_addr: ::core::option::Option<SdlDevAddr>,
#[prost(bytes = "vec", tag = "2")] #[prost(bytes = "vec", tag = "2")]
pub aes_key: ::prost::alloc::vec::Vec<u8>, pub aes_key: ::prost::alloc::vec::Vec<u8>,
#[prost(map = "uint32, bytes", tag = "3")]
pub known_macs: ::std::collections::HashMap<u32, ::prost::alloc::vec::Vec<u8>>,
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]