refactor: vpn

This commit is contained in:
zhom
2026-04-11 23:37:05 +04:00
parent c62ac6288e
commit 258ea047b6
7 changed files with 183 additions and 116 deletions
+7 -14
View File
@@ -716,29 +716,22 @@ impl SyncScheduler {
match entity_type.as_str() {
"profile" => {
let profile_manager = ProfileManager::instance();
let profile_to_delete = {
let has_profile = {
if let Ok(profiles) = profile_manager.list_profiles() {
let profile_uuid = uuid::Uuid::parse_str(&entity_id).ok();
profile_uuid.and_then(|uuid| profiles.into_iter().find(|p| p.id == uuid))
profile_uuid.is_some_and(|uuid| profiles.iter().any(|p| p.id == uuid))
} else {
None
false
}
};
if let Some(mut profile) = profile_to_delete {
if has_profile {
log::info!(
"Profile {} was deleted remotely, disabling sync locally",
"Profile {} was deleted remotely, deleting locally",
entity_id
);
profile.sync_mode = crate::profile::types::SyncMode::Disabled;
if let Err(e) = profile_manager.save_profile(&profile) {
log::warn!("Failed to disable sync for profile {}: {}", entity_id, e);
} else {
log::info!(
"Profile {} sync disabled due to remote tombstone (local copy kept)",
entity_id
);
let _ = events::emit("profiles-changed", ());
if let Err(e) = profile_manager.delete_profile_local_only(&entity_id) {
log::warn!("Failed to delete tombstoned profile {}: {}", entity_id, e);
}
}
}
+63 -44
View File
@@ -240,58 +240,77 @@ impl WireGuardSocks5Server {
socket: &UdpSocket,
peer_addr: SocketAddr,
) -> Result<(), VpnError> {
let mut dst = vec![0u8; 2048];
let result = tunn.format_handshake_initiation(&mut dst, false);
match result {
TunnResult::WriteToNetwork(packet) => {
socket
.send_to(packet, peer_addr)
.map_err(|e| VpnError::Connection(format!("Failed to send handshake: {e}")))?;
}
TunnResult::Err(e) => {
return Err(VpnError::Tunnel(format!(
"Handshake initiation failed: {e:?}"
)));
}
_ => {}
}
socket
.set_read_timeout(Some(std::time::Duration::from_secs(10)))
.set_read_timeout(Some(std::time::Duration::from_secs(5)))
.map_err(|e| VpnError::Connection(format!("Failed to set timeout: {e}")))?;
let mut recv_buf = vec![0u8; 2048];
match socket.recv_from(&mut recv_buf) {
Ok((len, _)) => {
let result = tunn.decapsulate(None, &recv_buf[..len], &mut dst);
match result {
TunnResult::WriteToNetwork(response) => {
socket
.send_to(response, peer_addr)
.map_err(|e| VpnError::Connection(format!("Failed to send response: {e}")))?;
}
TunnResult::Done => {}
TunnResult::Err(e) => {
return Err(VpnError::Tunnel(format!(
"Handshake response failed: {e:?}"
)));
}
_ => {}
// WireGuard handshakes use UDP which can silently lose packets, especially
// through Docker port-forwarding layers. Retry the handshake initiation up
// to 5 times (25s total) before giving up — the protocol is designed for
// retransmission and peers handle duplicate initiations correctly.
let max_attempts = 5;
let mut last_error = String::from("no handshake attempt completed");
for attempt in 1..=max_attempts {
let mut dst = vec![0u8; 2048];
let result = tunn.format_handshake_initiation(&mut dst, false);
match result {
TunnResult::WriteToNetwork(packet) => {
socket
.send_to(packet, peer_addr)
.map_err(|e| VpnError::Connection(format!("Failed to send handshake: {e}")))?;
}
TunnResult::Err(e) => {
return Err(VpnError::Tunnel(format!(
"Handshake initiation failed: {e:?}"
)));
}
_ => {}
}
Err(e) => {
return Err(VpnError::Connection(format!(
"Handshake timeout or error: {e}"
)));
let mut recv_buf = vec![0u8; 2048];
match socket.recv_from(&mut recv_buf) {
Ok((len, _)) => {
let result = tunn.decapsulate(None, &recv_buf[..len], &mut dst);
match result {
TunnResult::WriteToNetwork(response) => {
socket
.send_to(response, peer_addr)
.map_err(|e| VpnError::Connection(format!("Failed to send response: {e}")))?;
}
TunnResult::Done => {}
TunnResult::Err(e) => {
last_error = format!("handshake response error: {e:?}");
log::warn!(
"[vpn-worker] Handshake attempt {attempt}/{max_attempts} failed: {last_error}"
);
continue;
}
_ => {}
}
socket
.set_read_timeout(None)
.map_err(|e| VpnError::Connection(format!("Failed to clear timeout: {e}")))?;
return Ok(());
}
Err(e) if attempt < max_attempts => {
log::warn!(
"[vpn-worker] Handshake attempt {attempt}/{max_attempts} timed out: {e}, retrying"
);
last_error = format!("timeout: {e}");
continue;
}
Err(e) => {
last_error = format!("timeout: {e}");
}
}
}
socket
.set_read_timeout(None)
.map_err(|e| VpnError::Connection(format!("Failed to clear timeout: {e}")))?;
Ok(())
Err(VpnError::Connection(format!(
"Handshake failed after {max_attempts} attempts: {last_error}"
)))
}
pub async fn run(self, config_id: String) -> Result<(), VpnError> {
+1 -1
View File
@@ -7,7 +7,7 @@ use crate::vpn_worker_storage::{
use std::process::Stdio;
const VPN_WORKER_POLL_INTERVAL_MS: u64 = 100;
const VPN_WORKER_STARTUP_TIMEOUT_MS: u64 = 10_000;
const VPN_WORKER_STARTUP_TIMEOUT_MS: u64 = 30_000;
const OPENVPN_WORKER_STARTUP_TIMEOUT_MS: u64 = 100_000;
async fn vpn_worker_accepting_connections(config: &VpnWorkerConfig) -> bool {