支持upnp

This commit is contained in:
lbl8603
2024-06-29 17:29:37 +08:00
parent 1f80e06d9d
commit 218483f431
8 changed files with 257 additions and 9 deletions
Generated
+139 -3
View File
@@ -88,6 +88,18 @@ version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]]
name = "attohttpc"
version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247"
dependencies = [
"http",
"log",
"url",
"wildmatch",
]
[[package]]
name = "autocfg"
version = "1.2.0"
@@ -513,6 +525,15 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -604,6 +625,17 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "http"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "humantime"
version = "2.1.0"
@@ -633,6 +665,29 @@ dependencies = [
"cc",
]
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "igd"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556b5a75cd4adb7c4ea21c64af1c48cefb2ce7d43dc4352c720a1fe47c21f355"
dependencies = [
"attohttpc",
"log",
"rand",
"url",
"xmltree",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -861,11 +916,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "mio"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4929e1f84c5e54c3ec6141cd5d8b5a5c055f031f80cf78f2072920173cb4d880"
dependencies = [
"hermit-abi",
"libc",
"log",
"wasi",
"windows-sys 0.52.0",
]
[[package]]
name = "nom"
version = "7.1.3"
@@ -1033,6 +1100,12 @@ dependencies = [
"base64ct",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
@@ -1614,6 +1687,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "tinyvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.37.0"
@@ -1623,7 +1711,7 @@ dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"mio 0.8.11",
"num_cpus",
"parking_lot",
"pin-project-lite",
@@ -1672,12 +1760,27 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-width"
version = "0.1.11"
@@ -1715,6 +1818,17 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "uuid"
version = "1.8.0"
@@ -1777,12 +1891,13 @@ dependencies = [
"dns-parser",
"ecb",
"fnv",
"igd",
"libc",
"libloading",
"libsm",
"log",
"lz4_flex",
"mio",
"mio 1.0.0",
"openssl-sys",
"packet",
"parking_lot",
@@ -1895,6 +2010,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
[[package]]
name = "wildmatch"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a"
[[package]]
name = "winapi"
version = "0.3.9"
@@ -2065,6 +2186,21 @@ version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "xml-rs"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193"
[[package]]
name = "xmltree"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb"
dependencies = [
"xml-rs",
]
[[package]]
name = "yasna"
version = "0.5.2"
+1 -1
View File
@@ -32,7 +32,7 @@ ip_proxy = ["vnt/ip_proxy"]
port_mapping = ["vnt/port_mapping"]
lz4 = ["vnt/lz4_compress"]
zstd = ["vnt/zstd_compress"]
upnp = ["vnt/upnp"]
command = []
file_config = []
log = ["log4rs"]
+1 -1
View File
@@ -39,7 +39,7 @@ ip_proxy = ["vnt/ip_proxy", "common/ip_proxy"]
log = ["common/log"]
command = ["common/command"]
file_config = ["common/file_config"]
upnp = ["common/upnp"]
[build-dependencies]
rand = "0.8.5"
+5 -3
View File
@@ -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"]
+3
View File
@@ -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
View File
@@ -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(());
+5
View File
@@ -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::*;
+81
View File
@@ -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
// );
// }
// }
}
}