diff --git a/.vscode/settings.json b/.vscode/settings.json index 80d7c65..8fd1994 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { - "rust-analyzer.cargo.target": null, - "rust-analyzer.cargo.features": ["tun"] + "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu" + // "rust-analyzer.cargo.features": ["tun"] } \ No newline at end of file diff --git a/src/network/arp.rs b/src/network/arp.rs index 84b1429..906e348 100755 --- a/src/network/arp.rs +++ b/src/network/arp.rs @@ -15,8 +15,6 @@ use tokio::sync::{ oneshot, }; -use crate::network::tun::DNS_IP; - use super::{get_edge, get_route_table, init_arp_wait_list, init_route}; static GLOBAL_ARP: OnceCell = OnceCell::new(); diff --git a/src/network/mod.rs b/src/network/mod.rs index 5cd3e33..65c38c6 100755 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -18,6 +18,8 @@ pub use route::*; mod tuntap; pub use tuntap::*; +pub const DNS_IP: u32 = (100<<24) + (100<<16) + (100<<8) + 100; + #[cfg_attr(target_os = "linux", path = "tun_linux.rs")] #[cfg_attr(target_os = "windows", path = "tun_win.rs")] mod tun; diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index d8737a2..425d467 100755 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -27,8 +27,6 @@ use crate::tcp::PacketType; use super::device::{DeviceConfig, Mode}; use super::TunTapPacketHandler; -pub const DNS_IP: u32 = (100<<24) + (100<<16) + (100<<8) + 100; - const RESOLV_FILE: &'static str = "/etc/resolv.conf"; const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak"; @@ -120,7 +118,10 @@ impl Iface { return; } let mask = net_bit_len_to_mask(netbit); - let default_gw = (ip & mask) + 1; + let mut default_gw = (ip & mask) + 1; + if default_gw == ip { + default_gw += 1; + } let ip = ip_to_string(&ip); let netbit = ip_to_string(&net_bit_len_to_mask(netbit)); @@ -275,9 +276,6 @@ impl TunTapPacketHandler for Iface { async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> { debug!("in tun mode"); - if key.len() == 0 { - // got layer2 packet, just write to interface; - } // got layer 2 frame match Ethernet2Header::from_slice(&data) { Ok((hdr, rest)) => { diff --git a/src/network/tun_win.rs b/src/network/tun_win.rs index f584f81..d5979c2 100755 --- a/src/network/tun_win.rs +++ b/src/network/tun_win.rs @@ -14,9 +14,7 @@ use wintun; use crate::get_edge; use crate::network::{ - add_to_arp_wait_list, arp_arrived, form_ethernet_packet, generate_arp_request, - send_arp_request, send_packet_to_net, ArpHdr, ArpRequestInfo, ArpResponse, ARP_REPLY, - ARP_REQUEST, + ARP_REPLY, ARP_REQUEST, ArpHdr, ArpRequestInfo, ArpResponse, DNS_IP, add_to_arp_wait_list, arp_arrived, form_ethernet_packet, generate_arp_request, send_arp_request, send_packet_to_net }; use crate::pb::{encode_to_udp_message, SdlData}; use crate::tcp::PacketType; @@ -26,6 +24,7 @@ use super::device::{DeviceConfig, Mode}; use super::TunTapPacketHandler; pub struct Iface { + if_idx: u32, name: String, _adapter: Arc, session: Arc, @@ -65,7 +64,14 @@ impl Iface { error!("reload config's ip is 0"); return; } + + let mask = net_bit_len_to_mask(netbit); + let mut default_gw = (ip & mask) + 1; + if default_gw == ip { + default_gw += 1; + } let ip = ip_to_string(&ip); + let netbit = ip_to_string(&net_bit_len_to_mask(netbit)); let mut cmd = Command::new("netsh"); @@ -114,11 +120,13 @@ impl Iface { } } - /* - if let Err(e) = set_dns(&self.name, network_domain) { + let gw = ip_to_string(&default_gw); + println!("gw = {}", gw); + if let Err(e) = set_dns(&self.name, network_domain, &gw, self.if_idx) { println!("failed to set dns: {:?}", e); + } else { + println!("set dns ok"); } - */ } } @@ -145,15 +153,13 @@ impl TunTapPacketHandler for Iface { let edge = get_edge(); let self_mac = edge.device_config.get_mac(); - /* if hdr.destination != self_mac && hdr.destination != BROADCAST_MAC { error!( "packet to [{:?}] not direct to us", mac_to_string(&hdr.destination) ); - return; + return Ok(()); } - */ if hdr.ether_type == ARP { let mut arp = ArpHdr::from_slice(&data); @@ -302,6 +308,15 @@ impl TunTapPacketHandler for Iface { debug!("drop tun packet due to not authed"); return Ok(()); } + if dstip == DNS_IP { + println!("request for dns"); + let addr = format!("{}:15353", eee.server_ip); + println!("send dns to {}", addr); + if let Err(e) = eee.udp_sock_for_dns.send_to(&data, &addr).await { + error!("failed to send request to 15353: {}", e); + } + return Ok(()); + } match send_arp_request(ArpRequestInfo::Lookup { ip: dstip }).await { ArpResponse::LookupResp { mac, @@ -394,10 +409,13 @@ fn create_wintun(path: &str, name: &str) -> Iface { let adapter = match wintun::Adapter::open(&wt, name) { Ok(a) => a, Err(_e) => wintun::Adapter::create(&wt, name, "Example", None) - .expect("failed to create wintun adapter"), + .expect("failed to create tun adapter"), }; + let idx = adapter.get_adapter_index().expect("failed to get adapter index"); + println!("idx = {}", idx); let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap()); Iface { + if_idx: idx, _adapter: adapter, session, name: name.to_owned(), @@ -413,25 +431,35 @@ pub fn get_install_channel() -> String { "windows".to_owned() } -pub fn set_dns(name: &str, network_domain: &str) -> std::io::Result<()>{ - Command::new("netsh") +pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> std::io::Result<()>{ + let res = Command::new("ROUTE") + .arg("ADD") + .arg("100.100.100.100") + .arg("MASK") + .arg("255.255.255.255") + .arg(gw) + .arg("IF") + .arg(ifidx.to_string()) + .creation_flags(0x08000000) + .output()?; + + println!("res1: {}", res.status.success()); + + println!("route set ok"); + let res = Command::new("netsh") .arg("dnsclient") .arg("set") .arg("dnsserver") - .arg(&format!("name=\"{}\"", name)) + .arg(&format!("name={}", name)) .arg("source=static") .arg("address=100.100.100.100") - .arg("validate=yes").output()?; - - Command::new("netsh") - .arg("interface") - .arg("ipv4") - .arg("set") - .arg("dns") - .arg("suffix") - .arg(&format!("name=\"{}\"", name)) - .arg(&format!("suffix=\"{}\"", network_domain)) + .arg("validate=no") + .creation_flags(0x08000000) .output()?; + println!("res2: {}", res.status.success()); + + println!("netsh set ok"); + Ok(()) }