diff --git a/client/core/controllers/gatewayController.cpp b/client/core/controllers/gatewayController.cpp index 3e505f3c7..f358b3499 100644 --- a/client/core/controllers/gatewayController.cpp +++ b/client/core/controllers/gatewayController.cpp @@ -79,7 +79,7 @@ ErrorCode GatewayController::get(const QString &endpoint, QByteArray &responseBo if (m_isStrictKillSwitchEnabled) { const QUrl originalUrl = request.url(); const QString originalHost = originalUrl.host(); - const QString resolvedIp = allowKillSwitchExceptionForUrl(originalUrl); + const QString resolvedIp = addKillSwitchExceptionForUrl(originalUrl); if (!resolvedIp.isEmpty() && resolvedIp != originalHost) { QUrl ipUrl = originalUrl; ipUrl.setHost(resolvedIp); @@ -146,7 +146,7 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api if (m_isStrictKillSwitchEnabled) { const QUrl originalUrl = request.url(); const QString originalHost = originalUrl.host(); - const QString resolvedIp = allowKillSwitchExceptionForUrl(originalUrl); + const QString resolvedIp = addKillSwitchExceptionForUrl(originalUrl); if (!resolvedIp.isEmpty() && resolvedIp != originalHost) { QUrl ipUrl = originalUrl; ipUrl.setHost(resolvedIp); @@ -384,7 +384,7 @@ void GatewayController::bypassProxy(const QString &endpoint, QNetworkReply *repl } } -QString GatewayController::allowKillSwitchExceptionForUrl(const QUrl &url) +QString GatewayController::addKillSwitchExceptionForUrl(const QUrl &url) { #ifdef AMNEZIA_DESKTOP const QString host = url.host(); @@ -475,6 +475,41 @@ bool GatewayController::addKillSwitchException(const QStringList &ranges) return result; } +bool GatewayController::removeKillSwitchException(const QStringList &ranges) +{ + auto ipcInterface = IpcClient::Interface(); + if (!ipcInterface) { + qWarning() << "IPC interface is null, cannot remove KillSwitch exception"; + return false; + } + + const auto waitForReply = [](QRemoteObjectPendingReply reply) -> bool { + if (!reply.waitForFinished()) { + qWarning() << "Timed out waiting for KillSwitch removal reply"; + return false; + } + return reply.returnValue(); + }; + + QRemoteObjectPendingReply reply; + if (ipcInterface->thread() == QThread::currentThread()) { + reply = ipcInterface->removeKillSwitchAllowedRange(ranges); + } else { + const bool invoked = QMetaObject::invokeMethod(ipcInterface.data(), + [&reply, ipcInterface, ranges]() { + reply = ipcInterface->removeKillSwitchAllowedRange(ranges); + }, + Qt::BlockingQueuedConnection); + if (!invoked) { + qWarning() << "Failed to invoke KillSwitch removal via queued connection"; + return false; + } + } + + const bool result = waitForReply(reply); + return result; +} + QString GatewayController::resolveHostViaOpenDns(const QString &host) { const QString fallbackIp = QStringLiteral("146.112.41.2"); diff --git a/client/core/controllers/gatewayController.h b/client/core/controllers/gatewayController.h index cf936ab47..6f23f6ae5 100644 --- a/client/core/controllers/gatewayController.h +++ b/client/core/controllers/gatewayController.h @@ -27,10 +27,11 @@ private: const QByteArray &iv = "", const QByteArray &salt = ""); void bypassProxy(const QString &endpoint, QNetworkReply *reply, std::function requestFunction, std::function &sslErrors)> replyProcessingFunction); - QString allowKillSwitchExceptionForUrl(const QUrl &url); + QString addKillSwitchExceptionForUrl(const QUrl &url); QString resolveHost(const QString &host); #ifdef AMNEZIA_DESKTOP bool addKillSwitchException(const QStringList &ranges); + bool removeKillSwitchException(const QStringList &ranges); QString resolveHostViaOpenDns(const QString &host); QString resolveHostViaQuad9(const QString &host); QByteArray buildDnsQuery(const QString &host) const; diff --git a/ipc/ipc_interface.rep b/ipc/ipc_interface.rep index 4ecae9bcd..4515b519b 100644 --- a/ipc/ipc_interface.rep +++ b/ipc/ipc_interface.rep @@ -32,6 +32,7 @@ class IpcInterface SLOT( bool disableAllTraffic() ); SLOT( bool refreshKillSwitch( bool enabled ) ); SLOT( bool addKillSwitchAllowedRange( const QStringList ranges ) ); + SLOT( bool removeKillSwitchAllowedRange( const QStringList ranges ) ); SLOT( bool resetKillSwitchAllowedRange( const QStringList ranges ) ); SLOT( bool enablePeerTraffic( const QJsonObject &configStr) ); SLOT( bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex) ); diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp index 0c7f5295e..fa6884bae 100644 --- a/ipc/ipcserver.cpp +++ b/ipc/ipcserver.cpp @@ -189,6 +189,11 @@ bool IpcServer::addKillSwitchAllowedRange(QStringList ranges) return KillSwitch::instance()->addAllowedRange(ranges); } +bool IpcServer::removeKillSwitchAllowedRange(QStringList ranges) +{ + return KillSwitch::instance()->removeAllowedRange(ranges); +} + bool IpcServer::disableAllTraffic() { return KillSwitch::instance()->disableAllTraffic(); diff --git a/ipc/ipcserver.h b/ipc/ipcserver.h index 00d36354e..58b493552 100644 --- a/ipc/ipcserver.h +++ b/ipc/ipcserver.h @@ -36,6 +36,7 @@ public: virtual void StopRoutingIpv6() override; virtual bool disableAllTraffic() override; virtual bool addKillSwitchAllowedRange(QStringList ranges) override; + virtual bool removeKillSwitchAllowedRange(QStringList ranges) override; virtual bool resetKillSwitchAllowedRange(QStringList ranges) override; virtual bool enablePeerTraffic(const QJsonObject &configStr) override; virtual bool enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) override; diff --git a/service/server/killswitch.cpp b/service/server/killswitch.cpp index d0cba03a5..60021fb9d 100644 --- a/service/server/killswitch.cpp +++ b/service/server/killswitch.cpp @@ -189,6 +189,21 @@ bool KillSwitch::addAllowedRange(const QStringList &ranges) { return resetAllowedRange(m_allowedRanges); } +bool KillSwitch::removeAllowedRange(const QStringList &ranges) { + bool modified = false; + for (const QString &range : ranges) { + if (!range.isEmpty()) { + modified = modified || m_allowedRanges.removeAll(range) > 0; + } + } + + if (!modified) { + return true; + } + + return resetAllowedRange(m_allowedRanges); +} + bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) { #ifdef Q_OS_WIN InterfaceConfig config; diff --git a/service/server/killswitch.h b/service/server/killswitch.h index 519e2ed2a..f7cc34e3d 100644 --- a/service/server/killswitch.h +++ b/service/server/killswitch.h @@ -19,6 +19,7 @@ public: bool enableKillSwitch(const QJsonObject &configStr, int vpnAdapterIndex); bool resetAllowedRange(const QStringList &ranges); bool addAllowedRange(const QStringList &ranges); + bool removeAllowedRange(const QStringList &ranges); bool isStrictKillSwitchEnabled(); private: