v6 hole punch (#873)

Some devices have ipv6 but don't allow input connection, this patch add hole punching for these devices.

- **add v6 hole punch msg to udp tunnel**
- **send hole punch packet when do ipv6 direct connect**
This commit is contained in:
Sijie.Sun
2025-05-24 22:57:33 +08:00
committed by GitHub
parent fc397c35c5
commit 29994b663a
15 changed files with 499 additions and 198 deletions

View File

@@ -389,6 +389,15 @@ impl PeerManager {
});
}
pub async fn add_direct_tunnel(
&self,
t: Box<dyn Tunnel>,
) -> Result<(PeerId, PeerConnId), Error> {
let (peer_id, conn_id) = self.add_client_tunnel(t).await?;
self.add_directly_connected_conn(peer_id, conn_id);
Ok((peer_id, conn_id))
}
#[tracing::instrument]
pub async fn try_direct_connect<C>(
&self,
@@ -401,9 +410,7 @@ impl PeerManager {
let t = ns
.run_async(|| async move { connector.connect().await })
.await?;
let (peer_id, conn_id) = self.add_client_tunnel(t).await?;
self.add_directly_connected_conn(peer_id, conn_id);
Ok((peer_id, conn_id))
self.add_direct_tunnel(t).await
}
#[tracing::instrument]

View File

@@ -1,9 +1,15 @@
use std::net::SocketAddr;
use crate::{
common::global_ctx::ArcGlobalCtx,
proto::{
peer_rpc::{DirectConnectorRpc, GetIpListRequest, GetIpListResponse},
common::Void,
peer_rpc::{
DirectConnectorRpc, GetIpListRequest, GetIpListResponse, SendV6HolePunchPacketRequest,
},
rpc_types::{self, controller::BaseController},
},
tunnel::udp,
};
#[derive(Clone)]
@@ -30,8 +36,42 @@ impl DirectConnectorRpc for DirectConnectorManagerRpcServer {
.chain(self.global_ctx.get_running_listeners().into_iter())
.map(Into::into)
.collect();
tracing::trace!(
"get_ip_list: public_ipv4: {:?}, public_ipv6: {:?}, listeners: {:?}",
ret.public_ipv4,
ret.public_ipv6,
ret.listeners
);
Ok(ret)
}
async fn send_v6_hole_punch_packet(
&self,
_: BaseController,
req: SendV6HolePunchPacketRequest,
) -> rpc_types::error::Result<Void> {
let listener_port = req.listener_port as u16;
let SocketAddr::V6(connector_addr) = req
.connector_addr
.ok_or(anyhow::anyhow!("connector_addr is required"))?
.into()
else {
return Err(anyhow::anyhow!("connector_addr is not a v6 address").into());
};
tracing::info!(
"Sending v6 hole punch packet to {} from listener port {}",
connector_addr,
listener_port
);
// send 3 packets to the connector
for _ in 0..3 {
udp::send_v6_hole_punch_packet(listener_port, connector_addr).await?;
tokio::time::sleep(std::time::Duration::from_millis(30)).await;
}
Ok(Default::default())
}
}
impl DirectConnectorManagerRpcServer {