fix nat probe's bug

This commit is contained in:
asxalex 2024-12-27 00:23:30 +08:00
parent 240a3d263e
commit 63805d9a47
11 changed files with 64 additions and 32 deletions

3
.gitignore vendored
View File

@ -8,3 +8,6 @@ sdlan.exe
*.bak *.bak
*.a *.a
*.o *.o
*.tar
*.tar.gz
*.tgz

1
run.sh Normal file
View File

@ -0,0 +1 @@
LD_LIBRARY_PATH=. ./sdlan

View File

@ -15,6 +15,8 @@ async fn main() {
let cmd = CommandLineInput::from_args(); let cmd = CommandLineInput::from_args();
println!("port is {}", cmd.port);
let (tx, rx) = std::sync::mpsc::channel(); let (tx, rx) = std::sync::mpsc::channel();
let _ = run_sdlan( let _ = run_sdlan(
CommandLine { CommandLine {
@ -23,10 +25,12 @@ async fn main() {
nat_server1: "39.98.184.67:1265".to_owned(), nat_server1: "39.98.184.67:1265".to_owned(),
nat_server2: "47.98.178.3:1265".to_owned(), nat_server2: "47.98.178.3:1265".to_owned(),
_allow_routing: true, _allow_routing: true,
_drop_multicast: true,
register_ttl: 1, register_ttl: 1,
mtu: 1290, mtu: 1290,
name: "tau".to_owned(), name: "tau".to_owned(),
tos: 0, tos: 0,
local_port: cmd.port,
token: "test-token".to_owned(), token: "test-token".to_owned(),
allow_p2p: true, allow_p2p: true,
}, },

View File

@ -112,13 +112,13 @@ async fn parse_config(uuid: String, args: &CommandLine) -> Result<NodeConfig> {
let node_conf = NodeConfig { let node_conf = NodeConfig {
name: args.name.to_owned(), name: args.name.to_owned(),
allow_routing: true, allow_routing: true,
_drop_multicast: false, _drop_multicast: true,
allow_p2p: args.allow_p2p, allow_p2p: args.allow_p2p,
mtu: args.mtu, mtu: args.mtu,
_tos: 0, _tos: 0,
_register_super_interval: config::REGISTER_SUPER_INTERVAL, _register_super_interval: config::REGISTER_SUPER_INTERVAL,
register_ttl, register_ttl,
_local_port: 0, _local_port: args.local_port as u16,
node_uuid: uuid, node_uuid: uuid,
super_nodes: sockaddr, super_nodes: sockaddr,
super_node_index: AtomicU8::new(0), super_node_index: AtomicU8::new(0),

View File

@ -62,6 +62,7 @@ async fn handle_tcp_message(msg: SdlanTcp) {
let ip = ip_to_string(&dev.net_addr); let ip = ip_to_string(&dev.net_addr);
debug!("aes key is {:?}, ip is {}/{}", aes, ip, dev.net_bit_len,); debug!("aes key is {:?}, ip is {}/{}", aes, ip, dev.net_bit_len,);
println!("assigned ip: {}", ip);
edge.device_config edge.device_config
.ip .ip
.net_addr .net_addr
@ -424,9 +425,9 @@ async fn run_edge_loop(eee: &'static Node, cancel: CancellationToken) {
tokio::spawn(async move { tokio::spawn(async move {
loop_socket_v4(eee, &eee.udp_sock_v4, cancel, false).await; loop_socket_v4(eee, &eee.udp_sock_v4, cancel, false).await;
}); });
tokio::spawn(async move { if let Some(ref multicast) = eee.udp_sock_multicast {
loop_socket_v4(eee, &eee.udp_sock_multicast, cancel2, true).await; loop_socket_v4(eee, &multicast, cancel2, true).await;
}); }
} }
{ {
@ -593,7 +594,7 @@ async fn read_and_parse_tun_packet(eee: &'static Node, buf: Vec<u8>) {
} }
async fn edge_send_packet_to_net(eee: &Node, data: Vec<u8>) { async fn edge_send_packet_to_net(eee: &Node, data: Vec<u8>) {
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(); let encrypt_key = eee.get_encrypt_key();
if encrypt_key.len() == 0 { if encrypt_key.len() == 0 {

View File

@ -8,6 +8,7 @@ use std::time::Duration;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tokio::time::error::Elapsed;
use tracing::{debug, error}; use tracing::{debug, error};
use crate::pb::{ use crate::pb::{
@ -51,9 +52,15 @@ pub async fn init_edge(
// let edge_uuid = create_or_load_uuid("")?; // let edge_uuid = create_or_load_uuid("")?;
//let node_conf = parse_config(edge_uuid, &args).await?; //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 // allow multicast
// TODO: set the sn's tcp socket // TODO: set the sn's tcp socket
@ -133,7 +140,7 @@ pub struct Node {
pub known_peers: PeerMap, pub known_peers: PeerMap,
// pub tcp_sock_v4: TCPSocket, // pub tcp_sock_v4: TCPSocket,
pub udp_sock_multicast: Socket, pub udp_sock_multicast: Option<Socket>,
pub udp_sock_v4: Socket, pub udp_sock_v4: Socket,
pub outer_ip_v4: AtomicU32, pub outer_ip_v4: AtomicU32,
pub udp_sock_v6: RwLock<Option<Arc<Socket>>>, pub udp_sock_v6: RwLock<Option<Arc<Socket>>>,
@ -234,7 +241,7 @@ impl Node {
pubkey: String, pubkey: String,
config: NodeConfig, config: NodeConfig,
sock: Socket, sock: Socket,
multicast_sock: Socket, multicast_sock: Option<Socket>,
// tcpsock: TCPSocket, // tcpsock: TCPSocket,
token: &str, token: &str,
private: RsaPrivateKey, private: RsaPrivateKey,
@ -392,24 +399,22 @@ impl Node {
return NatType::Blocked; 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) { 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; *self.nat_type.lock().unwrap() = NatType::NoNat;
return 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 if let Ok(_reply3) = self
.send_and_wait_for_probe_reply(StunProbeAttr::Peer, &self.config.nat_server1) .send_and_wait_for_probe_reply(StunProbeAttr::Peer, &self.config.nat_server1)
.await .await
@ -450,6 +455,7 @@ impl Node {
attr: msgattr as u32, attr: msgattr as u32,
cookie, cookie,
}; };
println!("==> sending probe request: {:?}", probe);
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
self.cookie_match.insert(cookie, tx); self.cookie_match.insert(cookie, tx);

View File

@ -142,6 +142,7 @@ pub async fn handle_packet(eee: &'static Node, addr: SocketAddr, buf: &[u8]) ->
error!("failed to decode SdlStunReply"); error!("failed to decode SdlStunReply");
return Ok(()); return Ok(());
}; };
println!("got stun probe reply: {:?}", reply);
eee.send_nat_probe_reply(reply.cookie, reply).await; eee.send_nat_probe_reply(reply.cookie, reply).await;
} }
PacketType::StunReply => { PacketType::StunReply => {
@ -700,14 +701,16 @@ async fn register_with_new_peer(
} }
async fn register_with_local_peers(eee: &'static Node) { async fn register_with_local_peers(eee: &'static Node) {
send_register( if !eee.config._drop_multicast {
eee, send_register(
NatType::NoNat, eee,
&eee.multicast_sock, NatType::NoNat,
BROADCAST_MAC, &eee.multicast_sock,
&None, BROADCAST_MAC,
) &None,
.await; )
.await;
}
} }
async fn send_register( async fn send_register(

View File

@ -172,7 +172,7 @@ impl Iface {
#[cfg(feature = "tap")] #[cfg(feature = "tap")]
impl TunTapPacketHandler for Iface { impl TunTapPacketHandler for Iface {
async fn handle_packet_from_net(&self, data: &[u8], _: &[u8]) -> std::io::Result<()> { 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) { match self.send(data) {
Err(e) => { Err(e) => {
error!("failed to write to tap: {}", e.to_string()); error!("failed to write to tap: {}", e.to_string());

View File

@ -120,6 +120,7 @@ impl ReadWriteActor {
let _ = connecting_chan.send(ConnectionState::Connecting).await; let _ = connecting_chan.send(ConnectionState::Connecting).await;
} }
debug!("try connecting..."); debug!("try connecting...");
let Ok(mut stream) = TcpStream::connect(&self.remote).await else { let Ok(mut stream) = TcpStream::connect(&self.remote).await else {
self.connected.store(false, Ordering::Relaxed); self.connected.store(false, Ordering::Relaxed);
if keep_reconnect { if keep_reconnect {

View File

@ -4,6 +4,9 @@ use structopt::StructOpt;
pub struct CommandLineInput { pub struct CommandLineInput {
#[structopt(long = "token", default_value = "")] #[structopt(long = "token", default_value = "")]
pub token: String, pub token: String,
#[structopt(short = "p", long = "port", default_value = "0")]
pub port: u16,
} }
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
@ -25,6 +28,9 @@ pub struct CommandLine {
#[structopt(short = "r")] #[structopt(short = "r")]
pub _allow_routing: bool, pub _allow_routing: bool,
#[structopt(short = "dm")]
pub _drop_multicast: bool,
#[structopt( #[structopt(
help = "ttl of the register udp4 packet", help = "ttl of the register udp4 packet",
short = "L", short = "L",
@ -46,6 +52,9 @@ pub struct CommandLine {
#[structopt(short = "p")] #[structopt(short = "p")]
pub allow_p2p: bool, pub allow_p2p: bool,
#[structopt(short = "l")]
pub local_port: u16,
} }
impl Clone for CommandLine { impl Clone for CommandLine {
@ -54,8 +63,10 @@ impl Clone for CommandLine {
sn: self.sn.clone(), sn: self.sn.clone(),
tcp: self.tcp.clone(), tcp: self.tcp.clone(),
_allow_routing: self._allow_routing, _allow_routing: self._allow_routing,
_drop_multicast: self._drop_multicast,
register_ttl: self.register_ttl, register_ttl: self.register_ttl,
mtu: self.mtu, mtu: self.mtu,
local_port: self.local_port,
name: self.name.clone(), name: self.name.clone(),
tos: self.tos, tos: self.tos,
token: self.token.clone(), token: self.token.clone(),

2
start_docker.sh Normal file
View File

@ -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