Skip to content

Commit

Permalink
支持stun协议
Browse files Browse the repository at this point in the history
  • Loading branch information
vnt-dev committed Aug 3, 2023
1 parent c5398a5 commit d1bde29
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 202 deletions.
62 changes: 43 additions & 19 deletions vnt-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,27 @@ async fn main0() {
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.optopt("k", "", &format!("{}", green("必选,使用相同的token,就能组建一个局域网络".to_string())), "<token>");
opts.optopt("n", "", "给设备一个名字,默认使用系统版本", "<name>");
opts.optopt("k", "", "必选,使用相同的token,就能组建一个局域网络", "<token>");
opts.optopt("n", "", "给设备一个名字,便于区分不同设备,默认使用系统版本", "<name>");
opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip", "<id>");
opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入");
opts.optopt("s", "", "注册和中继服务器地址", "<server>");
opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", "<addr1,addr2>");
opts.optmulti("e", "", "stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2", "<stun-server>");
opts.optflag("a", "", "使用tap模式,默认使用tun模式");
opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3 \n表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3", "<in-ip>");
opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24 \n表示允许将数据转发到192.168.0.0/24", "<out-ip>");
opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3 \n表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3,可指定多个网段", "<in-ip>");
opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24 \n表示允许将数据转发到192.168.0.0/24,可指定多个网段", "<out-ip>");
opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "<password>");
opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
opts.optopt("u", "", "自定义mtu(默认为1430)", "<mtu>");
opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低");
opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", "<IP>");
opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
//"后台运行时,查看其他设备列表"
opts.optflag("", "list", &format!("{}", yellow("后台运行时,查看其他设备列表".to_string())));
opts.optflag("", "all", &format!("{}", yellow("后台运行时,查看其他设备完整信息".to_string())));
opts.optflag("", "info", &format!("{}", yellow("后台运行时,查看当前设备信息".to_string())));
opts.optflag("", "route", &format!("{}", yellow("后台运行时,查看数据转发路径".to_string())));
opts.optflag("", "stop", &format!("{}", yellow("停止后台运行".to_string())));
opts.optflag("", "list", "后台运行时,查看其他设备列表");
opts.optflag("", "all", "后台运行时,查看其他设备完整信息");
opts.optflag("", "info", "后台运行时,查看当前设备信息");
opts.optflag("", "route", "后台运行时,查看数据转发路径");
opts.optflag("", "stop", "停止后台运行");
opts.optflag("h", "help", "帮助");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Expand Down Expand Up @@ -132,11 +132,12 @@ async fn main0() {
return;
}
};
let nat_test_server = matches.opt_get_default("e",
"nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string()).unwrap();

let nat_test_server = nat_test_server.split(",").flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>();
let mut stun_server = matches.opt_strs("e");
if stun_server.is_empty() {
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.qq.com:3478".to_string());
}

let in_ip = matches.opt_strs("i");
let in_ip = match ips_parse(&in_ip) {
Expand Down Expand Up @@ -192,7 +193,7 @@ async fn main0() {
let config = Config::new(tap,
token, device_id, name,
server_address, server_address_str,
nat_test_server, in_ip,
stun_server, in_ip,
out_ip, password, simulate_multicast, mtu, tcp_channel, virtual_ip, relay);
let mut vnt_util = VntUtil::new(config).await.unwrap();
let response = loop {
Expand Down Expand Up @@ -309,10 +310,33 @@ async fn main0() {
vnt.wait_stop().await;
}

fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} [options]", program);
fn print_usage(program: &str, _opts: Options) {
println!("Usage: {} [options]", program);
println!("version:1.1.2");
println!("{}", opts.usage(&brief));
println!("Options:");
println!(" -k <token> {}", green("必选,使用相同的token,就能组建一个局域网络".to_string()));
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip");
println!(" -c 关闭交互式命令,使用此参数禁用控制台输入");
println!(" -s <server> 注册和中继服务器地址");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
println!(" -a 使用tap模式,默认使用tun模式");
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
println!(" 并转发到10.26.0.3,可指定多个网段");
println!(" -o <out-ip> 配置点对网时使用,-o 192.168.0.0/24表示允许将数据转发到192.168.0.0/24,可指定多个网段");
println!(" -w <password> 使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信");
println!(" -m 模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
println!(" -u <mtu> 自定义mtu(默认为1430)");
println!(" --tcp 和服务端使用tcp通信,默认使用udp,遇到udp qos时可指定使用tcp");
println!(" --ip <IP> 指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配");
println!(" --relay 仅使用服务器转发,不使用p2p,默认情况允许使用p2p");
println!();
println!(" --list {}",yellow("后台运行时,查看其他设备列表".to_string()));
println!(" --all {}",yellow("后台运行时,查看其他设备完整信息".to_string()));
println!(" --info {}",yellow("后台运行时,查看当前设备信息".to_string()));
println!(" --route {}",yellow("后台运行时,查看数据转发路径".to_string()));
println!(" --stop {}",yellow("停止后台运行".to_string()));
println!(" -h, --help 帮助");
}

fn green(str: String) -> impl std::fmt::Display {
Expand Down
10 changes: 6 additions & 4 deletions vnt-jni/src/vnt_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
let device_id = to_string_not_null(env, &config, "deviceId")?;
let password = to_string(env, &config, "password")?;
let server_address_str = to_string_not_null(env, &config, "server")?;
let nat_test_server = to_string_not_null(env, &config, "natTestServer")?;
// let nat_test_server = to_string_not_null(env, &config, "natTestServer")?;
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut rs) => {
if let Some(addr) = rs.next() {
Expand All @@ -72,12 +72,14 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
return Err(Error::JavaException);
}
};
let nat_test_server = nat_test_server.split(",").flat_map(|a| a.trim().to_socket_addrs()).flatten()
.collect::<Vec<_>>();
let mut stun_server = Vec::new();
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.qq.com:3478".to_string());
let config = Config::new(false,
token, device_id, name,
server_address, server_address_str,
nat_test_server, vec![],
stun_server, vec![],
vec![], password, false, None, false, None, false);
match VntUtilSync::new(config) {
Ok(vnt_util) => {
Expand Down
2 changes: 2 additions & 0 deletions vnt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ socket2 ={ version = "0.5.2", features = ["all"] }
tokio = { version = "1.28.1", features = ["full"] }
aes-gcm = {version="0.10.2", optional = true}
ring = {version="0.16.20", optional = true}
stun-format = {version="1.0.1",features=["fmt","rfc3489"]}

[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
tun = { path = "./rust-tun" }

Expand Down
17 changes: 11 additions & 6 deletions vnt/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,16 +181,16 @@ impl VntUtil {
let local_ip = crate::nat::local_ip()?;
let local_port = context.main_local_port()?;
// NAT检测
let nat_test = NatTest::new(config.nat_test_server.clone(), response.public_ip, response.public_port, local_ip, local_port);
let nat_test = NatTest::new(config.stun_server.clone(), response.public_ip, response.public_port, local_ip, local_port).await;
let in_external_route = if config.in_ips.is_empty() {
None
} else {
Some(ExternalRoute::new(config.in_ips))
};
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
let (tcp_proxy, udp_proxy, ip_proxy_map) = if config.out_ips.is_empty() {
(None, None, None)
} else {
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), current_device.clone()).await?;
let (tcp_proxy, udp_proxy, ip_proxy_map) = crate::ip_proxy::init_proxy(channel_sender.clone(), current_device.clone()).await?;
(Some(tcp_proxy), Some(udp_proxy), Some(ip_proxy_map))
};
let out_external_route = AllowExternalRoute::new(config.out_ips);
Expand Down Expand Up @@ -335,7 +335,7 @@ pub struct Config {
pub name: String,
pub server_address: SocketAddr,
pub server_address_str: String,
pub nat_test_server: Vec<SocketAddr>,
pub stun_server: Vec<String>,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32)>,
pub password: Option<String>,
Expand All @@ -353,19 +353,24 @@ impl Config {
name: String,
server_address: SocketAddr,
server_address_str: String,
nat_test_server: Vec<SocketAddr>,
mut stun_server: Vec<String>,
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32)>,
password: Option<String>, simulate_multicast: bool, mtu: Option<u16>, tcp: bool,
ip: Option<Ipv4Addr>,
relay: bool, ) -> Self {
for x in stun_server.iter_mut() {
if !x.contains(":") {
x.push_str(":3478");
}
}
Self {
tap,
token,
device_id,
name,
server_address,
server_address_str,
nat_test_server,
stun_server,
in_ips,
out_ips,
password,
Expand Down
2 changes: 1 addition & 1 deletion vnt/src/handle/recv_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ impl ChannelDataHandler {
let local_port = context.main_local_port()?;
let local_ip = nat::local_ip()?;
let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip),
response.public_port as u16, local_ip, local_port);
response.public_port as u16, local_ip, local_port).await;
context.switch(nat_info.nat_type);
let new_ip = Ipv4Addr::from(response.virtual_ip);
let current_ip = current_device.virtual_ip();
Expand Down
155 changes: 0 additions & 155 deletions vnt/src/nat/check.rs

This file was deleted.

Loading

0 comments on commit d1bde29

Please sign in to comment.