支持upnp
This commit is contained in:
+5
-3
@@ -6,7 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tun = { path = "tun" ,optional = true}
|
||||
tun = { path = "tun", optional = true }
|
||||
packet = { path = "./packet" }
|
||||
bytes = "1.5.0"
|
||||
log = "0.4.17"
|
||||
@@ -32,7 +32,7 @@ spki = { version = "0.7.2", features = ["fingerprint", "alloc", "base64"], optio
|
||||
openssl-sys = { git = "https://github.com/lbl8603/rust-openssl", optional = true }
|
||||
libsm = { git = "https://github.com/lbl8603/libsm", optional = true }
|
||||
|
||||
mio = { version = "0.8.10", features = ["os-poll", "net", "os-ext"] }
|
||||
mio = { version = "1.0.0", features = ["os-poll", "net", "os-ext"] }
|
||||
crossbeam-queue = "0.3.11"
|
||||
anyhow = "1.0.82"
|
||||
dns-parser = "0.8.0"
|
||||
@@ -43,6 +43,7 @@ lz4_flex = { version = "0.11", default-features = false, optional = true }
|
||||
zstd = { version = "0.13.1", optional = true }
|
||||
|
||||
fnv = "1.0.7"
|
||||
igd = { version = "0.12.1", optional = true }
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
libloading = "0.8.0"
|
||||
|
||||
@@ -53,7 +54,7 @@ protoc-bin-vendored = "3.0.0"
|
||||
cfg_aliases = "0.2.1"
|
||||
|
||||
[features]
|
||||
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "lz4_compress", "zstd_compress","integrated_tun"]
|
||||
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "lz4_compress", "zstd_compress", "integrated_tun"]
|
||||
openssl = ["openssl-sys"]
|
||||
# 从源码编译
|
||||
openssl-vendored = ["openssl-sys/vendored"]
|
||||
@@ -69,3 +70,4 @@ port_mapping = ["tokio"]
|
||||
lz4_compress = ["lz4_flex"]
|
||||
zstd_compress = ["zstd"]
|
||||
integrated_tun = ["tun"]
|
||||
upnp = ["igd"]
|
||||
|
||||
@@ -42,6 +42,9 @@ fn retrieve_nat_type0(
|
||||
log::warn!("nat re_test {:?}", e);
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "upnp")]
|
||||
nat_test.reset_upnp();
|
||||
log::info!("刷新nat成功")
|
||||
}
|
||||
})
|
||||
.expect("natTest");
|
||||
|
||||
+22
-1
@@ -13,6 +13,8 @@ use rand::Rng;
|
||||
|
||||
use crate::channel::punch::{NatInfo, NatType};
|
||||
use crate::proto::message::PunchNatType;
|
||||
#[cfg(feature = "upnp")]
|
||||
use crate::util::UPnP;
|
||||
|
||||
mod stun;
|
||||
|
||||
@@ -111,6 +113,8 @@ pub struct NatTest {
|
||||
time: Arc<AtomicCell<Instant>>,
|
||||
udp_ports: Vec<u16>,
|
||||
tcp_port: u16,
|
||||
#[cfg(feature = "upnp")]
|
||||
upnp: UPnP,
|
||||
}
|
||||
|
||||
impl From<NatType> for PunchNatType {
|
||||
@@ -157,6 +161,14 @@ impl NatTest {
|
||||
NatType::Cone,
|
||||
);
|
||||
let info = Arc::new(Mutex::new(nat_info));
|
||||
#[cfg(feature = "upnp")]
|
||||
let upnp = UPnP::default();
|
||||
#[cfg(feature = "upnp")]
|
||||
for port in &udp_ports {
|
||||
upnp.add_udp_port(*port);
|
||||
}
|
||||
#[cfg(feature = "upnp")]
|
||||
upnp.add_tcp_port(tcp_port);
|
||||
NatTest {
|
||||
stun_server,
|
||||
info,
|
||||
@@ -165,6 +177,8 @@ impl NatTest {
|
||||
)),
|
||||
udp_ports,
|
||||
tcp_port,
|
||||
#[cfg(feature = "upnp")]
|
||||
upnp,
|
||||
}
|
||||
}
|
||||
pub fn can_update(&self) -> bool {
|
||||
@@ -255,6 +269,13 @@ impl NatTest {
|
||||
|
||||
Ok(guard.clone())
|
||||
}
|
||||
#[cfg(feature = "upnp")]
|
||||
pub fn reset_upnp(&self) {
|
||||
let local_ipv4 = self.info.lock().local_ipv4.clone();
|
||||
if let Some(local_ipv4) = local_ipv4 {
|
||||
self.upnp.reset(local_ipv4)
|
||||
}
|
||||
}
|
||||
pub fn send_data(&self) -> anyhow::Result<(Vec<u8>, SocketAddr)> {
|
||||
let len = self.stun_server.len();
|
||||
let stun_server = if len == 1 {
|
||||
@@ -297,7 +318,7 @@ impl NatTest {
|
||||
let source_ip = match source_addr.ip() {
|
||||
IpAddr::V4(ip) => ip,
|
||||
IpAddr::V6(ip) => {
|
||||
if let Some(ip) = ip.to_ipv4_mapped() {
|
||||
if let Some(ip) = ip.to_ipv4() {
|
||||
ip
|
||||
} else {
|
||||
return Ok(());
|
||||
|
||||
@@ -8,3 +8,8 @@ pub use counter::*;
|
||||
|
||||
mod dns_query;
|
||||
pub use dns_query::*;
|
||||
|
||||
#[cfg(feature = "upnp")]
|
||||
mod upnp;
|
||||
#[cfg(feature = "upnp")]
|
||||
pub use upnp::*;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
use igd::{search_gateway, PortMappingProtocol};
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct UPnP {
|
||||
inner: Arc<UpnpInner>,
|
||||
}
|
||||
|
||||
impl Deref for UPnP {
|
||||
type Target = UpnpInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UpnpInner {
|
||||
list: Mutex<Vec<(PortMappingProtocol, u16)>>,
|
||||
}
|
||||
|
||||
impl UpnpInner {
|
||||
pub fn add_tcp_port(&self, port: u16) {
|
||||
self.list.lock().push((PortMappingProtocol::TCP, port));
|
||||
}
|
||||
pub fn add_udp_port(&self, port: u16) {
|
||||
self.list.lock().push((PortMappingProtocol::UDP, port));
|
||||
}
|
||||
pub fn reset(&self, local_ip: Ipv4Addr) {
|
||||
let gateway = match search_gateway(Default::default()) {
|
||||
Ok(gateway) => gateway,
|
||||
Err(e) => {
|
||||
log::warn!("search_gateway {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let guard = self.list.lock();
|
||||
|
||||
// 不支持upnp的情况会阻塞30秒,之后再改这个库
|
||||
for (protocol, port) in guard.iter() {
|
||||
let local_addr = SocketAddrV4::new(local_ip, *port);
|
||||
log::info!("add upnp protocol={} {}", protocol, local_addr);
|
||||
if let Err(e) = gateway.add_port(*protocol, *port, local_addr, 700, "upnp") {
|
||||
log::warn!(
|
||||
"add upnp failed protocol={},port={} err:{:?}",
|
||||
protocol,
|
||||
port,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for UpnpInner {
|
||||
fn drop(&mut self) {
|
||||
// let gateway = match search_gateway(Default::default()) {
|
||||
// Ok(gateway) => gateway,
|
||||
// Err(e) => {
|
||||
// log::warn!("search_gateway {:?}", e);
|
||||
// return;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// let guard = self.list.lock();
|
||||
// for (protocol, port) in guard.iter() {
|
||||
// if let Err(e) = gateway.remove_port(*protocol, *port) {
|
||||
// log::warn!(
|
||||
// "remove upnp failed protocol={},port={} err:{:?}",
|
||||
// protocol,
|
||||
// port,
|
||||
// e
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user