调整默认网卡的逻辑

This commit is contained in:
lbl8603
2024-08-08 20:38:58 +08:00
parent 7e0de2c4e6
commit e6cfdec9c6
10 changed files with 98 additions and 43 deletions
+9 -3
View File
@@ -58,10 +58,14 @@ pub fn create_tcp0(
)? )?
}; };
if v4 { if v4 {
socket.set_ip_unicast_if(default_interface)?; if let Err(e) = socket.set_ip_unicast_if(default_interface) {
log::warn!("set_ip_unicast_if {:?}", e)
}
} }
if bind_port != 0 { if bind_port != 0 {
socket.set_reuse_address(true)?; socket
.set_reuse_address(true)
.context("set_reuse_address")?;
#[cfg(unix)] #[cfg(unix)]
if let Err(e) = socket.set_reuse_port(true) { if let Err(e) = socket.set_reuse_port(true) {
log::warn!("set_reuse_port {:?}", e) log::warn!("set_reuse_port {:?}", e)
@@ -90,7 +94,9 @@ pub fn bind_udp_ops(
socket2::Type::DGRAM, socket2::Type::DGRAM,
Some(Protocol::UDP), Some(Protocol::UDP),
)?; )?;
socket.set_ip_unicast_if(default_interface)?; if let Err(e) = socket.set_ip_unicast_if(default_interface) {
log::warn!("set_ip_unicast_if {:?}", e)
}
socket socket
} else { } else {
let socket = socket2::Socket::new( let socket = socket2::Socket::new(
+6 -1
View File
@@ -2,7 +2,7 @@ use crate::channel::socket::{get_interface, LocalInterface, VntSocketTrait};
use anyhow::Context; use anyhow::Context;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_os = "linux")]
impl VntSocketTrait for socket2::Socket { impl VntSocketTrait for socket2::Socket {
fn set_ip_unicast_if(&self, interface: &LocalInterface) -> anyhow::Result<()> { fn set_ip_unicast_if(&self, interface: &LocalInterface) -> anyhow::Result<()> {
if let Some(name) = &interface.name { if let Some(name) = &interface.name {
@@ -23,6 +23,7 @@ impl VntSocketTrait for socket2::Socket {
} }
} }
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub fn get_best_interface(dest_ip: Ipv4Addr) -> anyhow::Result<LocalInterface> { pub fn get_best_interface(dest_ip: Ipv4Addr) -> anyhow::Result<LocalInterface> {
match get_interface(dest_ip) { match get_interface(dest_ip) {
Ok(iface) => return Ok(iface), Ok(iface) => return Ok(iface),
@@ -33,3 +34,7 @@ pub fn get_best_interface(dest_ip: Ipv4Addr) -> anyhow::Result<LocalInterface> {
// 应该再查路由表找到默认路由的 // 应该再查路由表找到默认路由的
Ok(LocalInterface::default()) Ok(LocalInterface::default())
} }
#[cfg(target_os = "android")]
pub fn get_best_interface(dest_ip: Ipv4Addr) -> anyhow::Result<LocalInterface> {
Ok(LocalInterface::default())
}
+3 -12
View File
@@ -12,7 +12,6 @@ use crate::channel::context::ChannelContext;
use crate::channel::idle::Idle; use crate::channel::idle::Idle;
use crate::channel::punch::{NatInfo, Punch}; use crate::channel::punch::{NatInfo, Punch};
use crate::channel::sender::IpPacketSender; use crate::channel::sender::IpPacketSender;
use crate::channel::socket::LocalInterface;
use crate::channel::{init_channel, init_context, Route, RouteKey}; use crate::channel::{init_channel, init_context, Route, RouteKey};
use crate::cipher::Cipher; use crate::cipher::Cipher;
#[cfg(feature = "server_encrypt")] #[cfg(feature = "server_encrypt")]
@@ -30,7 +29,7 @@ use crate::tun_tap_device::tun_create_helper::{DeviceAdapter, TunDeviceHelper};
use crate::tun_tap_device::vnt_device::DeviceWrite; use crate::tun_tap_device::vnt_device::DeviceWrite;
use crate::util::limit::TrafficMeterMultiAddress; use crate::util::limit::TrafficMeterMultiAddress;
use crate::util::{Scheduler, StopManager}; use crate::util::{Scheduler, StopManager};
use crate::{channel, nat, VntCallback}; use crate::{nat, VntCallback};
#[derive(Clone)] #[derive(Clone)]
pub struct Vnt { pub struct Vnt {
@@ -139,16 +138,8 @@ impl VntInner {
nat::local_ipv4() nat::local_ipv4()
}; };
let default_interface = if config.in_ips.is_empty() { let default_interface = config.local_interface.clone();
//没有改变路由,不需要绑定网卡 log::info!("default_interface = {:?}", default_interface);
LocalInterface::default()
} else {
//vnt的流量都走这个接口
let default_interface =
channel::socket::get_best_interface(local_ipv4.unwrap_or(Ipv4Addr::UNSPECIFIED))?;
log::info!("default_interface = {:?}", default_interface);
default_interface
};
//基础信息 //基础信息
let config_info = BaseConfigInfo::new( let config_info = BaseConfigInfo::new(
+13 -5
View File
@@ -5,6 +5,7 @@ use std::str::FromStr;
pub use conn::Vnt; pub use conn::Vnt;
use crate::channel::punch::PunchModel; use crate::channel::punch::PunchModel;
use crate::channel::socket::LocalInterface;
use crate::channel::{ConnectProtocol, UseChannelType}; use crate::channel::{ConnectProtocol, UseChannelType};
use crate::cipher::CipherModel; use crate::cipher::CipherModel;
use crate::compression::Compressor; use crate::compression::Compressor;
@@ -53,6 +54,7 @@ pub struct Config {
pub enable_traffic: bool, pub enable_traffic: bool,
pub allow_wire_guard: bool, pub allow_wire_guard: bool,
pub local_ipv4: Option<Ipv4Addr>, pub local_ipv4: Option<Ipv4Addr>,
pub local_interface: LocalInterface,
} }
impl Config { impl Config {
@@ -148,8 +150,11 @@ impl Config {
server_address_str = s.to_string(); server_address_str = s.to_string();
protocol = ConnectProtocol::TCP; protocol = ConnectProtocol::TCP;
} }
server_address = server_address = address_choose(dns_query_all(
address_choose(dns_query_all(&server_address_str, name_servers.clone())?)?; &server_address_str,
name_servers.clone(),
&LocalInterface::default(),
)?)?;
} }
#[cfg(feature = "port_mapping")] #[cfg(feature = "port_mapping")]
let port_mapping_list = crate::port_mapping::convert(port_mapping_list)?; let port_mapping_list = crate::port_mapping::convert(port_mapping_list)?;
@@ -158,9 +163,11 @@ impl Config {
*dest = *mask & *dest; *dest = *mask & *dest;
} }
in_ips.sort_by(|(dest1, _, _), (dest2, _, _)| dest2.cmp(dest1)); in_ips.sort_by(|(dest1, _, _), (dest2, _, _)| dest2.cmp(dest1));
if let Some(local_ip) = local_ipv4 { let local_interface = if let Some(local_ip) = local_ipv4 {
let _ = crate::channel::socket::get_interface(local_ip)?; crate::channel::socket::get_interface(local_ip)?
} } else {
LocalInterface::default()
};
Ok(Self { Ok(Self {
#[cfg(feature = "integrated_tun")] #[cfg(feature = "integrated_tun")]
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@@ -199,6 +206,7 @@ impl Config {
enable_traffic, enable_traffic,
allow_wire_guard, allow_wire_guard,
local_ipv4, local_ipv4,
local_interface,
}) })
} }
} }
+2
View File
@@ -173,6 +173,7 @@ pub enum ErrorType {
InvalidIp, InvalidIp,
LocalIpExists, LocalIpExists,
FailedToCrateDevice, FailedToCrateDevice,
Warn,
Unknown, Unknown,
} }
@@ -186,6 +187,7 @@ impl Into<u8> for ErrorType {
ErrorType::InvalidIp => 5, ErrorType::InvalidIp => 5,
ErrorType::LocalIpExists => 6, ErrorType::LocalIpExists => 6,
ErrorType::FailedToCrateDevice => 101, ErrorType::FailedToCrateDevice => 101,
ErrorType::Warn => 102,
ErrorType::Unknown => 255, ErrorType::Unknown => 255,
} }
} }
+9 -2
View File
@@ -7,6 +7,7 @@ use crossbeam_utils::atomic::AtomicCell;
use crate::channel::context::ChannelContext; use crate::channel::context::ChannelContext;
use crate::channel::idle::{Idle, IdleType}; use crate::channel::idle::{Idle, IdleType};
use crate::channel::sender::ConnectUtil; use crate::channel::sender::ConnectUtil;
use crate::channel::socket::LocalInterface;
use crate::channel::ConnectProtocol; use crate::channel::ConnectProtocol;
use crate::handle::callback::{ConnectInfo, ErrorType}; use crate::handle::callback::{ConnectInfo, ErrorType};
use crate::handle::handshaker::Handshake; use crate::handle::handshaker::Handshake;
@@ -130,7 +131,8 @@ fn check_gateway_channel<Call: VntCallback>(
let connect_protocol = context.main_protocol(); let connect_protocol = context.main_protocol();
if connect_protocol.is_transport() { if connect_protocol.is_transport() {
// 传输层的协议需要探测服务器地址 // 传输层的协议需要探测服务器地址
current_device = domain_request0(current_device_info, config); current_device =
domain_request0(current_device_info, config, context.default_interface());
} }
//需要重连 //需要重连
call.connect(ConnectInfo::new(*count, current_device.connect_server)); call.connect(ConnectInfo::new(*count, current_device.connect_server));
@@ -160,11 +162,16 @@ fn check_gateway_channel<Call: VntCallback>(
pub fn domain_request0( pub fn domain_request0(
current_device: &AtomicCell<CurrentDeviceInfo>, current_device: &AtomicCell<CurrentDeviceInfo>,
config: &BaseConfigInfo, config: &BaseConfigInfo,
default_interface: &LocalInterface,
) -> CurrentDeviceInfo { ) -> CurrentDeviceInfo {
let mut current_dev = current_device.load(); let mut current_dev = current_device.load();
// 探测服务端地址变化 // 探测服务端地址变化
match dns_query_all(&config.server_addr, config.name_servers.clone()) { match dns_query_all(
&config.server_addr,
config.name_servers.clone(),
default_interface,
) {
Ok(addrs) => { Ok(addrs) => {
log::info!( log::info!(
"domain {} dns {:?} addr {:?}", "domain {} dns {:?} addr {:?}",
+4 -1
View File
@@ -355,7 +355,10 @@ impl<Call: VntCallback, Device: DeviceWrite> ServerPacketHandler<Call, Device> {
target_os = "linux", target_os = "linux",
target_os = "macos" target_os = "macos"
))] ))]
match crate::tun_tap_device::create_device(device_config) { match crate::tun_tap_device::create_device(
device_config,
&self.callback,
) {
Ok(device) => { Ok(device) => {
use tun::device::IFace; use tun::device::IFace;
let tun_info = crate::handle::callback::DeviceInfo::new( let tun_info = crate::handle::callback::DeviceInfo::new(
+3 -1
View File
@@ -52,7 +52,9 @@ impl IcmpProxy {
.bind(&socket2::SockAddr::from(addr)) .bind(&socket2::SockAddr::from(addr))
.context("bind Socket ICMPV4 failed")?; .context("bind Socket ICMPV4 failed")?;
icmp_socket.set_nonblocking(true)?; icmp_socket.set_nonblocking(true)?;
icmp_socket.set_ip_unicast_if(default_interface)?; if let Err(e) = icmp_socket.set_ip_unicast_if(default_interface) {
log::warn!("set_ip_unicast_if {:?}", e)
}
let std_socket: std::net::UdpSocket = icmp_socket.into(); let std_socket: std::net::UdpSocket = icmp_socket.into();
let tokio_icmp_socket = UdpSocket::from_std(std_socket.try_clone()?)?; let tokio_icmp_socket = UdpSocket::from_std(std_socket.try_clone()?)?;
+13 -3
View File
@@ -1,4 +1,4 @@
use crate::{DeviceConfig, ErrorInfo, ErrorType}; use crate::{DeviceConfig, ErrorInfo, ErrorType, VntCallback};
use std::io; use std::io;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::sync::Arc; use std::sync::Arc;
@@ -10,7 +10,10 @@ const DEFAULT_TUN_NAME: &str = "vnt-tun";
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
const DEFAULT_TAP_NAME: &str = "vnt-tap"; const DEFAULT_TAP_NAME: &str = "vnt-tap";
pub fn create_device(config: DeviceConfig) -> Result<Arc<Device>, ErrorInfo> { pub fn create_device<Call: VntCallback>(
config: DeviceConfig,
call: &Call,
) -> Result<Arc<Device>, ErrorInfo> {
let device = match create_device0(&config) { let device = match create_device0(&config) {
Ok(device) => device, Ok(device) => device,
Err(e) => { Err(e) => {
@@ -44,7 +47,14 @@ pub fn create_device(config: DeviceConfig) -> Result<Arc<Device>, ErrorInfo> {
for (dest, mask) in config.external_route { for (dest, mask) in config.external_route {
if let Err(e) = device.add_route(dest, mask, 1) { if let Err(e) = device.add_route(dest, mask, 1) {
log::warn!("添加路由失败 ={:?}", e); log::warn!("添加路由失败,请检查-i参数是否和现有路由冲突 ={:?}", e);
call.error(ErrorInfo::new_msg(
ErrorType::Warn,
format!(
"警告! 添加路由失败,请检查-i参数是否和现有路由冲突 ={:?}",
e
),
))
} }
} }
Ok(device) Ok(device)
+36 -15
View File
@@ -5,6 +5,7 @@ use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use crate::channel::socket::LocalInterface;
use anyhow::Context; use anyhow::Context;
use dns_parser::{Builder, Packet, QueryClass, QueryType, RData, ResponseCode}; use dns_parser::{Builder, Packet, QueryClass, QueryType, RData, ResponseCode};
@@ -79,6 +80,7 @@ fn address_choose0(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
pub fn dns_query_all( pub fn dns_query_all(
domain: &str, domain: &str,
mut name_servers: Vec<String>, mut name_servers: Vec<String>,
default_interface: &LocalInterface,
) -> anyhow::Result<Vec<SocketAddr>> { ) -> anyhow::Result<Vec<SocketAddr>> {
match SocketAddr::from_str(domain) { match SocketAddr::from_str(domain) {
Ok(addr) => Ok(vec![addr]), Ok(addr) => Ok(vec![addr]),
@@ -102,7 +104,7 @@ pub fn dns_query_all(
let mut err: Option<anyhow::Error> = None; let mut err: Option<anyhow::Error> = None;
for name_server in name_servers { for name_server in name_servers {
if let Some(domain) = txt_domain.as_ref() { if let Some(domain) = txt_domain.as_ref() {
match txt_dns(domain, name_server) { match txt_dns(domain, name_server, default_interface) {
Ok(addr) => { Ok(addr) => {
if !addr.is_empty() { if !addr.is_empty() {
return Ok(addr); return Ok(addr);
@@ -127,12 +129,14 @@ pub fn dns_query_all(
let th1 = { let th1 = {
let host = host.to_string(); let host = host.to_string();
let name_server = name_server.clone(); let name_server = name_server.clone();
thread::spawn(move || a_dns(host, name_server)) let default_interface = default_interface.clone();
thread::spawn(move || a_dns(host, name_server, &default_interface))
}; };
let th2 = { let th2 = {
let host = host.to_string(); let host = host.to_string();
let name_server = name_server.clone(); let name_server = name_server.clone();
thread::spawn(move || aaaa_dns(host, name_server)) let default_interface = default_interface.clone();
thread::spawn(move || aaaa_dns(host, name_server, &default_interface))
}; };
let mut addr = Vec::new(); let mut addr = Vec::new();
match th1.join().unwrap() { match th1.join().unwrap() {
@@ -230,9 +234,13 @@ fn query<'a>(
Ok(pkt) Ok(pkt)
} }
pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAddr>> { pub fn txt_dns(
domain: &str,
name_server: String,
default_interface: &LocalInterface,
) -> anyhow::Result<Vec<SocketAddr>> {
let name_server: SocketAddr = name_server.parse()?; let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?; let udp = bind_udp(name_server, default_interface)?;
let mut buf = [0; 65536]; let mut buf = [0; 65536];
let message = query(&udp, domain, name_server, QueryType::TXT, &mut buf)?; let message = query(&udp, domain, name_server, QueryType::TXT, &mut buf)?;
let mut rs = Vec::new(); let mut rs = Vec::new();
@@ -249,19 +257,28 @@ pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAd
Ok(rs) Ok(rs)
} }
fn bind_udp(name_server: SocketAddr) -> anyhow::Result<UdpSocket> { fn bind_udp(
let udp = if name_server.is_ipv4() { name_server: SocketAddr,
UdpSocket::bind("0.0.0.0:0")? default_interface: &LocalInterface,
) -> anyhow::Result<UdpSocket> {
let addr: SocketAddr = if name_server.is_ipv4() {
"0.0.0.0:0".parse().unwrap()
} else { } else {
UdpSocket::bind("[::]:0")? "[::]:0".parse().unwrap()
}; };
udp.set_read_timeout(Some(Duration::from_millis(800)))?; let socket = crate::channel::socket::bind_udp(addr, default_interface)?;
Ok(udp) socket.set_nonblocking(false)?;
socket.set_read_timeout(Some(Duration::from_millis(800)))?;
Ok(socket.into())
} }
pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr>> { pub fn a_dns(
domain: String,
name_server: String,
default_interface: &LocalInterface,
) -> anyhow::Result<Vec<Ipv4Addr>> {
let name_server: SocketAddr = name_server.parse()?; let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?; let udp = bind_udp(name_server, default_interface)?;
let mut buf = [0; 65536]; let mut buf = [0; 65536];
let message = query(&udp, &domain, name_server, QueryType::A, &mut buf)?; let message = query(&udp, &domain, name_server, QueryType::A, &mut buf)?;
let mut rs = Vec::new(); let mut rs = Vec::new();
@@ -273,9 +290,13 @@ pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr
Ok(rs) Ok(rs)
} }
pub fn aaaa_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv6Addr>> { pub fn aaaa_dns(
domain: String,
name_server: String,
default_interface: &LocalInterface,
) -> anyhow::Result<Vec<Ipv6Addr>> {
let name_server: SocketAddr = name_server.parse()?; let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?; let udp = bind_udp(name_server, default_interface)?;
let mut buf = [0; 65536]; let mut buf = [0; 65536];
let message = query(&udp, &domain, name_server, QueryType::AAAA, &mut buf)?; let message = query(&udp, &domain, name_server, QueryType::AAAA, &mut buf)?;
let mut rs = Vec::new(); let mut rs = Vec::new();