229 lines
7.2 KiB
Rust
Executable File
229 lines
7.2 KiB
Rust
Executable File
use std::sync::atomic::Ordering;
|
|
|
|
use bytes::{Bytes, BytesMut};
|
|
use dashmap::DashMap;
|
|
use once_cell::sync::OnceCell;
|
|
use sdlan_sn_rs::{
|
|
config::SDLAN_DEFAULT_TTL,
|
|
utils::{get_current_timestamp, ip_to_string, Mac, Result},
|
|
};
|
|
|
|
use tracing::{debug, warn};
|
|
|
|
use tracing::error;
|
|
|
|
use crate::{
|
|
network::{form_ethernet_packet, send_packet_to_net, Node, RouteInfo},
|
|
pb::{encode_to_udp_message, SdlData},
|
|
tcp::PacketType,
|
|
utils::mac_to_string,
|
|
};
|
|
|
|
use super::get_edge;
|
|
|
|
pub const MAX_WAIT_PACKETS: usize = 100;
|
|
|
|
const DEFAULT_DNS_SERVER: u32 = (223 << 24) + (5 << 16) + (5 << 8) + 5; // ali dns
|
|
|
|
pub trait TunTapPacketHandler {
|
|
async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()>;
|
|
async fn handle_packet_from_device(&self, data: BytesMut) -> std::io::Result<()>;
|
|
}
|
|
|
|
pub fn set_route_from_net(routes: Vec<RouteInfo>) -> Result<()> {
|
|
let eee = get_edge();
|
|
eee.route_table.clear_and_add_routes(routes)?;
|
|
eee.route_table.apply_system(eee.device.get_if_idx());
|
|
Ok(())
|
|
}
|
|
|
|
/*
|
|
static ARP_WAIT_LIST: OnceCell<ArpWaitList> = OnceCell::new();
|
|
|
|
pub fn init_arp_wait_list() {
|
|
let waitlist = ArpWaitList {
|
|
content: DashMap::new(),
|
|
};
|
|
ARP_WAIT_LIST.set(waitlist).unwrap();
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ArpWaitInfo {
|
|
timestamp: u64,
|
|
// origin data is from the tun or tap device
|
|
origin_data: BytesMut,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ArpWaitList {
|
|
content: DashMap<u32, Vec<ArpWaitInfo>>,
|
|
}
|
|
|
|
impl ArpWaitList {
|
|
fn add_to_wait_list(&self, ip: u32, origin_data_with_zeroed_layer2: BytesMut) {
|
|
let mut entry = self.content.entry(ip).or_insert(vec![]);
|
|
if entry.len() < MAX_WAIT_PACKETS {
|
|
entry.push(ArpWaitInfo {
|
|
timestamp: get_current_timestamp(),
|
|
origin_data: origin_data_with_zeroed_layer2,
|
|
})
|
|
}
|
|
}
|
|
|
|
async fn arp_arrived(&self, ip: u32, mac: Mac) {
|
|
debug!(
|
|
"arp for {} arrived: {}",
|
|
ip_to_string(&ip),
|
|
mac_to_string(&mac)
|
|
);
|
|
let Some(items) = self.content.remove(&ip) else {
|
|
return;
|
|
};
|
|
let edge = get_edge();
|
|
// just remove the items
|
|
if !edge.is_authorized() {
|
|
return;
|
|
}
|
|
|
|
// let encrypt_key = edge.get_encrypt_key();
|
|
let network_id = edge.network_id.load(Ordering::Relaxed);
|
|
|
|
let src_mac = edge.device_config.get_mac();
|
|
let now = get_current_timestamp();
|
|
for item in items.1 {
|
|
if (now - item.timestamp) > 5 {
|
|
continue;
|
|
}
|
|
let packet = form_ethernet_packet(src_mac, mac, item.origin_data);
|
|
|
|
let pkt_size = packet.len();
|
|
|
|
let Ok(encrypted) = edge.encryptor.load().encrypt(&packet) else {
|
|
// let Ok(encrypted) = edge.encryptor.read().unwrap().encrypt(&packet) else {
|
|
// let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else {
|
|
error!("failed to encrypt packet request");
|
|
return;
|
|
};
|
|
let data_bytes = Bytes::from(encrypted);
|
|
let data = SdlData {
|
|
is_p2p: true,
|
|
network_id,
|
|
ttl: SDLAN_DEFAULT_TTL as u32,
|
|
src_mac: Vec::from(src_mac),
|
|
dst_mac: Vec::from(mac),
|
|
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, mac, &msg, pkt_size as u64).await;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn add_to_arp_wait_list(ip: u32, origin_data_with_zeroed_layer2: BytesMut) {
|
|
let waitlist = ARP_WAIT_LIST
|
|
.get()
|
|
.expect("ARP_WAIT_LIST has not been inited");
|
|
|
|
waitlist.add_to_wait_list(ip, origin_data_with_zeroed_layer2);
|
|
}
|
|
|
|
pub async fn arp_arrived(ip: u32, mac: Mac) {
|
|
let waitlist = ARP_WAIT_LIST
|
|
.get()
|
|
.expect("ARP_WAIT_LIST has not been inited");
|
|
|
|
waitlist.arp_arrived(ip, mac).await;
|
|
}
|
|
*/
|
|
|
|
pub fn get_dns_gateway(edge: &Node, payload: &[u8]) -> Option<String> {
|
|
let dns_packet = match simple_dns::Packet::parse(payload) {
|
|
Err(e) => {
|
|
error!("failed to parse dns packet: {}", e);
|
|
return None;
|
|
}
|
|
Ok(p) => p,
|
|
};
|
|
|
|
let mut target_dns: &str = "";
|
|
if !dns_packet.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns_packet.questions.is_empty() {
|
|
let question = &dns_packet.questions[0];
|
|
let domain = question.qname.to_string();
|
|
|
|
let self_domain = &edge.network_domain.load();
|
|
if self_domain.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
if domain.ends_with(self_domain.as_str()) {
|
|
debug!("got dns request for domain {}, which ends with our network domain {}, should send to dns server", domain, self_domain);
|
|
return Some(domain);
|
|
}
|
|
}
|
|
return None;
|
|
}
|
|
|
|
pub async fn parse_dns_payload(
|
|
edge: &Node,
|
|
layer7: &[u8],
|
|
layer3: &[u8],
|
|
source_ip: u32,
|
|
source_port: u16,
|
|
) {
|
|
match simple_dns::Packet::parse(layer7) {
|
|
Ok(mut dns) => {
|
|
if !dns.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns.questions.is_empty() {
|
|
let question = &dns.questions[0];
|
|
let qname = question.qname.to_string();
|
|
if qname.ends_with(edge.network_domain.load().as_str()) {
|
|
warn!(
|
|
"question 15353 for {} from {}:{} with transaction_id = {}",
|
|
qname,
|
|
ip_to_string(&source_ip),
|
|
source_port,
|
|
dns.id()
|
|
);
|
|
// should send to our socket
|
|
if let Err(e) = edge
|
|
.udp_sock_for_dns
|
|
.send_to(layer3, format!("{}:15353", edge.server_ip))
|
|
.await
|
|
{
|
|
error!("failed to send request to 15353: {}", e);
|
|
}
|
|
} else {
|
|
let origin_transaction_id = dns.id();
|
|
let transaction_id = edge.dns_matcher.generate_transaction_id(
|
|
source_ip,
|
|
source_port,
|
|
origin_transaction_id,
|
|
);
|
|
dns.set_id(transaction_id);
|
|
warn!(
|
|
"question 223.5.5.5 for {} from {}:{} with transaction_id = {}",
|
|
qname,
|
|
ip_to_string(&source_ip),
|
|
source_port,
|
|
dns.id()
|
|
);
|
|
if let Ok(res) = dns.build_bytes_vec() {
|
|
if let Err(e) = edge
|
|
.udp_sock_for_global_dns
|
|
.send_to(&res, "223.5.5.5:53")
|
|
.await
|
|
{
|
|
error!("failed to query for global dns: {}", e);
|
|
}
|
|
}
|
|
// edge.udp_sock_for_global_dns.send_to()
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
error!("failed to parse dns packet");
|
|
}
|
|
}
|
|
}
|