fix wireguard listener (#1382)

* listen both v4 and v6 for wireguard portal
* fix panic when getting udp local addr

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Sijie.Sun
2025-09-17 23:45:05 +08:00
committed by GitHub
parent 215db09925
commit 56fd6e4ab6
7 changed files with 52 additions and 16 deletions
@@ -212,6 +212,7 @@ event:
ConnectionError: 连接错误 ConnectionError: 连接错误
Connecting: 正在连接 Connecting: 正在连接
ConnectError: 连接错误 ConnectError: 连接错误
VpnPortalStarted: VPN门户已启动
VpnPortalClientConnected: VPN门户客户端已连接 VpnPortalClientConnected: VPN门户客户端已连接
VpnPortalClientDisconnected: VPN门户客户端已断开连接 VpnPortalClientDisconnected: VPN门户客户端已断开连接
DhcpIpv4Changed: DHCP IPv4地址更改 DhcpIpv4Changed: DHCP IPv4地址更改
@@ -212,6 +212,7 @@ event:
ConnectionError: ConnectionError ConnectionError: ConnectionError
Connecting: Connecting Connecting: Connecting
ConnectError: ConnectError ConnectError: ConnectError
VpnPortalStarted: VpnPortalStarted
VpnPortalClientConnected: VpnPortalClientConnected VpnPortalClientConnected: VpnPortalClientConnected
VpnPortalClientDisconnected: VpnPortalClientDisconnected VpnPortalClientDisconnected: VpnPortalClientDisconnected
DhcpIpv4Changed: DhcpIpv4Changed DhcpIpv4Changed: DhcpIpv4Changed
@@ -306,6 +306,7 @@ export enum EventType {
Connecting = 'Connecting', // any Connecting = 'Connecting', // any
ConnectError = 'ConnectError', // string, string, string ConnectError = 'ConnectError', // string, string, string
VpnPortalStarted = 'VpnPortalStarted', // string
VpnPortalClientConnected = 'VpnPortalClientConnected', // string, string VpnPortalClientConnected = 'VpnPortalClientConnected', // string, string
VpnPortalClientDisconnected = 'VpnPortalClientDisconnected', // string, string, string VpnPortalClientDisconnected = 'VpnPortalClientDisconnected', // string, string, string
+1
View File
@@ -44,6 +44,7 @@ pub enum GlobalCtxEvent {
Connecting(url::Url), Connecting(url::Url),
ConnectError(String, String, String), // (dst, ip version, error message) ConnectError(String, String, String), // (dst, ip version, error message)
VpnPortalStarted(String), // (portal)
VpnPortalClientConnected(String, String), // (portal, client ip) VpnPortalClientConnected(String, String), // (portal, client ip)
VpnPortalClientDisconnected(String, String), // (portal, client ip) VpnPortalClientDisconnected(String, String), // (portal, client ip)
+7
View File
@@ -270,6 +270,13 @@ fn handle_event(
); );
} }
GlobalCtxEvent::VpnPortalStarted(portal) => {
print_event(
instance_id,
format!("vpn portal started. portal: {}", portal),
);
}
GlobalCtxEvent::VpnPortalClientConnected(portal, client_addr) => { GlobalCtxEvent::VpnPortalClientConnected(portal, client_addr) => {
print_event( print_event(
instance_id, instance_id,
+4 -1
View File
@@ -629,7 +629,10 @@ impl WgTunnelConnector {
addr: SocketAddr, addr: SocketAddr,
) -> Result<Box<dyn super::Tunnel>, super::TunnelError> { ) -> Result<Box<dyn super::Tunnel>, super::TunnelError> {
tracing::warn!("wg connect: {:?}", addr); tracing::warn!("wg connect: {:?}", addr);
let local_addr = udp.local_addr().unwrap().to_string(); let local_addr = udp
.local_addr()
.with_context(|| "Failed to get local addr")?
.to_string();
let mut wg_peer = WgPeer::new(Arc::new(udp), config.clone(), addr); let mut wg_peer = WgPeer::new(Arc::new(udp), config.clone(), addr);
let udp = wg_peer.udp_socket(); let udp = wg_peer.udp_socket();
+36 -14
View File
@@ -1,5 +1,5 @@
use std::{ use std::{
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6},
sync::Arc, sync::Arc,
}; };
@@ -49,7 +49,7 @@ struct WireGuardImpl {
global_ctx: ArcGlobalCtx, global_ctx: ArcGlobalCtx,
peer_mgr: Arc<PeerManager>, peer_mgr: Arc<PeerManager>,
wg_config: WgConfig, wg_config: WgConfig,
listenr_addr: SocketAddr, listener_addr: SocketAddr,
wg_peer_ip_table: WgPeerIpTable, wg_peer_ip_table: WgPeerIpTable,
@@ -62,13 +62,13 @@ impl WireGuardImpl {
let wg_config = get_wg_config_for_portal(&nid); let wg_config = get_wg_config_for_portal(&nid);
let vpn_cfg = global_ctx.config.get_vpn_portal_config().unwrap(); let vpn_cfg = global_ctx.config.get_vpn_portal_config().unwrap();
let listenr_addr = vpn_cfg.wireguard_listen; let listener_addr = vpn_cfg.wireguard_listen;
Self { Self {
global_ctx, global_ctx,
peer_mgr, peer_mgr,
wg_config, wg_config,
listenr_addr, listener_addr,
wg_peer_ip_table: Arc::new(DashMap::new()), wg_peer_ip_table: Arc::new(DashMap::new()),
tasks: Arc::new(std::sync::Mutex::new(JoinSet::new())), tasks: Arc::new(std::sync::Mutex::new(JoinSet::new())),
} }
@@ -209,12 +209,11 @@ impl WireGuardImpl {
.await; .await;
} }
#[tracing::instrument(skip(self), err(level = Level::WARN))] async fn start_listener(&self, listener_addr: &SocketAddr) -> anyhow::Result<()> {
async fn start(&self) -> anyhow::Result<()> { let mut listener_url = url::Url::parse("wg://0.0.0.0:0").unwrap();
let mut l = WgTunnelListener::new( listener_url.set_port(Some(listener_addr.port())).unwrap();
format!("wg://{}", self.listenr_addr).parse().unwrap(), listener_url.set_ip_host(listener_addr.ip()).unwrap();
self.wg_config.clone(), let mut l = WgTunnelListener::new(listener_url.clone(), self.wg_config.clone());
);
tracing::info!("Wireguard VPN Portal Starting"); tracing::info!("Wireguard VPN Portal Starting");
@@ -224,9 +223,6 @@ impl WireGuardImpl {
.await .await
.with_context(|| "Failed to start wireguard listener for vpn portal")?; .with_context(|| "Failed to start wireguard listener for vpn portal")?;
} }
join_joinset_background(self.tasks.clone(), "wireguard".to_string());
let tasks = Arc::downgrade(&self.tasks.clone()); let tasks = Arc::downgrade(&self.tasks.clone());
let peer_mgr = self.peer_mgr.clone(); let peer_mgr = self.peer_mgr.clone();
let wg_peer_ip_table = self.wg_peer_ip_table.clone(); let wg_peer_ip_table = self.wg_peer_ip_table.clone();
@@ -243,6 +239,32 @@ impl WireGuardImpl {
} }
}); });
self.global_ctx
.issue_event(GlobalCtxEvent::VpnPortalStarted(listener_url.to_string()));
Ok(())
}
#[tracing::instrument(skip(self), err(level = Level::WARN))]
async fn start(&self) -> anyhow::Result<()> {
tracing::info!("Wireguard VPN Portal Starting");
self.start_listener(&self.listener_addr).await?;
// if binding to v4 unspecified, also start a listener on v6 unspecified
if let SocketAddr::V4(v4) = &self.listener_addr {
if v4.ip().is_unspecified() {
let _ = self
.start_listener(&SocketAddr::V6(SocketAddrV6::new(
Ipv6Addr::UNSPECIFIED,
v4.port(),
0,
0,
)))
.await;
}
};
join_joinset_background(self.tasks.clone(), "wireguard".to_string());
self.start_pipeline_processor().await; self.start_pipeline_processor().await;
Ok(()) Ok(())
@@ -324,7 +346,7 @@ PersistentKeepalive = 25
"#, "#,
peer_secret_key = BASE64_STANDARD.encode(cfg.peer_secret_key()), peer_secret_key = BASE64_STANDARD.encode(cfg.peer_secret_key()),
my_public_key = BASE64_STANDARD.encode(cfg.my_public_key()), my_public_key = BASE64_STANDARD.encode(cfg.my_public_key()),
listenr_addr = self.inner.as_ref().unwrap().listenr_addr, listenr_addr = self.inner.as_ref().unwrap().listener_addr,
allow_ips = allow_ips, allow_ips = allow_ips,
address = client_cidr.first_address().to_string() + "/32", address = client_cidr.first_address().to_string() + "/32",
); );