From 63805d9a47e24b9ec0a029bbe5ac70bf784cee66 Mon Sep 17 00:00:00 2001 From: asxalex Date: Fri, 27 Dec 2024 00:23:30 +0800 Subject: [PATCH] fix nat probe's bug --- .gitignore | 3 +++ run.sh | 1 + src/bin/sdlan/main.rs | 4 ++++ src/lib.rs | 4 ++-- src/network/async_main.rs | 9 +++++---- src/network/node.rs | 40 ++++++++++++++++++++++----------------- src/network/packet.rs | 19 +++++++++++-------- src/network/tun_linux.rs | 2 +- src/tcp/tcp_conn.rs | 1 + src/utils/command.rs | 11 +++++++++++ start_docker.sh | 2 ++ 11 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 run.sh create mode 100644 start_docker.sh diff --git a/.gitignore b/.gitignore index faa8f9f..0422212 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ sdlan.exe *.bak *.a *.o +*.tar +*.tar.gz +*.tgz diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..ee6e917 --- /dev/null +++ b/run.sh @@ -0,0 +1 @@ +LD_LIBRARY_PATH=. ./sdlan \ No newline at end of file diff --git a/src/bin/sdlan/main.rs b/src/bin/sdlan/main.rs index 5674ad0..ba11294 100644 --- a/src/bin/sdlan/main.rs +++ b/src/bin/sdlan/main.rs @@ -15,6 +15,8 @@ async fn main() { let cmd = CommandLineInput::from_args(); + println!("port is {}", cmd.port); + let (tx, rx) = std::sync::mpsc::channel(); let _ = run_sdlan( CommandLine { @@ -23,10 +25,12 @@ async fn main() { nat_server1: "39.98.184.67:1265".to_owned(), nat_server2: "47.98.178.3:1265".to_owned(), _allow_routing: true, + _drop_multicast: true, register_ttl: 1, mtu: 1290, name: "tau".to_owned(), tos: 0, + local_port: cmd.port, token: "test-token".to_owned(), allow_p2p: true, }, diff --git a/src/lib.rs b/src/lib.rs index 7cac1bc..b7591dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,13 +112,13 @@ async fn parse_config(uuid: String, args: &CommandLine) -> Result { let node_conf = NodeConfig { name: args.name.to_owned(), allow_routing: true, - _drop_multicast: false, + _drop_multicast: true, allow_p2p: args.allow_p2p, mtu: args.mtu, _tos: 0, _register_super_interval: config::REGISTER_SUPER_INTERVAL, register_ttl, - _local_port: 0, + _local_port: args.local_port as u16, node_uuid: uuid, super_nodes: sockaddr, super_node_index: AtomicU8::new(0), diff --git a/src/network/async_main.rs b/src/network/async_main.rs index bdb644e..823df2d 100644 --- a/src/network/async_main.rs +++ b/src/network/async_main.rs @@ -62,6 +62,7 @@ async fn handle_tcp_message(msg: SdlanTcp) { let ip = ip_to_string(&dev.net_addr); debug!("aes key is {:?}, ip is {}/{}", aes, ip, dev.net_bit_len,); + println!("assigned ip: {}", ip); edge.device_config .ip .net_addr @@ -424,9 +425,9 @@ async fn run_edge_loop(eee: &'static Node, cancel: CancellationToken) { tokio::spawn(async move { loop_socket_v4(eee, &eee.udp_sock_v4, cancel, false).await; }); - tokio::spawn(async move { - loop_socket_v4(eee, &eee.udp_sock_multicast, cancel2, true).await; - }); + if let Some(ref multicast) = eee.udp_sock_multicast { + loop_socket_v4(eee, &multicast, cancel2, true).await; + } } { @@ -593,7 +594,7 @@ async fn read_and_parse_tun_packet(eee: &'static Node, buf: Vec) { } async fn edge_send_packet_to_net(eee: &Node, data: Vec) { - debug!("edge send packet to net({} bytes): {:?}", data.len(), data); + // debug!("edge send packet to net({} bytes): {:?}", data.len(), data); let encrypt_key = eee.get_encrypt_key(); if encrypt_key.len() == 0 { diff --git a/src/network/node.rs b/src/network/node.rs index a2a236d..e8fbdf8 100644 --- a/src/network/node.rs +++ b/src/network/node.rs @@ -8,6 +8,7 @@ use std::time::Duration; use tokio::io::AsyncReadExt; use tokio::sync::mpsc::Sender; use tokio::sync::oneshot; +use tokio::time::error::Elapsed; use tracing::{debug, error}; use crate::pb::{ @@ -51,9 +52,15 @@ pub async fn init_edge( // let edge_uuid = create_or_load_uuid("")?; //let node_conf = parse_config(edge_uuid, &args).await?; - let sock_v4 = Socket::build(0, true, false, tos).await?; + let Ok(sock_v4) = Socket::build(node_conf._local_port, true, false, tos).await else { + panic!("failed to build sock for sock v4"); + }; - let sock_multicast = Socket::build(MULTICAST_PORT, true, true, 0).await?; + let mut sock_multicast = None; + if !node_conf._drop_multicast { + sock_multicast = Some(Socket::build(MULTICAST_PORT, true, true, 0).await?); + } + // let sock_multicast = Socket::build(MULTICAST_PORT, true, true, 0).await?; // allow multicast // TODO: set the sn's tcp socket @@ -133,7 +140,7 @@ pub struct Node { pub known_peers: PeerMap, // pub tcp_sock_v4: TCPSocket, - pub udp_sock_multicast: Socket, + pub udp_sock_multicast: Option, pub udp_sock_v4: Socket, pub outer_ip_v4: AtomicU32, pub udp_sock_v6: RwLock>>, @@ -234,7 +241,7 @@ impl Node { pubkey: String, config: NodeConfig, sock: Socket, - multicast_sock: Socket, + multicast_sock: Option, // tcpsock: TCPSocket, token: &str, private: RsaPrivateKey, @@ -392,24 +399,22 @@ impl Node { return NatType::Blocked; }; - let Ok(reply2) = self - .send_and_wait_for_probe_reply(StunProbeAttr::None, &self.config.nat_server2) - .await - else { - *self.nat_type.lock().unwrap() = NatType::Blocked; - return NatType::Blocked; - }; - if reply1.ip == self.outer_ip_v4.load(Ordering::Relaxed) { + let Ok(reply2) = self + .send_and_wait_for_probe_reply(StunProbeAttr::None, &self.config.nat_server2) + .await + else { + *self.nat_type.lock().unwrap() = NatType::Blocked; + return NatType::Blocked; + }; + if reply1.ip != reply2.ip || reply1.port != reply2.port { + *self.nat_type.lock().unwrap() = NatType::Symmetric; + return NatType::Symmetric; + } *self.nat_type.lock().unwrap() = NatType::NoNat; return NatType::NoNat; } - if reply1.ip != reply2.ip || reply1.port != reply2.port { - *self.nat_type.lock().unwrap() = NatType::Symmetric; - return NatType::Symmetric; - } - if let Ok(_reply3) = self .send_and_wait_for_probe_reply(StunProbeAttr::Peer, &self.config.nat_server1) .await @@ -450,6 +455,7 @@ impl Node { attr: msgattr as u32, cookie, }; + println!("==> sending probe request: {:?}", probe); let (tx, rx) = oneshot::channel(); self.cookie_match.insert(cookie, tx); diff --git a/src/network/packet.rs b/src/network/packet.rs index ef79fec..fa32965 100644 --- a/src/network/packet.rs +++ b/src/network/packet.rs @@ -142,6 +142,7 @@ pub async fn handle_packet(eee: &'static Node, addr: SocketAddr, buf: &[u8]) -> error!("failed to decode SdlStunReply"); return Ok(()); }; + println!("got stun probe reply: {:?}", reply); eee.send_nat_probe_reply(reply.cookie, reply).await; } PacketType::StunReply => { @@ -700,14 +701,16 @@ async fn register_with_new_peer( } async fn register_with_local_peers(eee: &'static Node) { - send_register( - eee, - NatType::NoNat, - &eee.multicast_sock, - BROADCAST_MAC, - &None, - ) - .await; + if !eee.config._drop_multicast { + send_register( + eee, + NatType::NoNat, + &eee.multicast_sock, + BROADCAST_MAC, + &None, + ) + .await; + } } async fn send_register( diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index c4947a5..98e2c22 100644 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -172,7 +172,7 @@ impl Iface { #[cfg(feature = "tap")] impl TunTapPacketHandler for Iface { async fn handle_packet_from_net(&self, data: &[u8], _: &[u8]) -> std::io::Result<()> { - debug!("in tap mode, got data: {:?}", data); + // debug!("in tap mode, got data: {:?}", data); match self.send(data) { Err(e) => { error!("failed to write to tap: {}", e.to_string()); diff --git a/src/tcp/tcp_conn.rs b/src/tcp/tcp_conn.rs index 826e92c..f63135e 100644 --- a/src/tcp/tcp_conn.rs +++ b/src/tcp/tcp_conn.rs @@ -120,6 +120,7 @@ impl ReadWriteActor { let _ = connecting_chan.send(ConnectionState::Connecting).await; } debug!("try connecting..."); + let Ok(mut stream) = TcpStream::connect(&self.remote).await else { self.connected.store(false, Ordering::Relaxed); if keep_reconnect { diff --git a/src/utils/command.rs b/src/utils/command.rs index 215b4e3..5521eb4 100644 --- a/src/utils/command.rs +++ b/src/utils/command.rs @@ -4,6 +4,9 @@ use structopt::StructOpt; pub struct CommandLineInput { #[structopt(long = "token", default_value = "")] pub token: String, + + #[structopt(short = "p", long = "port", default_value = "0")] + pub port: u16, } #[derive(StructOpt, Debug)] @@ -25,6 +28,9 @@ pub struct CommandLine { #[structopt(short = "r")] pub _allow_routing: bool, + #[structopt(short = "dm")] + pub _drop_multicast: bool, + #[structopt( help = "ttl of the register udp4 packet", short = "L", @@ -46,6 +52,9 @@ pub struct CommandLine { #[structopt(short = "p")] pub allow_p2p: bool, + + #[structopt(short = "l")] + pub local_port: u16, } impl Clone for CommandLine { @@ -54,8 +63,10 @@ impl Clone for CommandLine { sn: self.sn.clone(), tcp: self.tcp.clone(), _allow_routing: self._allow_routing, + _drop_multicast: self._drop_multicast, register_ttl: self.register_ttl, mtu: self.mtu, + local_port: self.local_port, name: self.name.clone(), tos: self.tos, token: self.token.clone(), diff --git a/start_docker.sh b/start_docker.sh new file mode 100644 index 0000000..44be6d5 --- /dev/null +++ b/start_docker.sh @@ -0,0 +1,2 @@ +## pull image: docker pull ubuntu +docker run -v .:/root/punchnet -it --device=/dev/net/tun --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -w /root/punchnet ubuntu \ No newline at end of file