支持选择tcp或udp打洞
This commit is contained in:
+1
-1
@@ -363,7 +363,7 @@ fn get_description(key: &str, language: &str) -> String {
|
||||
("--ip <ip>", ("指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", "Specify virtual IP, must be unique and valid within server subnet, by default allocated by server")),
|
||||
("--model <model>", ("加密模式(默认aes_gcm),可选值{}", "Encryption mode (default aes_gcm), options {}")),
|
||||
("--finger", ("增加数据指纹校验,可增加安全性,如果服务端开启指纹校验,则客户端也必须开启", "Add data fingerprint verification for increased security, client must enable if server does")),
|
||||
("--punch <punch>", ("取值ipv4/ipv6/all,ipv4表示仅使用ipv4打洞", "Values ipv4/ipv6/all, ipv4 for IPv4 hole punching only")),
|
||||
("--punch <punch>", ("取值ipv4/ipv6/ipv4-tcp/ipv4-udp/ipv6-tcp/ipv6-udp/all,ipv4表示仅使用ipv4打洞", "Values ipv4/ipv6/ipv4-tcp/ipv4-udp/ipv6-tcp/ipv6-udp/all, ipv4 for IPv4 hole punching only")),
|
||||
("--ports <port,port>", ("取值0~65535,指定本地监听的一组端口,默认监听两个随机端口,使用过多端口会增加网络负担", "Values 0~65535, specify a group of local listening ports, defaults to two random ports, using many ports increases network load")),
|
||||
("--cmd", ("开启交互式命令,使用此参数开启控制台输入", "Enable interactive command mode, use this parameter to enable console input")),
|
||||
("--no-proxy", ("关闭内置代理,如需点对网则需要配置网卡NAT转发", "Disable built-in proxy, configure network card NAT forwarding for point-to-point networking")),
|
||||
|
||||
+88
-29
@@ -14,15 +14,38 @@ use crate::channel::context::ChannelContext;
|
||||
use crate::channel::sender::ConnectUtil;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::nat::NatTest;
|
||||
use crate::nat::{is_ipv4_global, NatTest};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum PunchModel {
|
||||
IPv4,
|
||||
IPv6,
|
||||
IPv4Tcp,
|
||||
IPv4Udp,
|
||||
IPv6Tcp,
|
||||
IPv6Udp,
|
||||
All,
|
||||
}
|
||||
|
||||
impl PunchModel {
|
||||
pub fn use_tcp(&self) -> bool {
|
||||
self != &PunchModel::IPv4Udp && self != &PunchModel::IPv6Udp
|
||||
}
|
||||
pub fn use_udp(&self) -> bool {
|
||||
self != &PunchModel::IPv4Tcp && self != &PunchModel::IPv6Tcp
|
||||
}
|
||||
pub fn use_ipv6(&self) -> bool {
|
||||
self == &PunchModel::All
|
||||
|| self == &PunchModel::IPv6
|
||||
|| self == &PunchModel::IPv6Tcp
|
||||
|| self == &PunchModel::IPv6Udp
|
||||
}
|
||||
pub fn use_ipv4(&self) -> bool {
|
||||
self == &PunchModel::All
|
||||
|| self == &PunchModel::IPv4
|
||||
|| self == &PunchModel::IPv4Tcp
|
||||
|| self == &PunchModel::IPv4Udp
|
||||
}
|
||||
}
|
||||
impl FromStr for PunchModel {
|
||||
type Err = String;
|
||||
|
||||
@@ -30,8 +53,15 @@ impl FromStr for PunchModel {
|
||||
match s.to_lowercase().trim() {
|
||||
"ipv4" => Ok(PunchModel::IPv4),
|
||||
"ipv6" => Ok(PunchModel::IPv6),
|
||||
"ipv4-tcp" => Ok(PunchModel::IPv4Tcp),
|
||||
"ipv4-udp" => Ok(PunchModel::IPv4Udp),
|
||||
"ipv6-tcp" => Ok(PunchModel::IPv6Tcp),
|
||||
"ipv6-udp" => Ok(PunchModel::IPv6Udp),
|
||||
"all" => Ok(PunchModel::All),
|
||||
_ => Err(format!("not match '{}', enum: ipv4/ipv6/all", s)),
|
||||
_ => Err(format!(
|
||||
"not match '{}', enum: ipv4/ipv4-tcp/ipv4-udp/ipv6/ipv6-tcp/ipv6-udp/all",
|
||||
s
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +217,6 @@ pub struct Punch {
|
||||
port_vec: Vec<u16>,
|
||||
port_index: HashMap<Ipv4Addr, usize>,
|
||||
punch_model: PunchModel,
|
||||
is_tcp: bool,
|
||||
connect_util: ConnectUtil,
|
||||
external_route: ExternalRoute,
|
||||
nat_test: NatTest,
|
||||
@@ -198,7 +227,6 @@ impl Punch {
|
||||
pub fn new(
|
||||
context: ChannelContext,
|
||||
punch_model: PunchModel,
|
||||
is_tcp: bool,
|
||||
connect_util: ConnectUtil,
|
||||
external_route: ExternalRoute,
|
||||
nat_test: NatTest,
|
||||
@@ -213,7 +241,6 @@ impl Punch {
|
||||
port_vec,
|
||||
port_index: HashMap::new(),
|
||||
punch_model,
|
||||
is_tcp,
|
||||
connect_util,
|
||||
external_route,
|
||||
nat_test,
|
||||
@@ -242,48 +269,53 @@ impl Punch {
|
||||
return Ok(());
|
||||
}
|
||||
let device_info = self.current_device.load();
|
||||
|
||||
nat_info.public_ips.retain(|ip| {
|
||||
is_ipv4_global(ip)
|
||||
&& self.external_route.route(ip).is_none()
|
||||
&& device_info.not_in_network(*ip)
|
||||
});
|
||||
nat_info.public_ports.retain(|port| *port != 0);
|
||||
nat_info.udp_ports.retain(|port| *port != 0);
|
||||
|
||||
nat_info.local_ipv4 = nat_info.local_ipv4.filter(|ip| {
|
||||
self.external_route.route(ip).is_none() && device_info.not_in_network(*ip)
|
||||
});
|
||||
nat_info.local_ipv4.filter(|ip| {
|
||||
self.external_route.route(ip).is_none() && device_info.not_in_network(*ip)
|
||||
});
|
||||
nat_info.ipv6.filter(|ip| {
|
||||
nat_info.ipv6 = nat_info.ipv6.filter(|ip| {
|
||||
if let Some(ip) = ip.to_ipv4() {
|
||||
self.external_route.route(&ip).is_none()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
if punch_tcp && self.is_tcp && nat_info.tcp_port != 0 {
|
||||
if punch_tcp && self.punch_model.use_tcp() && nat_info.tcp_port != 0 {
|
||||
//向tcp发起连接
|
||||
if let Some(ipv6_addr) = nat_info.local_tcp_ipv6addr() {
|
||||
self.connect_tcp(buf, ipv6_addr)
|
||||
if self.punch_model.use_ipv6() {
|
||||
if let Some(ipv6_addr) = nat_info.local_tcp_ipv6addr() {
|
||||
self.connect_tcp(buf, ipv6_addr)
|
||||
}
|
||||
}
|
||||
//向tcp发起连接
|
||||
if let Some(ipv4_addr) = nat_info.local_tcp_ipv4addr() {
|
||||
self.connect_tcp(buf, ipv4_addr)
|
||||
}
|
||||
for ip in &nat_info.public_ips {
|
||||
let addr = SocketAddr::V4(SocketAddrV4::new(*ip, nat_info.tcp_port));
|
||||
self.connect_tcp(buf, addr)
|
||||
}
|
||||
}
|
||||
let channel_num = self.context.channel_num();
|
||||
for index in 0..channel_num {
|
||||
if let Some(ipv4_addr) = nat_info.local_udp_ipv4addr(index) {
|
||||
if !self.nat_test.is_local_address(false, ipv4_addr) {
|
||||
let _ = self.context.send_main_udp(index, buf, ipv4_addr);
|
||||
if self.punch_model.use_ipv4() {
|
||||
if let Some(ipv4_addr) = nat_info.local_tcp_ipv4addr() {
|
||||
self.connect_tcp(buf, ipv4_addr)
|
||||
}
|
||||
for ip in &nat_info.public_ips {
|
||||
let addr = SocketAddr::V4(SocketAddrV4::new(*ip, nat_info.tcp_port));
|
||||
self.connect_tcp(buf, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !self.punch_model.use_udp() {
|
||||
return Ok(());
|
||||
}
|
||||
let channel_num = self.context.channel_num();
|
||||
|
||||
if self.punch_model != PunchModel::IPv4 {
|
||||
if self.punch_model.use_ipv6() {
|
||||
for index in 0..channel_num {
|
||||
if let Some(ipv6_addr) = nat_info.local_udp_ipv6addr(index) {
|
||||
if !self.nat_test.is_local_address(false, ipv6_addr) {
|
||||
let rs = self.context.send_main_udp(index, buf, ipv6_addr);
|
||||
log::info!("发送到ipv6地址:{:?},rs={:?}", ipv6_addr, rs);
|
||||
log::info!("发送到ipv6地址:{:?},rs={:?} {}", ipv6_addr, rs, id);
|
||||
if rs.is_ok() && self.punch_model == PunchModel::IPv6 {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -291,6 +323,33 @@ impl Punch {
|
||||
}
|
||||
}
|
||||
}
|
||||
if !self.punch_model.use_ipv4() {
|
||||
return Ok(());
|
||||
}
|
||||
for index in 0..channel_num {
|
||||
if let Some(ipv4_addr) = nat_info.local_udp_ipv4addr(index) {
|
||||
if !self.nat_test.is_local_address(false, ipv4_addr) {
|
||||
let _ = self.context.send_main_udp(index, buf, ipv4_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 可能是开放了端口的,需要打洞
|
||||
for index in 0..channel_num {
|
||||
for port in &nat_info.udp_ports {
|
||||
if *port == 0 {
|
||||
continue;
|
||||
}
|
||||
for ip in &nat_info.public_ips {
|
||||
if ip.is_unspecified() {
|
||||
continue;
|
||||
}
|
||||
let addr = SocketAddrV4::new(*ip, *port);
|
||||
let _ = self.context.send_main_udp(index, buf, addr.into());
|
||||
thread::sleep(Duration::from_millis(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match nat_info.nat_type {
|
||||
NatType::Symmetric => {
|
||||
// 假设对方绑定n个端口,通过NAT对外映射出n个 公网ip:公网端口,自己随机尝试k次的情况下
|
||||
|
||||
@@ -266,7 +266,6 @@ impl VntInner {
|
||||
let punch = Punch::new(
|
||||
context.clone(),
|
||||
config.punch_model,
|
||||
config.protocol.is_base_tcp(),
|
||||
connect_util.clone(),
|
||||
external_route.clone(),
|
||||
nat_test.clone(),
|
||||
|
||||
Reference in New Issue
Block a user