调整默认网卡的逻辑

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 {
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 {
socket.set_reuse_address(true)?;
socket
.set_reuse_address(true)
.context("set_reuse_address")?;
#[cfg(unix)]
if let Err(e) = socket.set_reuse_port(true) {
log::warn!("set_reuse_port {:?}", e)
@@ -90,7 +94,9 @@ pub fn bind_udp_ops(
socket2::Type::DGRAM,
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
} else {
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 std::net::Ipv4Addr;
#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(target_os = "linux")]
impl VntSocketTrait for socket2::Socket {
fn set_ip_unicast_if(&self, interface: &LocalInterface) -> anyhow::Result<()> {
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> {
match get_interface(dest_ip) {
Ok(iface) => return Ok(iface),
@@ -33,3 +34,7 @@ pub fn get_best_interface(dest_ip: Ipv4Addr) -> anyhow::Result<LocalInterface> {
// 应该再查路由表找到默认路由的
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::punch::{NatInfo, Punch};
use crate::channel::sender::IpPacketSender;
use crate::channel::socket::LocalInterface;
use crate::channel::{init_channel, init_context, Route, RouteKey};
use crate::cipher::Cipher;
#[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::util::limit::TrafficMeterMultiAddress;
use crate::util::{Scheduler, StopManager};
use crate::{channel, nat, VntCallback};
use crate::{nat, VntCallback};
#[derive(Clone)]
pub struct Vnt {
@@ -139,16 +138,8 @@ impl VntInner {
nat::local_ipv4()
};
let default_interface = if config.in_ips.is_empty() {
//没有改变路由,不需要绑定网卡
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 default_interface = config.local_interface.clone();
log::info!("default_interface = {:?}", default_interface);
//基础信息
let config_info = BaseConfigInfo::new(
+13 -5
View File
@@ -5,6 +5,7 @@ use std::str::FromStr;
pub use conn::Vnt;
use crate::channel::punch::PunchModel;
use crate::channel::socket::LocalInterface;
use crate::channel::{ConnectProtocol, UseChannelType};
use crate::cipher::CipherModel;
use crate::compression::Compressor;
@@ -53,6 +54,7 @@ pub struct Config {
pub enable_traffic: bool,
pub allow_wire_guard: bool,
pub local_ipv4: Option<Ipv4Addr>,
pub local_interface: LocalInterface,
}
impl Config {
@@ -148,8 +150,11 @@ impl Config {
server_address_str = s.to_string();
protocol = ConnectProtocol::TCP;
}
server_address =
address_choose(dns_query_all(&server_address_str, name_servers.clone())?)?;
server_address = address_choose(dns_query_all(
&server_address_str,
name_servers.clone(),
&LocalInterface::default(),
)?)?;
}
#[cfg(feature = "port_mapping")]
let port_mapping_list = crate::port_mapping::convert(port_mapping_list)?;
@@ -158,9 +163,11 @@ impl Config {
*dest = *mask & *dest;
}
in_ips.sort_by(|(dest1, _, _), (dest2, _, _)| dest2.cmp(dest1));
if let Some(local_ip) = local_ipv4 {
let _ = crate::channel::socket::get_interface(local_ip)?;
}
let local_interface = if let Some(local_ip) = local_ipv4 {
crate::channel::socket::get_interface(local_ip)?
} else {
LocalInterface::default()
};
Ok(Self {
#[cfg(feature = "integrated_tun")]
#[cfg(target_os = "windows")]
@@ -199,6 +206,7 @@ impl Config {
enable_traffic,
allow_wire_guard,
local_ipv4,
local_interface,
})
}
}
+2
View File
@@ -173,6 +173,7 @@ pub enum ErrorType {
InvalidIp,
LocalIpExists,
FailedToCrateDevice,
Warn,
Unknown,
}
@@ -186,6 +187,7 @@ impl Into<u8> for ErrorType {
ErrorType::InvalidIp => 5,
ErrorType::LocalIpExists => 6,
ErrorType::FailedToCrateDevice => 101,
ErrorType::Warn => 102,
ErrorType::Unknown => 255,
}
}
+9 -2
View File
@@ -7,6 +7,7 @@ use crossbeam_utils::atomic::AtomicCell;
use crate::channel::context::ChannelContext;
use crate::channel::idle::{Idle, IdleType};
use crate::channel::sender::ConnectUtil;
use crate::channel::socket::LocalInterface;
use crate::channel::ConnectProtocol;
use crate::handle::callback::{ConnectInfo, ErrorType};
use crate::handle::handshaker::Handshake;
@@ -130,7 +131,8 @@ fn check_gateway_channel<Call: VntCallback>(
let connect_protocol = context.main_protocol();
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));
@@ -160,11 +162,16 @@ fn check_gateway_channel<Call: VntCallback>(
pub fn domain_request0(
current_device: &AtomicCell<CurrentDeviceInfo>,
config: &BaseConfigInfo,
default_interface: &LocalInterface,
) -> CurrentDeviceInfo {
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) => {
log::info!(
"domain {} dns {:?} addr {:?}",
+4 -1
View File
@@ -355,7 +355,10 @@ impl<Call: VntCallback, Device: DeviceWrite> ServerPacketHandler<Call, Device> {
target_os = "linux",
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) => {
use tun::device::IFace;
let tun_info = crate::handle::callback::DeviceInfo::new(
+3 -1
View File
@@ -52,7 +52,9 @@ impl IcmpProxy {
.bind(&socket2::SockAddr::from(addr))
.context("bind Socket ICMPV4 failed")?;
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 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::net::Ipv4Addr;
use std::sync::Arc;
@@ -10,7 +10,10 @@ const DEFAULT_TUN_NAME: &str = "vnt-tun";
#[cfg(target_os = "windows")]
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) {
Ok(device) => device,
Err(e) => {
@@ -44,7 +47,14 @@ pub fn create_device(config: DeviceConfig) -> Result<Arc<Device>, ErrorInfo> {
for (dest, mask) in config.external_route {
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)
+36 -15
View File
@@ -5,6 +5,7 @@ use std::str::FromStr;
use std::time::Duration;
use std::{io, thread};
use crate::channel::socket::LocalInterface;
use anyhow::Context;
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(
domain: &str,
mut name_servers: Vec<String>,
default_interface: &LocalInterface,
) -> anyhow::Result<Vec<SocketAddr>> {
match SocketAddr::from_str(domain) {
Ok(addr) => Ok(vec![addr]),
@@ -102,7 +104,7 @@ pub fn dns_query_all(
let mut err: Option<anyhow::Error> = None;
for name_server in name_servers {
if let Some(domain) = txt_domain.as_ref() {
match txt_dns(domain, name_server) {
match txt_dns(domain, name_server, default_interface) {
Ok(addr) => {
if !addr.is_empty() {
return Ok(addr);
@@ -127,12 +129,14 @@ pub fn dns_query_all(
let th1 = {
let host = host.to_string();
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 host = host.to_string();
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();
match th1.join().unwrap() {
@@ -230,9 +234,13 @@ fn query<'a>(
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 udp = bind_udp(name_server)?;
let udp = bind_udp(name_server, default_interface)?;
let mut buf = [0; 65536];
let message = query(&udp, domain, name_server, QueryType::TXT, &mut buf)?;
let mut rs = Vec::new();
@@ -249,19 +257,28 @@ pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAd
Ok(rs)
}
fn bind_udp(name_server: SocketAddr) -> anyhow::Result<UdpSocket> {
let udp = if name_server.is_ipv4() {
UdpSocket::bind("0.0.0.0:0")?
fn bind_udp(
name_server: SocketAddr,
default_interface: &LocalInterface,
) -> anyhow::Result<UdpSocket> {
let addr: SocketAddr = if name_server.is_ipv4() {
"0.0.0.0:0".parse().unwrap()
} else {
UdpSocket::bind("[::]:0")?
"[::]:0".parse().unwrap()
};
udp.set_read_timeout(Some(Duration::from_millis(800)))?;
Ok(udp)
let socket = crate::channel::socket::bind_udp(addr, default_interface)?;
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 udp = bind_udp(name_server)?;
let udp = bind_udp(name_server, default_interface)?;
let mut buf = [0; 65536];
let message = query(&udp, &domain, name_server, QueryType::A, &mut buf)?;
let mut rs = Vec::new();
@@ -273,9 +290,13 @@ pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr
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 udp = bind_udp(name_server)?;
let udp = bind_udp(name_server, default_interface)?;
let mut buf = [0; 65536];
let message = query(&udp, &domain, name_server, QueryType::AAAA, &mut buf)?;
let mut rs = Vec::new();