diff --git a/common/src/args_parse.rs b/common/src/args_parse.rs index 81af384..7763af9 100644 --- a/common/src/args_parse.rs +++ b/common/src/args_parse.rs @@ -1,6 +1,6 @@ use std::net::Ipv4Addr; -pub fn ips_parse(ips: &Vec,in_ip:bool) -> Result, String> { +pub fn ips_parse(ips: &Vec) -> Result, String> { let mut in_ips_c = vec![]; for x in ips { let mut split = x.split(","); @@ -12,10 +12,7 @@ pub fn ips_parse(ips: &Vec,in_ip:bool) -> Result() { ip @@ -38,16 +35,45 @@ pub fn ips_parse(ips: &Vec,in_ip:bool) -> Result() { - let mut mask = 0 as u32; - for i in 0..m { - mask = mask | (1 << (31 - i)); - } - mask - } else { - return Err("not netmask".to_string()); - }; + let mask = to_ip(mask)?; in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip)); } Ok(in_ips_c) +} + +pub fn out_ips_parse(ips: &Vec) -> Result, String> { + let mut in_ips_c = vec![]; + for x in ips { + let mut split = x.split("/"); + let dest = if let Some(dest) = split.next() { + dest + } else { + return Err("no ipv4/mask".to_string()); + }; + let mask = if let Some(mask) = split.next() { + mask + } else { + return Err("no netmask".to_string()); + }; + let dest = if let Ok(dest) = dest.parse::() { + dest + } else { + return Err("not ipv4".to_string()); + }; + let mask = to_ip(mask)?; + in_ips_c.push((u32::from_be_bytes(dest.octets()), mask)); + } + Ok(in_ips_c) +} + +pub fn to_ip(mask: &str) -> Result { + if let Ok(m) = mask.parse::() { + let mut mask = 0 as u32; + for i in 0..m { + mask = mask | (1 << (31 - i)); + } + Ok(mask) + } else { + Err("not netmask".to_string()) + } } \ No newline at end of file diff --git a/vnt-cli/src/main.rs b/vnt-cli/src/main.rs index d4c09d9..959db1e 100644 --- a/vnt-cli/src/main.rs +++ b/vnt-cli/src/main.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use console::style; use getopts::Options; use tokio::io::{AsyncBufReadExt, BufReader}; -use common::args_parse::ips_parse; +use common::args_parse::{ips_parse, out_ips_parse}; use vnt::core::{Config, VntUtil}; use vnt::handle::registration_handler::ReqEnum; @@ -33,16 +33,16 @@ async fn main0() { let mut opts = Options::new(); opts.optopt("k", "", &format!("{}", green("必选,使用相同的token,就能组建一个局域网络".to_string())), ""); opts.optopt("n", "", "给设备一个名字,默认使用系统版本", ""); - opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配ip", ""); + opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip", ""); opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入"); opts.optopt("s", "", "注册和中继服务器地址", ""); opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", ""); opts.optflag("a", "", "使用tap模式,默认使用tun模式"); opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3 \n表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3", ""); - opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24,192.168.0.10 \n表示允许目标为192.168.0.0/24的数据从网卡192.168.0.10转发出去,不指定出口地址则使用默认网卡", ""); + opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24 \n表示允许目标为192.168.0.0/24的数据转发出去", ""); opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", ""); opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); - opts.optopt("u", "", "虚拟网卡mtu值", ""); + opts.optopt("u", "", "自定义mtu(默认为1430)", ""); opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低"); opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", ""); opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); @@ -139,22 +139,24 @@ async fn main0() { .collect::>(); let in_ip = matches.opt_strs("i"); - let in_ip = match ips_parse(&in_ip, true) { + let in_ip = match ips_parse(&in_ip) { Ok(in_ip) => { in_ip } Err(e) => { print_usage(&program, opts); println!(); println!("-i {}", e); + println!("example: -i 192.168.0.0/24,10.26.0.3"); return; } }; let out_ip = matches.opt_strs("o"); - let out_ip = match ips_parse(&out_ip, false) { + let out_ip = match out_ips_parse(&out_ip) { Ok(out_ip) => { out_ip } Err(e) => { print_usage(&program, opts); println!(); println!("-o {}", e); + println!("example: -o 0.0.0.0/0"); return; } }; diff --git a/vnt/src/core/mod.rs b/vnt/src/core/mod.rs index 1ead5c8..1afa69d 100644 --- a/vnt/src/core/mod.rs +++ b/vnt/src/core/mod.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::io; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; @@ -18,7 +17,7 @@ use crate::channel::sender::ChannelSender; use crate::cipher::Cipher; use crate::core::status::VntStatusManger; use crate::error::Error; -use crate::external_route::ExternalRoute; +use crate::external_route::{AllowExternalRoute, ExternalRoute}; use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler}; use crate::handle::recv_handler::ChannelDataHandler; use crate::handle::registration_handler::{RegResponse, ReqEnum}; @@ -183,25 +182,18 @@ impl VntUtil { let local_port = context.main_local_port()?; // NAT检测 let nat_test = NatTest::new(config.nat_test_server.clone(), response.public_ip, response.public_port, local_ip, local_port); - let mut out_ip_list = config.out_ips; - for (_, _, ip) in out_ip_list.iter_mut() { - if ip == &Ipv4Addr::UNSPECIFIED { - *ip = local_ip; - } - } - let out_ips = out_ip_list.iter().map(|(_, _, ip)| *ip).collect::>(); - let out_external_route = ExternalRoute::new(out_ip_list); let in_external_route = if config.in_ips.is_empty() { None } else { Some(ExternalRoute::new(config.in_ips)) }; - let (tcp_proxy, udp_proxy, ip_proxy_map) = if out_ips.is_empty() { + let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() { (None, None, None) } else { - let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), out_ips, current_device.clone()).await?; + let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), current_device.clone()).await?; (Some(tcp_proxy), Some(udp_proxy), Some(ip_proxy_map)) }; + let out_external_route = AllowExternalRoute::new(config.out_ips); let igmp_server = if config.simulate_multicast { Some(IgmpServer::new(device_writer.clone())) @@ -345,7 +337,7 @@ pub struct Config { pub server_address_str: String, pub nat_test_server: Vec, pub in_ips: Vec<(u32, u32, Ipv4Addr)>, - pub out_ips: Vec<(u32, u32, Ipv4Addr)>, + pub out_ips: Vec<(u32, u32)>, pub password: Option, pub simulate_multicast: bool, pub mtu: Option, @@ -362,7 +354,7 @@ impl Config { server_address: SocketAddr, server_address_str: String, nat_test_server: Vec, - in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, + in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>, password: Option, simulate_multicast: bool, mtu: Option, tcp: bool, ip: Option, relay: bool, ) -> Self { diff --git a/vnt/src/external_route/mod.rs b/vnt/src/external_route/mod.rs index 080d9e5..f427ac4 100644 --- a/vnt/src/external_route/mod.rs +++ b/vnt/src/external_route/mod.rs @@ -11,7 +11,7 @@ pub struct ExternalRoute { impl ExternalRoute { pub fn new(route_table: Vec<(u32, u32, Ipv4Addr)>) -> Self { Self { - route_table:Arc::new(route_table) + route_table: Arc::new(route_table) } } pub fn route(&self, ip: &Ipv4Addr) -> Option { @@ -23,4 +23,26 @@ impl ExternalRoute { } None } +} + +#[derive(Clone)] +pub struct AllowExternalRoute { + route_table: Arc>, +} + +impl AllowExternalRoute { + pub fn new(route_table: Vec<(u32, u32)>) -> Self { + Self { + route_table: Arc::new(route_table) + } + } + pub fn allow(&self, ip: &Ipv4Addr) -> bool { + let ip = u32::from_be_bytes(ip.octets()); + for (dest, mask) in self.route_table.iter() { + if *mask & ip == *mask & *dest { + return true; + } + } + false + } } \ No newline at end of file diff --git a/vnt/src/handle/recv_handler.rs b/vnt/src/handle/recv_handler.rs index 08deb01..c26f0ad 100644 --- a/vnt/src/handle/recv_handler.rs +++ b/vnt/src/handle/recv_handler.rs @@ -17,7 +17,7 @@ use crate::channel::{Route, RouteKey}; use crate::cipher::Cipher; use crate::error::Error; -use crate::external_route::ExternalRoute; +use crate::external_route::AllowExternalRoute; use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, PeerDeviceStatus}; use crate::handle::registration_handler::Register; use crate::igmp_server::IgmpServer; @@ -41,7 +41,7 @@ pub struct ChannelDataHandler { connect_status: Arc>, peer_nat_info_map: Arc>, ip_proxy_map: Option, - out_external_route: ExternalRoute, + out_external_route: AllowExternalRoute, cone_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, cipher: Cipher, @@ -58,7 +58,7 @@ impl ChannelDataHandler { connect_status: Arc>, peer_nat_info_map: Arc>, ip_proxy_map: Option, - out_external_route: ExternalRoute, + out_external_route: AllowExternalRoute, cone_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, cipher: Cipher, @@ -185,7 +185,7 @@ impl ChannelDataHandler { } if not_broadcast && ipv4.destination_ip() != destination { if let Some(ip_proxy_map) = &self.ip_proxy_map { - if let Some(gate_way) = self.out_external_route.route(&ipv4.destination_ip()) { + if self.out_external_route.allow(&ipv4.destination_ip()) { match ipv4.protocol() { ipv4::protocol::Protocol::Tcp => { let dest_ip = ipv4.destination_ip(); @@ -197,8 +197,7 @@ impl ChannelDataHandler { tcp_packet.update_checksum(); ipv4.set_destination_ip(destination); ipv4.update_checksum(); - ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port), - (SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port))); + ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port), SocketAddrV4::new(dest_ip, dest_port)); } ipv4::protocol::Protocol::Udp => { let dest_ip = ipv4.destination_ip(); @@ -210,8 +209,7 @@ impl ChannelDataHandler { udp_packet.update_checksum(); ipv4.set_destination_ip(destination); ipv4.update_checksum(); - ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port), - (SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port))); + ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port), SocketAddrV4::new(dest_ip, dest_port)); } ipv4::protocol::Protocol::Icmp => { let dest_ip = ipv4.destination_ip(); @@ -220,7 +218,7 @@ impl ChannelDataHandler { match icmp_packet.header_other() { HeaderOther::Identifier(id, seq) => { ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source); - ip_proxy_map.send_icmp(ipv4.payload(), &gate_way, &dest_ip)?; + ip_proxy_map.send_icmp(ipv4.payload(), &dest_ip)?; } _ => { return Ok(()); @@ -419,7 +417,7 @@ impl ChannelDataHandler { ControlPacket::AddrRequest => { match route_key.addr.ip() { std::net::IpAddr::V4(ipv4) => { - let mut packet = NetPacket::new([0;12+6])?; + let mut packet = NetPacket::new([0; 12 + 6])?; packet.set_version(Version::V1); packet.set_protocol(Protocol::Control); packet.set_transport_protocol( diff --git a/vnt/src/handle/tun_tap/mod.rs b/vnt/src/handle/tun_tap/mod.rs index b391197..aa59b65 100644 --- a/vnt/src/handle/tun_tap/mod.rs +++ b/vnt/src/handle/tun_tap/mod.rs @@ -190,7 +190,7 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], SocketAddrV4::new(dest_ip, tcp_packet.destination_port()) }; if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) { - let source_addr = entry.value().1; + let source_addr = entry.value(); let source_ip = *source_addr.ip(); let mut tcp_packet = TcpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; tcp_packet.set_source_port(source_addr.port()); @@ -206,7 +206,7 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], SocketAddrV4::new(dest_ip, udp_packet.destination_port()) }; if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) { - let source_addr = entry.value().1; + let source_addr = entry.value(); let source_ip = *source_addr.ip(); let mut udp_packet = UdpPacket::new(source_ip, dest_ip, &mut net_packet.buffer_mut()[12 + ip_head_len..data_len])?; udp_packet.set_source_port(source_addr.port()); diff --git a/vnt/src/ip_proxy/mod.rs b/vnt/src/ip_proxy/mod.rs index 4f25dc2..3a4b6b1 100644 --- a/vnt/src/ip_proxy/mod.rs +++ b/vnt/src/ip_proxy/mod.rs @@ -1,5 +1,4 @@ use std::{io, thread}; -use std::collections::{HashMap, HashSet}; use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use crossbeam_utils::atomic::AtomicCell; @@ -27,28 +26,23 @@ pub enum Protocol { pub struct IpProxyMap { pub(crate) tcp_proxy_port: u16, pub(crate) udp_proxy_port: u16, - //真实源地址 -> (绑定地址,目的地址) - pub(crate) tcp_proxy_map: Arc>, - pub(crate) udp_proxy_map: Arc>, + //真实源地址 -> 目的地址 + pub(crate) tcp_proxy_map: Arc>, + pub(crate) udp_proxy_map: Arc>, // icmp用Identifier来区分,没有Identifier的一律不转发 pub(crate) icmp_proxy_map: Arc>, - icmp_sockets: HashMap>, + icmp_socket: Arc, } impl IpProxyMap { - pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result { - if let Some(socket) = self.icmp_sockets.get(src) { - socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0))) - } else { - Err(io::Error::new(io::ErrorKind::Other, format!("not found src:{},dest:{}", src, dest))) - } + pub fn send_icmp(&self, buf: &[u8], dest: &Ipv4Addr) -> io::Result { + self.icmp_socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0))) } } -pub async fn init_proxy(sender: ChannelSender, bind_ips: HashSet, current_device: Arc>) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> { - let mut icmp_sockets = HashMap::new(); - let tcp_proxy_map: Arc> = Arc::new(SkipMap::new()); - let udp_proxy_map: Arc> = Arc::new(SkipMap::new()); +pub async fn init_proxy(sender: ChannelSender, current_device: Arc>) -> io::Result<(TcpProxy, UdpProxy, IpProxyMap)> { + let tcp_proxy_map: Arc> = Arc::new(SkipMap::new()); + let udp_proxy_map: Arc> = Arc::new(SkipMap::new()); let icmp_proxy_map: Arc> = Arc::new(SkipMap::new()); let tcp_listener = TcpListener::bind("0.0.0.0:0").await?; let udp_socket = UdpSocket::bind("0.0.0.0:0").await?; @@ -56,15 +50,12 @@ pub async fn init_proxy(sender: ChannelSender, bind_ips: HashSet, curr let udp_proxy_port = udp_socket.local_addr()?.port(); let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map.clone()); let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map.clone()); - for ip in bind_ips { - let addr = SocketAddrV4::new(ip, 0); - let icmp_proxy_map = icmp_proxy_map.clone(); - let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.clone(), current_device.clone())?; - icmp_sockets.insert(ip, icmp_proxy.icmp_socket()); - thread::spawn(move || { - icmp_proxy.start(); - }); - } + let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0); + let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map.clone(), sender.clone(), current_device.clone())?; + let icmp_socket = icmp_proxy.icmp_socket(); + thread::spawn(move || { + icmp_proxy.start(); + }); Ok((tcp_proxy, udp_proxy, IpProxyMap { tcp_proxy_port, @@ -72,6 +63,6 @@ pub async fn init_proxy(sender: ChannelSender, bind_ips: HashSet, curr tcp_proxy_map, udp_proxy_map, icmp_proxy_map, - icmp_sockets, + icmp_socket, })) } \ No newline at end of file diff --git a/vnt/src/ip_proxy/tcp_proxy.rs b/vnt/src/ip_proxy/tcp_proxy.rs index 5e2f3c2..4b7293a 100644 --- a/vnt/src/ip_proxy/tcp_proxy.rs +++ b/vnt/src/ip_proxy/tcp_proxy.rs @@ -6,11 +6,11 @@ use tokio::net::{TcpListener, TcpStream}; pub struct TcpProxy { tcp_listener: TcpListener, - map: Arc>, + map: Arc>, } impl TcpProxy { - pub fn new(tcp_listener: TcpListener, map: Arc>) -> Self { + pub fn new(tcp_listener: TcpListener, map: Arc>) -> Self { Self { tcp_listener, map, @@ -25,11 +25,11 @@ impl TcpProxy { match sender_addr { SocketAddr::V4(sender_addr) => { if let Some(entry) = map.get(&sender_addr) { - let (src_addr, dest_addr) = *entry.value(); + let dest_addr = *entry.value(); let peer_tcp_stream = match TcpStream::connect(dest_addr).await { Ok(peer_tcp_stream) => {peer_tcp_stream} Err(e) => { - log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr); continue; } }; @@ -38,7 +38,7 @@ impl TcpProxy { match proxy(tcp_stream, peer_tcp_stream).await { Ok(_) => {} Err(e) => { - log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr); } } map.remove(&sender_addr); diff --git a/vnt/src/ip_proxy/udp_proxy.rs b/vnt/src/ip_proxy/udp_proxy.rs index 4376562..7cb7d01 100644 --- a/vnt/src/ip_proxy/udp_proxy.rs +++ b/vnt/src/ip_proxy/udp_proxy.rs @@ -8,11 +8,11 @@ use tokio::net::UdpSocket; /// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址 pub struct UdpProxy { udp_socket: Arc, - map: Arc>, + map: Arc>, } impl UdpProxy { - pub fn new(udp_socket: UdpSocket, map: Arc>) -> Self { + pub fn new(udp_socket: UdpSocket, map: Arc>) -> Self { let udp_socket = Arc::new(udp_socket); Self { udp_socket, @@ -48,11 +48,11 @@ impl UdpProxy { } } -async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc>>, map: &Arc>, udp_socket: &Arc) -> io::Result<()> { +async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc>>, map: &Arc>, udp_socket: &Arc) -> io::Result<()> { if let Some(entry) = inner_map.get(&sender_addr) { entry.value().send(buf).await?; } else if let Some(entry) = map.get(&sender_addr) { - let (src_addr, dest_addr) = *entry.value(); + let dest_addr = *entry.value(); let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?; peer_udp_socket.connect(dest_addr).await?; peer_udp_socket.send(buf).await?; @@ -71,20 +71,20 @@ async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc {} Err(e) => { - log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr); break; } } } Err(e) => { - log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr); + log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,sender_addr,dest_addr); break; } } } Err(_) => { //超时关闭 - log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr); + log::warn!("udp代理超时关闭,来源:{},目标:{}",sender_addr,dest_addr); break; } }