From 214b18f65ff0c019e01f351e09354696027fadae Mon Sep 17 00:00:00 2001 From: NickVs2015 Date: Tue, 31 Mar 2026 14:08:04 +0300 Subject: [PATCH] fix: improve reeconnection --- client/mozilla/localsocketcontroller.cpp | 2 +- .../platforms/linux/daemon/linuxfirewall.cpp | 2 +- .../linux/daemon/linuxroutemonitor.cpp | 7 +++++- .../linux/daemon/wireguardutilslinux.cpp | 22 ++++++++----------- .../linux/linuxnetworkwatcherworker.cpp | 7 +++++- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/client/mozilla/localsocketcontroller.cpp b/client/mozilla/localsocketcontroller.cpp index 17bf5a5e9..ddb868869 100644 --- a/client/mozilla/localsocketcontroller.cpp +++ b/client/mozilla/localsocketcontroller.cpp @@ -27,7 +27,7 @@ #include "protocols/protocols_defs.h" // How many times do we try to reconnect. -constexpr int MAX_CONNECTION_RETRY = 10; +constexpr int MAX_CONNECTION_RETRY = 70; // How long do we wait between one try and the next one. constexpr int CONNECTION_RETRY_TIMER_MSEC = 500; diff --git a/client/platforms/linux/daemon/linuxfirewall.cpp b/client/platforms/linux/daemon/linuxfirewall.cpp index 971008c38..3ed029c58 100644 --- a/client/platforms/linux/daemon/linuxfirewall.cpp +++ b/client/platforms/linux/daemon/linuxfirewall.cpp @@ -378,7 +378,7 @@ void LinuxFirewall::uninstall() bool LinuxFirewall::isInstalled() { - return execute(QStringLiteral("iptables -C %1 -j %2 2> /dev/null").arg(kOutputChain, kRootChain)) == 0; + return execute(QStringLiteral("iptables -C %1 -j %2 2> /dev/null").arg(kOutputChain, kRootChain), true) == 0; } void LinuxFirewall::enableAnchor(LinuxFirewall::IPVersion ip, const QString &anchor, const QString& tableName) diff --git a/client/platforms/linux/daemon/linuxroutemonitor.cpp b/client/platforms/linux/daemon/linuxroutemonitor.cpp index 39926f232..eaf5bcd85 100644 --- a/client/platforms/linux/daemon/linuxroutemonitor.cpp +++ b/client/platforms/linux/daemon/linuxroutemonitor.cpp @@ -164,8 +164,13 @@ bool LinuxRouteMonitor::rtmSendRoute(int action, int flags, int type, } if (rtm->rtm_type == RTN_THROW) { + QString gateway = NetworkUtilities::getGatewayAndIface().first; + if (gateway.isEmpty()) { + logger.warning() << "No default gateway available, skipping exclusion route"; + return false; + } struct in_addr ip4; - inet_pton(AF_INET, NetworkUtilities::getGatewayAndIface().first.toUtf8(), &ip4); + inet_pton(AF_INET, gateway.toUtf8(), &ip4); nlmsg_append_attr(nlmsg, sizeof(buf), RTA_GATEWAY, &ip4, sizeof(ip4)); nlmsg_append_attr32(nlmsg, sizeof(buf), RTA_PRIORITY, 0); rtm->rtm_type = RTN_UNICAST; diff --git a/client/platforms/linux/daemon/wireguardutilslinux.cpp b/client/platforms/linux/daemon/wireguardutilslinux.cpp index 1856cbcfb..098c8ba29 100644 --- a/client/platforms/linux/daemon/wireguardutilslinux.cpp +++ b/client/platforms/linux/daemon/wireguardutilslinux.cpp @@ -65,18 +65,10 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) { return false; } - // Kill any orphaned wireguard-go process from a previous crash that may - // still hold the amn0 TUN device, then delete the stale interface. - QProcess::execute("pkill", {"-f", QString("wireguard-go.*%1").arg(WG_INTERFACE)}); - QProcess::execute("ip", {"link", "delete", WG_INTERFACE}); - QDir wgRuntimeDir(WG_RUNTIME_DIR); if (!wgRuntimeDir.exists()) { wgRuntimeDir.mkpath("."); } - // Remove stale runtime files from a previous session. - QFile::remove(wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".name")); - QFile::remove(wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".sock")); QProcessEnvironment pe = QProcessEnvironment::systemEnvironment(); QString wgNameFile = wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".sock"); @@ -245,8 +237,10 @@ bool WireguardUtilsLinux::updatePeer(const InterfaceConfig& config) { // Exclude the server address, except for multihop exit servers. if ((config.m_hopType != InterfaceConfig::MultiHopExit) && (m_rtmonitor != nullptr)) { - m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn)); - m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv6AddrIn)); + IPAddress v4(config.m_serverIpv4AddrIn); + if (!v4.address().isNull()) m_rtmonitor->addExclusionRoute(v4); + IPAddress v6(config.m_serverIpv6AddrIn); + if (!v6.address().isNull()) m_rtmonitor->addExclusionRoute(v6); } int err = uapiErrno(uapiCommand(message)); @@ -260,11 +254,13 @@ bool WireguardUtilsLinux::deletePeer(const InterfaceConfig& config) { QByteArray publicKey = QByteArray::fromBase64(qPrintable(config.m_serverPublicKey)); - // Clear exclustion routes for this peer. + // Clear exclusion routes for this peer. if ((config.m_hopType != InterfaceConfig::MultiHopExit) && (m_rtmonitor != nullptr)) { - m_rtmonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv4AddrIn)); - m_rtmonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv6AddrIn)); + IPAddress v4(config.m_serverIpv4AddrIn); + if (!v4.address().isNull()) m_rtmonitor->deleteExclusionRoute(v4); + IPAddress v6(config.m_serverIpv6AddrIn); + if (!v6.address().isNull()) m_rtmonitor->deleteExclusionRoute(v6); } QString message; diff --git a/client/platforms/linux/linuxnetworkwatcherworker.cpp b/client/platforms/linux/linuxnetworkwatcherworker.cpp index 2a9453346..a03490b24 100644 --- a/client/platforms/linux/linuxnetworkwatcherworker.cpp +++ b/client/platforms/linux/linuxnetworkwatcherworker.cpp @@ -213,7 +213,12 @@ void LinuxNetworkWatcherWorker::NMStateChanged(quint32 state) if (state == NM_STATE_ASLEEP) { emit wakeup(); } else if (state >= NM_STATE_CONNECTED_SITE && m_previousNMState < NM_STATE_CONNECTED_SITE) { - emit networkChanged(); + // Delay the reconnect so the kernel routing table (and default gateway) + // are fully restored before the VPN exclusion route is recalculated. + // Without this delay, getGatewayAndIface() may return an empty gateway + // immediately after network recovery, causing the server exclusion route + // to be installed with gateway 0.0.0.0 and breaking WG handshakes. + QTimer::singleShot(3000, this, [this]() { emit networkChanged(); }); } m_previousNMState = state;