mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-20 02:00:55 +07:00
refactor: move routing/KS/DNS lifecycle from Daemon to TrafficGuard
This commit is contained in:
@@ -13,6 +13,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "core/utils/networkUtilities.h"
|
#include "core/utils/networkUtilities.h"
|
||||||
|
#include "core/tunnel.h"
|
||||||
|
#include "mozilla/localsocketcontroller.h"
|
||||||
|
|
||||||
VpnTrafficGuard::VpnTrafficGuard(SecureAppSettingsRepository* appSettings, QObject *parent)
|
VpnTrafficGuard::VpnTrafficGuard(SecureAppSettingsRepository* appSettings, QObject *parent)
|
||||||
: QObject(parent), m_appSettingsRepository(appSettings)
|
: QObject(parent), m_appSettingsRepository(appSettings)
|
||||||
@@ -230,29 +232,30 @@ void VpnTrafficGuard::applyFirewall(const QString &gateway, const QString &local
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnTrafficGuard::teardown()
|
void VpnTrafficGuard::flushAll()
|
||||||
{
|
{
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
|
iface->restoreTunnelResolvers();
|
||||||
QRemoteObjectPendingReply<bool> reply = iface->disableKillSwitch();
|
QRemoteObjectPendingReply<bool> reply = iface->disableKillSwitch();
|
||||||
m_allowedEndpoints.clear();
|
m_allowedEndpoints.clear();
|
||||||
//TODO: why it takes so long?
|
//TODO: why it takes so long?
|
||||||
if (!reply.waitForFinished(5000) || !reply.returnValue()) {
|
if (!reply.waitForFinished(5000) || !reply.returnValue()) {
|
||||||
qWarning() << "VpnTrafficGuard::teardown: Failed to disable killswitch";
|
qWarning() << "VpnTrafficGuard::flushAll: Failed to disable killswitch";
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "VpnTrafficGuard::teardown: Successfully disabled killswitch";
|
qDebug() << "VpnTrafficGuard::flushAll: Successfully disabled killswitch";
|
||||||
}
|
}
|
||||||
auto flushDns = iface->flushDns();
|
auto flushDns = iface->flushDns();
|
||||||
if (flushDns.waitForFinished() && flushDns.returnValue())
|
if (flushDns.waitForFinished() && flushDns.returnValue())
|
||||||
qDebug() << "VpnTrafficGuard::teardown: Successfully flushed DNS";
|
qDebug() << "VpnTrafficGuard::flushAll: Successfully flushed DNS";
|
||||||
else
|
else
|
||||||
qWarning() << "VpnTrafficGuard::teardown: Failed to flush DNS";
|
qWarning() << "VpnTrafficGuard::flushAll: Failed to flush DNS";
|
||||||
|
|
||||||
auto clearSavedRoutes = iface->clearSavedRoutes();
|
auto clearSavedRoutes = iface->clearSavedRoutes();
|
||||||
if (clearSavedRoutes.waitForFinished() && clearSavedRoutes.returnValue())
|
if (clearSavedRoutes.waitForFinished() && clearSavedRoutes.returnValue())
|
||||||
qDebug() << "VpnTrafficGuard::teardown: Successfully cleared saved routes";
|
qDebug() << "VpnTrafficGuard::flushAll: Successfully cleared saved routes";
|
||||||
else
|
else
|
||||||
qWarning() << "VpnTrafficGuard::teardown: Failed to clear saved routes";
|
qWarning() << "VpnTrafficGuard::flushAll: Failed to clear saved routes";
|
||||||
if (m_ipv6RoutingStopped) {
|
if (m_ipv6RoutingStopped) {
|
||||||
auto StartRoutingIpv6 = iface->StartRoutingIpv6();
|
auto StartRoutingIpv6 = iface->StartRoutingIpv6();
|
||||||
if (!StartRoutingIpv6.waitForFinished() || !StartRoutingIpv6.returnValue()) {
|
if (!StartRoutingIpv6.waitForFinished() || !StartRoutingIpv6.returnValue()) {
|
||||||
@@ -264,3 +267,144 @@ void VpnTrafficGuard::teardown()
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
QStringList allowedIpPrefixesFor(const QJsonObject& activateJson)
|
||||||
|
{
|
||||||
|
QStringList prefixes;
|
||||||
|
const QJsonArray ranges = activateJson.value("allowedIPAddressRanges").toArray();
|
||||||
|
for (const QJsonValue& v : ranges) {
|
||||||
|
const QJsonObject r = v.toObject();
|
||||||
|
const QString addr = r.value("address").toString();
|
||||||
|
if (addr.isEmpty()) continue;
|
||||||
|
prefixes.append(QStringLiteral("%1/%2").arg(addr).arg(r.value("range").toInt()));
|
||||||
|
}
|
||||||
|
return prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList excludedAddressesFor(const QJsonObject& activateJson)
|
||||||
|
{
|
||||||
|
QStringList addrs;
|
||||||
|
const QJsonArray excluded = activateJson.value("excludedAddresses").toArray();
|
||||||
|
for (const QJsonValue& v : excluded) {
|
||||||
|
const QString s = v.toString();
|
||||||
|
if (!s.isEmpty()) addrs.append(s);
|
||||||
|
}
|
||||||
|
return addrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList resolversFor(const QJsonObject& activateJson)
|
||||||
|
{
|
||||||
|
QStringList dns;
|
||||||
|
const QString primary = activateJson.value("primaryDnsServer").toString();
|
||||||
|
if (!primary.isEmpty()) dns.append(primary);
|
||||||
|
const QString secondary = activateJson.value("secondaryDnsServer").toString();
|
||||||
|
if (!secondary.isEmpty()) dns.append(secondary);
|
||||||
|
return dns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::reserve(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
#ifdef AMNEZIA_DESKTOP
|
||||||
|
allowEndpoint(tunnel->remoteAddress());
|
||||||
|
#else
|
||||||
|
Q_UNUSED(tunnel)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::release(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
#ifdef AMNEZIA_DESKTOP
|
||||||
|
revokeEndpoint(tunnel->remoteAddress());
|
||||||
|
#else
|
||||||
|
Q_UNUSED(tunnel)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::applyPolicy(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
#ifdef AMNEZIA_DESKTOP
|
||||||
|
const QJsonObject activate = LocalSocketController::buildActivateJson(tunnel->config(), tunnel->ifname());
|
||||||
|
const QStringList prefixes = allowedIpPrefixesFor(activate);
|
||||||
|
const QStringList excluded = excludedAddressesFor(activate);
|
||||||
|
const QStringList dns = resolversFor(activate);
|
||||||
|
const QString ifname = tunnel->ifname();
|
||||||
|
const QString peer = tunnel->remoteAddress();
|
||||||
|
|
||||||
|
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
|
if (!peer.isEmpty()) iface->addExclusionRoute(peer);
|
||||||
|
for (const QString& addr : excluded) {
|
||||||
|
iface->addExclusionRoute(addr);
|
||||||
|
}
|
||||||
|
for (const QString& prefix : prefixes) {
|
||||||
|
iface->addAllowedIp(ifname, prefix);
|
||||||
|
}
|
||||||
|
iface->setTunnelResolvers(ifname, dns);
|
||||||
|
iface->flushDns();
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
Q_UNUSED(tunnel)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::revokePolicy(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
#ifdef AMNEZIA_DESKTOP
|
||||||
|
const QJsonObject activate = LocalSocketController::buildActivateJson(tunnel->config(), tunnel->ifname());
|
||||||
|
const QStringList prefixes = allowedIpPrefixesFor(activate);
|
||||||
|
const QStringList excluded = excludedAddressesFor(activate);
|
||||||
|
const QString ifname = tunnel->ifname();
|
||||||
|
const QString peer = tunnel->remoteAddress();
|
||||||
|
|
||||||
|
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
|
for (const QString& prefix : prefixes) {
|
||||||
|
iface->delAllowedIp(ifname, prefix);
|
||||||
|
}
|
||||||
|
for (const QString& addr : excluded) {
|
||||||
|
iface->delExclusionRoute(addr);
|
||||||
|
}
|
||||||
|
if (!peer.isEmpty()) iface->delExclusionRoute(peer);
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
Q_UNUSED(tunnel)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::bringUp(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
reserve(tunnel);
|
||||||
|
tunnel->prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::commit(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
applyPolicy(tunnel);
|
||||||
|
tunnel->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::tearDown(Tunnel* tunnel)
|
||||||
|
{
|
||||||
|
if (!tunnel) return;
|
||||||
|
revokePolicy(tunnel);
|
||||||
|
release(tunnel);
|
||||||
|
tunnel->deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnTrafficGuard::swap(Tunnel* from, Tunnel* to)
|
||||||
|
{
|
||||||
|
if (!to) return;
|
||||||
|
applyPolicy(to);
|
||||||
|
to->commit();
|
||||||
|
if (from) {
|
||||||
|
revokePolicy(from);
|
||||||
|
release(from);
|
||||||
|
from->deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "core/repositories/secureAppSettingsRepository.h"
|
#include "core/repositories/secureAppSettingsRepository.h"
|
||||||
#include "protocols/vpnProtocol.h"
|
#include "protocols/vpnProtocol.h"
|
||||||
|
|
||||||
|
class Tunnel;
|
||||||
|
|
||||||
class VpnTrafficGuard : public QObject
|
class VpnTrafficGuard : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -17,10 +19,21 @@ public:
|
|||||||
const QSharedPointer<VpnProtocol> &protocol,
|
const QSharedPointer<VpnProtocol> &protocol,
|
||||||
const QString &remoteAddress);
|
const QString &remoteAddress);
|
||||||
|
|
||||||
void teardown();
|
void flushAll();
|
||||||
bool allowEndpoint(const QString &remoteAddress);
|
bool allowEndpoint(const QString &remoteAddress);
|
||||||
void revokeEndpoint(const QString &remoteAddress);
|
void revokeEndpoint(const QString &remoteAddress);
|
||||||
void applyFirewall(const QString &vpnGateway, const QString &vpnLocalAddress);
|
void applyFirewall(const QString &vpnGateway, const QString &vpnLocalAddress);
|
||||||
|
|
||||||
|
void reserve(Tunnel* tunnel);
|
||||||
|
void release(Tunnel* tunnel);
|
||||||
|
void applyPolicy(Tunnel* tunnel);
|
||||||
|
void revokePolicy(Tunnel* tunnel);
|
||||||
|
|
||||||
|
void bringUp(Tunnel* tunnel);
|
||||||
|
void commit(Tunnel* tunnel);
|
||||||
|
void tearDown(Tunnel* tunnel);
|
||||||
|
void swap(Tunnel* from, Tunnel* to);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addSplitTunnelRoutes(const QString &gateway, amnezia::RouteMode mode);
|
void addSplitTunnelRoutes(const QString &gateway, amnezia::RouteMode mode);
|
||||||
SecureAppSettingsRepository* m_appSettingsRepository;
|
SecureAppSettingsRepository* m_appSettingsRepository;
|
||||||
|
|||||||
+48
-102
@@ -101,13 +101,6 @@ bool Daemon::activate(const QString& ifname, const InterfaceConfig& config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.m_serverIpv4AddrIn.isEmpty()) {
|
|
||||||
addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
|
||||||
}
|
|
||||||
if (!config.m_serverIpv6AddrIn.isEmpty()) {
|
|
||||||
addExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the peer to this interface.
|
// Add the peer to this interface.
|
||||||
if (!wg->updatePeer(config)) {
|
if (!wg->updatePeer(config)) {
|
||||||
logger.error() << "Peer creation failed.";
|
logger.error() << "Peer creation failed.";
|
||||||
@@ -138,90 +131,32 @@ bool Daemon::setPrimary(const QString& ifname, const InterfaceConfig& config) {
|
|||||||
m_primaryIfname = priorPrimary;
|
m_primaryIfname = priorPrimary;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const QString& i : config.m_excludedAddresses) {
|
|
||||||
addExclusionRoute(IPAddress(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
|
|
||||||
if (!wg->updateRoutePrefix(ip)) {
|
|
||||||
logger.warning() << "setPrimary: route setup failed for" << ip.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!maybeUpdateResolvers(config)) {
|
|
||||||
logger.warning() << "setPrimary: DNS resolver update failed";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!run(Up, config)) {
|
if (!run(Up, config)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_connections[ifname].m_config = config;
|
m_connections[ifname].m_config = config;
|
||||||
|
|
||||||
// Demote the prior primary AFTER the new primary is fully installed.
|
|
||||||
// Delete-after-install order preserves coverage during the make-before-break overlap.
|
|
||||||
if (!priorPrimary.isEmpty() && priorPrimary != ifname) {
|
|
||||||
demotePrimary(priorPrimary);
|
|
||||||
}
|
|
||||||
|
|
||||||
failure_guard.dismiss();
|
failure_guard.dismiss();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Daemon::demotePrimary(const QString& ifname) {
|
|
||||||
WireguardUtils* wg = wgutilsFor(ifname);
|
|
||||||
if (!wg) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const ConnectionState cs = m_connections.value(ifname);
|
|
||||||
const InterfaceConfig& config = cs.m_config;
|
|
||||||
|
|
||||||
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
|
|
||||||
wg->deleteRoutePrefix(ip);
|
|
||||||
}
|
|
||||||
for (const QString& addr : config.m_excludedAddresses) {
|
|
||||||
if (addr.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
IPAddress ip(addr);
|
|
||||||
if (m_excludedAddrSet.contains(ip)) {
|
|
||||||
delExclusionRoute(ip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Daemon::deactivateTunnel(const QString& ifname) {
|
bool Daemon::deactivateTunnel(const QString& ifname) {
|
||||||
WireguardUtils* wg = m_tunnels.value(ifname);
|
WireguardUtils* wg = m_tunnels.value(ifname);
|
||||||
const ConnectionState cs = m_connections.value(ifname);
|
const ConnectionState cs = m_connections.value(ifname);
|
||||||
const InterfaceConfig& config = cs.m_config;
|
const InterfaceConfig& config = cs.m_config;
|
||||||
const bool wasPrimary = (ifname == m_primaryIfname);
|
const bool wasPrimary = (ifname == m_primaryIfname);
|
||||||
|
const bool isLastTunnel = wg && m_tunnels.size() == 1;
|
||||||
|
|
||||||
if (wg) {
|
if (wg) {
|
||||||
logger.debug() << "deactivateTunnel" << wg->interfaceName();
|
logger.debug() << "deactivateTunnel" << wg->interfaceName();
|
||||||
if (wasPrimary) {
|
if (isLastTunnel) {
|
||||||
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
|
for (const IPAddress& prefix : m_excludedAddrSet.keys()) {
|
||||||
wg->deleteRoutePrefix(ip);
|
wg->deleteExclusionRoute(prefix);
|
||||||
}
|
}
|
||||||
|
m_excludedAddrSet.clear();
|
||||||
}
|
}
|
||||||
wg->deletePeer(config);
|
wg->deletePeer(config);
|
||||||
|
|
||||||
auto removeExclusion = [&](const QString& addr) {
|
|
||||||
if (addr.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IPAddress ip(addr);
|
|
||||||
if (m_excludedAddrSet.contains(ip)) {
|
|
||||||
delExclusionRoute(ip);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
removeExclusion(config.m_serverIpv4AddrIn);
|
|
||||||
removeExclusion(config.m_serverIpv6AddrIn);
|
|
||||||
if (wasPrimary) {
|
|
||||||
for (const QString& i : config.m_excludedAddresses) {
|
|
||||||
removeExclusion(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wg->deleteInterface();
|
wg->deleteInterface();
|
||||||
m_tunnels.remove(ifname);
|
m_tunnels.remove(ifname);
|
||||||
delete wg;
|
delete wg;
|
||||||
@@ -234,30 +169,6 @@ bool Daemon::deactivateTunnel(const QString& ifname) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Daemon::maybeUpdateResolvers(const InterfaceConfig& config) {
|
|
||||||
if ((config.m_hopType == InterfaceConfig::MultiHopExit) ||
|
|
||||||
(config.m_hopType == InterfaceConfig::SingleHop)) {
|
|
||||||
QList<QHostAddress> resolvers;
|
|
||||||
resolvers.append(QHostAddress(config.m_primaryDnsServer));
|
|
||||||
if (!config.m_secondaryDnsServer.isEmpty()) {
|
|
||||||
resolvers.append(QHostAddress(config.m_secondaryDnsServer));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the DNS is not the Gateway, it's a user defined DNS
|
|
||||||
// thus, not add any other :)
|
|
||||||
if (config.m_primaryDnsServer == config.m_serverIpv4Gateway) {
|
|
||||||
resolvers.append(QHostAddress(config.m_serverIpv6Gateway));
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString ifname = wgutilsFor(config.m_ifname)->interfaceName();
|
|
||||||
if (!dnsutils()->updateResolvers(ifname, resolvers)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool Daemon::parseStringList(const QJsonObject& obj, const QString& name,
|
bool Daemon::parseStringList(const QJsonObject& obj, const QString& name,
|
||||||
QStringList& list) {
|
QStringList& list) {
|
||||||
@@ -279,20 +190,25 @@ bool Daemon::parseStringList(const QJsonObject& obj, const QString& name,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Daemon::addExclusionRoute(const IPAddress& prefix) {
|
bool Daemon::addExclusionRoute(const QString &addr) {
|
||||||
|
IPAddress prefix(addr);
|
||||||
if (m_excludedAddrSet.contains(prefix)) {
|
if (m_excludedAddrSet.contains(prefix)) {
|
||||||
m_excludedAddrSet[prefix]++;
|
m_excludedAddrSet[prefix]++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!primaryWgutils()->addExclusionRoute(prefix)) {
|
WireguardUtils* wg = primaryWgutils();
|
||||||
|
if (!wg || !wg->addExclusionRoute(prefix)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_excludedAddrSet[prefix] = 1;
|
m_excludedAddrSet[prefix] = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Daemon::delExclusionRoute(const IPAddress& prefix) {
|
bool Daemon::delExclusionRoute(const QString &addr) {
|
||||||
Q_ASSERT(m_excludedAddrSet.contains(prefix));
|
IPAddress prefix(addr);
|
||||||
|
if (!m_excludedAddrSet.contains(prefix)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (m_excludedAddrSet[prefix] > 1) {
|
if (m_excludedAddrSet[prefix] > 1) {
|
||||||
m_excludedAddrSet[prefix]--;
|
m_excludedAddrSet[prefix]--;
|
||||||
return true;
|
return true;
|
||||||
@@ -302,6 +218,32 @@ bool Daemon::delExclusionRoute(const IPAddress& prefix) {
|
|||||||
return wg && wg->deleteExclusionRoute(prefix);
|
return wg && wg->deleteExclusionRoute(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Daemon::addAllowedIp(const QString &ifname, const QString &prefix) {
|
||||||
|
WireguardUtils* wg = wgutilsFor(ifname);
|
||||||
|
return wg && wg->updateRoutePrefix(IPAddress(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Daemon::delAllowedIp(const QString &ifname, const QString &prefix) {
|
||||||
|
WireguardUtils* wg = wgutilsFor(ifname);
|
||||||
|
return wg && wg->deleteRoutePrefix(IPAddress(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Daemon::setTunnelResolvers(const QString &ifname, const QStringList &resolvers) {
|
||||||
|
WireguardUtils* wg = wgutilsFor(ifname);
|
||||||
|
if (!wg || !dnsutils()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QList<QHostAddress> hostAddrs;
|
||||||
|
for (const QString& r : resolvers) {
|
||||||
|
hostAddrs.append(QHostAddress(r));
|
||||||
|
}
|
||||||
|
return dnsutils()->updateResolvers(wg->interfaceName(), hostAddrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Daemon::restoreTunnelResolvers() {
|
||||||
|
return dnsutils() && dnsutils()->restoreResolvers();
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
||||||
#define GETVALUE(name, where, jsontype) \
|
#define GETVALUE(name, where, jsontype) \
|
||||||
@@ -529,16 +471,20 @@ bool Daemon::deactivate(bool emitSignals) {
|
|||||||
emit disconnected();
|
emit disconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dnsutils()->restoreResolvers()) {
|
|
||||||
logger.warning() << "Failed to restore DNS resolvers.";
|
|
||||||
}
|
|
||||||
|
|
||||||
const QStringList ifnames = m_tunnels.keys();
|
const QStringList ifnames = m_tunnels.keys();
|
||||||
for (const QString& ifname : ifnames) {
|
for (const QString& ifname : ifnames) {
|
||||||
if (ifname != primary) {
|
if (ifname != primary) {
|
||||||
deactivateTunnel(ifname);
|
deactivateTunnel(ifname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto* wg = primaryWgutils()) {
|
||||||
|
for (const IPAddress& prefix : m_excludedAddrSet.keys()) {
|
||||||
|
wg->deleteExclusionRoute(prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_excludedAddrSet.clear();
|
||||||
|
|
||||||
if (m_tunnels.contains(primary)) {
|
if (m_tunnels.contains(primary)) {
|
||||||
deactivateTunnel(primary);
|
deactivateTunnel(primary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ class Daemon : public QObject {
|
|||||||
virtual bool deactivate(bool emitSignals = true);
|
virtual bool deactivate(bool emitSignals = true);
|
||||||
virtual QJsonObject getStatus();
|
virtual QJsonObject getStatus();
|
||||||
|
|
||||||
|
bool addExclusionRoute(const QString &addr);
|
||||||
|
bool delExclusionRoute(const QString &addr);
|
||||||
|
bool addAllowedIp(const QString &ifname, const QString &prefix);
|
||||||
|
bool delAllowedIp(const QString &ifname, const QString &prefix);
|
||||||
|
bool setTunnelResolvers(const QString &ifname, const QStringList &resolvers);
|
||||||
|
bool restoreTunnelResolvers();
|
||||||
|
|
||||||
const QString& primaryIfname() const { return m_primaryIfname; }
|
const QString& primaryIfname() const { return m_primaryIfname; }
|
||||||
WireguardUtils* wgutilsFor(const QString& ifname) const { return m_tunnels.value(ifname); }
|
WireguardUtils* wgutilsFor(const QString& ifname) const { return m_tunnels.value(ifname); }
|
||||||
|
|
||||||
@@ -56,10 +63,6 @@ class Daemon : public QObject {
|
|||||||
void backendFailure(DaemonError reason = DaemonError::ERROR_FATAL);
|
void backendFailure(DaemonError reason = DaemonError::ERROR_FATAL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool maybeUpdateResolvers(const InterfaceConfig& config);
|
|
||||||
bool addExclusionRoute(const IPAddress& address);
|
|
||||||
bool delExclusionRoute(const IPAddress& address);
|
|
||||||
void demotePrimary(const QString& ifname);
|
|
||||||
void checkActivations();
|
void checkActivations();
|
||||||
WireguardUtils* primaryWgutils() const { return m_tunnels.value(m_primaryIfname); }
|
WireguardUtils* primaryWgutils() const { return m_tunnels.value(m_primaryIfname); }
|
||||||
QTimer m_activationTimer;
|
QTimer m_activationTimer;
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ void LocalSocketController::daemonConnected() {
|
|||||||
checkStatus();
|
checkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LocalSocketController::buildActivateJson(const QJsonObject& rawConfig) {
|
QJsonObject LocalSocketController::buildActivateJson(const QJsonObject& rawConfig,
|
||||||
|
const QString& ifname) {
|
||||||
QString protocolName = rawConfig.value("protocol").toString();
|
QString protocolName = rawConfig.value("protocol").toString();
|
||||||
|
|
||||||
int splitTunnelType = rawConfig.value("splitTunnelType").toInt();
|
int splitTunnelType = rawConfig.value("splitTunnelType").toInt();
|
||||||
@@ -138,7 +139,6 @@ QJsonObject LocalSocketController::buildActivateJson(const QJsonObject& rawConfi
|
|||||||
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
|
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
|
||||||
json.insert("privateKey", wgConfig.value(amnezia::configKey::clientPrivKey));
|
json.insert("privateKey", wgConfig.value(amnezia::configKey::clientPrivKey));
|
||||||
json.insert("deviceIpv4Address", wgConfig.value(amnezia::configKey::clientIp));
|
json.insert("deviceIpv4Address", wgConfig.value(amnezia::configKey::clientIp));
|
||||||
m_deviceIpv4 = wgConfig.value(amnezia::configKey::clientIp).toString();
|
|
||||||
|
|
||||||
// set up IPv6 unique-local-address, ULA, with "fd00::/8" prefix, not globally routable.
|
// set up IPv6 unique-local-address, ULA, with "fd00::/8" prefix, not globally routable.
|
||||||
// this will be default IPv6 gateway, OS recognizes that IPv6 link is local and switches to IPv4.
|
// this will be default IPv6 gateway, OS recognizes that IPv6 link is local and switches to IPv4.
|
||||||
@@ -230,7 +230,6 @@ QJsonObject LocalSocketController::buildActivateJson(const QJsonObject& rawConfi
|
|||||||
json.insert("allowedIPAddressRanges", jsAllowedIPAddesses);
|
json.insert("allowedIPAddressRanges", jsAllowedIPAddesses);
|
||||||
|
|
||||||
QJsonArray jsExcludedAddresses;
|
QJsonArray jsExcludedAddresses;
|
||||||
jsExcludedAddresses.append(wgConfig.value(amnezia::configKey::hostName));
|
|
||||||
if (splitTunnelType == 2) {
|
if (splitTunnelType == 2) {
|
||||||
for (auto v : splitTunnelSites) {
|
for (auto v : splitTunnelSites) {
|
||||||
QString ipRange = v.toString();
|
QString ipRange = v.toString();
|
||||||
@@ -292,18 +291,22 @@ QJsonObject LocalSocketController::buildActivateJson(const QJsonObject& rawConfi
|
|||||||
json.insert(amnezia::configKey::specialJunk5, wgConfig.value(amnezia::configKey::specialJunk5));
|
json.insert(amnezia::configKey::specialJunk5, wgConfig.value(amnezia::configKey::specialJunk5));
|
||||||
}
|
}
|
||||||
|
|
||||||
json.insert("ifname", m_ifname);
|
json.insert("ifname", ifname);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSocketController::activate(const QJsonObject& rawConfig) {
|
void LocalSocketController::activate(const QJsonObject& rawConfig) {
|
||||||
QJsonObject json = buildActivateJson(rawConfig);
|
const QString protocolName = rawConfig.value("protocol").toString();
|
||||||
|
const QJsonObject wgConfig = rawConfig.value(protocolName + "_config_data").toObject();
|
||||||
|
m_deviceIpv4 = wgConfig.value(amnezia::configKey::clientIp).toString();
|
||||||
|
|
||||||
|
QJsonObject json = buildActivateJson(rawConfig, m_ifname);
|
||||||
json.insert("type", "activate");
|
json.insert("type", "activate");
|
||||||
write(json);
|
write(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSocketController::setPrimary(const QJsonObject& rawConfig) {
|
void LocalSocketController::setPrimary(const QJsonObject& rawConfig) {
|
||||||
QJsonObject json = buildActivateJson(rawConfig);
|
QJsonObject json = buildActivateJson(rawConfig, m_ifname);
|
||||||
json.insert("type", "setPrimary");
|
json.insert("type", "setPrimary");
|
||||||
write(json);
|
write(json);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,12 +38,14 @@ class LocalSocketController final : public ControllerImpl {
|
|||||||
|
|
||||||
bool multihopSupported() override { return true; }
|
bool multihopSupported() override { return true; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
static QJsonObject buildActivateJson(const QJsonObject& rawConfig,
|
||||||
|
const QString& ifname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeInternal();
|
void initializeInternal();
|
||||||
void disconnectInternal();
|
void disconnectInternal();
|
||||||
|
|
||||||
QJsonObject buildActivateJson(const QJsonObject& rawConfig);
|
|
||||||
|
|
||||||
void daemonConnected();
|
void daemonConnected();
|
||||||
void errorOccurred(QLocalSocket::LocalSocketError socketError);
|
void errorOccurred(QLocalSocket::LocalSocketError socketError);
|
||||||
void readData();
|
void readData();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include "leakdetector.h"
|
#include "leakdetector.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "killswitch.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Logger logger("LinuxDaemon");
|
Logger logger("LinuxDaemon");
|
||||||
@@ -51,8 +50,3 @@ LinuxDaemon* LinuxDaemon::instance() {
|
|||||||
return s_daemon;
|
return s_daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LinuxDaemon::deactivate(bool emitSignals) {
|
|
||||||
bool result = Daemon::deactivate(emitSignals);
|
|
||||||
KillSwitch::instance()->disableKillSwitch();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ class LinuxDaemon final : public Daemon {
|
|||||||
|
|
||||||
static LinuxDaemon* instance();
|
static LinuxDaemon* instance();
|
||||||
|
|
||||||
bool deactivate(bool emitSignals = true) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DnsUtils* dnsutils() override { return m_dnsutils; }
|
DnsUtils* dnsutils() override { return m_dnsutils; }
|
||||||
bool supportIPUtils() const override { return true; }
|
bool supportIPUtils() const override { return true; }
|
||||||
|
|||||||
@@ -208,15 +208,6 @@ bool WireguardUtilsLinux::updatePeer(const InterfaceConfig& config) {
|
|||||||
out << "allowed_ip=" << ip.toString() << "\n";
|
out << "allowed_ip=" << ip.toString() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude the server address, except for multihop exit servers.
|
|
||||||
if ((config.m_hopType != InterfaceConfig::MultiHopExit) &&
|
|
||||||
(m_rtmonitor != nullptr)) {
|
|
||||||
if (!config.m_serverIpv4AddrIn.isEmpty())
|
|
||||||
m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
|
||||||
if (!config.m_serverIpv6AddrIn.isEmpty())
|
|
||||||
m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = uapiErrno(uapiCommand(message));
|
int err = uapiErrno(uapiCommand(message));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
logger.error() << "Peer configuration failed:" << strerror(err);
|
logger.error() << "Peer configuration failed:" << strerror(err);
|
||||||
@@ -228,15 +219,6 @@ bool WireguardUtilsLinux::deletePeer(const InterfaceConfig& config) {
|
|||||||
QByteArray publicKey =
|
QByteArray publicKey =
|
||||||
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
||||||
|
|
||||||
// Clear exclustion routes for this peer.
|
|
||||||
if ((config.m_hopType != InterfaceConfig::MultiHopExit) &&
|
|
||||||
(m_rtmonitor != nullptr)) {
|
|
||||||
if (!config.m_serverIpv4AddrIn.isEmpty())
|
|
||||||
m_rtmonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
|
||||||
if (!config.m_serverIpv6AddrIn.isEmpty())
|
|
||||||
m_rtmonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString message;
|
QString message;
|
||||||
QTextStream out(&message);
|
QTextStream out(&message);
|
||||||
out << "set=1\n";
|
out << "set=1\n";
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ bool DnsUtilsMacos::restoreResolvers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DnsUtilsMacos::backupService(const QString& uuid) {
|
void DnsUtilsMacos::backupService(const QString& uuid) {
|
||||||
|
if (m_prevServices.contains(uuid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
DnsBackup backup;
|
DnsBackup backup;
|
||||||
CFStringRef path = CFStringCreateWithFormat(
|
CFStringRef path = CFStringCreateWithFormat(
|
||||||
kCFAllocatorSystemDefault, nullptr,
|
kCFAllocatorSystemDefault, nullptr,
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include "killswitch.h"
|
|
||||||
#include "leakdetector.h"
|
#include "leakdetector.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
@@ -51,8 +50,3 @@ MacOSDaemon* MacOSDaemon::instance() {
|
|||||||
return s_daemon;
|
return s_daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacOSDaemon::deactivate(bool emitSignals) {
|
|
||||||
bool result = Daemon::deactivate(emitSignals);
|
|
||||||
KillSwitch::instance()->disableKillSwitch();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ class MacOSDaemon final : public Daemon {
|
|||||||
|
|
||||||
static MacOSDaemon* instance();
|
static MacOSDaemon* instance();
|
||||||
|
|
||||||
bool deactivate(bool emitSignals = true) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DnsUtils* dnsutils() override { return m_dnsutils; }
|
DnsUtils* dnsutils() override { return m_dnsutils; }
|
||||||
bool supportIPUtils() const override { return true; }
|
bool supportIPUtils() const override { return true; }
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ MacosRouteMonitor::MacosRouteMonitor(const QString& ifname, QObject* parent)
|
|||||||
|
|
||||||
MacosRouteMonitor::~MacosRouteMonitor() {
|
MacosRouteMonitor::~MacosRouteMonitor() {
|
||||||
MZ_COUNT_DTOR(MacosRouteMonitor);
|
MZ_COUNT_DTOR(MacosRouteMonitor);
|
||||||
flushExclusionRoutes();
|
|
||||||
if (m_rtsock >= 0) {
|
if (m_rtsock >= 0) {
|
||||||
close(m_rtsock);
|
close(m_rtsock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,13 +204,6 @@ bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
|
|||||||
out << "allowed_ip=" << ip.toString() << "\n";
|
out << "allowed_ip=" << ip.toString() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = uapiErrno(uapiCommand(message));
|
int err = uapiErrno(uapiCommand(message));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
logger.error() << "Peer configuration failed:" << strerror(err);
|
logger.error() << "Peer configuration failed:" << strerror(err);
|
||||||
@@ -222,13 +215,6 @@ bool WireguardUtilsMacos::deletePeer(const InterfaceConfig& config) {
|
|||||||
QByteArray publicKey =
|
QByteArray publicKey =
|
||||||
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
||||||
|
|
||||||
// Clear exclustion 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString message;
|
QString message;
|
||||||
QTextStream out(&message);
|
QTextStream out(&message);
|
||||||
out << "set=1\n";
|
out << "set=1\n";
|
||||||
|
|||||||
@@ -185,12 +185,6 @@ bool WireguardUtilsWindows::updatePeer(const InterfaceConfig& config) {
|
|||||||
out << "allowed_ip=" << ip.toString() << "\n";
|
out << "allowed_ip=" << ip.toString() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude the server address, except for multihop exit servers.
|
|
||||||
if (m_routeMonitor && config.m_hopType != InterfaceConfig::MultiHopExit) {
|
|
||||||
m_routeMonitor->addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
|
||||||
m_routeMonitor->addExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString reply = m_tunnel.uapiCommand(message);
|
QString reply = m_tunnel.uapiCommand(message);
|
||||||
logger.debug() << "DATA:" << reply;
|
logger.debug() << "DATA:" << reply;
|
||||||
return true;
|
return true;
|
||||||
@@ -200,12 +194,6 @@ bool WireguardUtilsWindows::deletePeer(const InterfaceConfig& config) {
|
|||||||
QByteArray publicKey =
|
QByteArray publicKey =
|
||||||
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
||||||
|
|
||||||
// Clear exclustion routes for this peer.
|
|
||||||
if (m_routeMonitor && config.m_hopType != InterfaceConfig::MultiHopExit) {
|
|
||||||
m_routeMonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
|
||||||
m_routeMonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the windows firewall for this peer.
|
// Disable the windows firewall for this peer.
|
||||||
m_firewall->disablePeerTraffic(config.m_serverPublicKey);
|
m_firewall->disablePeerTraffic(config.m_serverPublicKey);
|
||||||
|
|
||||||
|
|||||||
+28
-40
@@ -146,9 +146,6 @@ void VpnConnection::wireTunnelSignals(Tunnel* tunnel, bool isActive)
|
|||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
connect(tunnel, &Tunnel::bytesChanged, this, &VpnConnection::onBytesChanged);
|
connect(tunnel, &Tunnel::bytesChanged, this, &VpnConnection::onBytesChanged);
|
||||||
// Staging tunnel deliberately skips this wire: applying KS while the old
|
|
||||||
// primary is still serving would clobber its allow-rules. onTunnelActivated
|
|
||||||
// invokes applyFirewall manually after the make-before-break swap.
|
|
||||||
connect(tunnel, &Tunnel::addressesUpdated,
|
connect(tunnel, &Tunnel::addressesUpdated,
|
||||||
m_trafficGuard.data(), &VpnTrafficGuard::applyFirewall);
|
m_trafficGuard.data(), &VpnTrafficGuard::applyFirewall);
|
||||||
}
|
}
|
||||||
@@ -197,14 +194,14 @@ void VpnConnection::connectToVpn(const QString &serverId, DockerContainer contai
|
|||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
if (m_active) {
|
if (m_active) {
|
||||||
const QString oldIfname = m_active->ifname();
|
const QString oldIfname = m_active->ifname();
|
||||||
m_active->deactivate();
|
m_trafficGuard->tearDown(m_active);
|
||||||
delete m_active;
|
delete m_active;
|
||||||
m_active = nullptr;
|
m_active = nullptr;
|
||||||
releaseIfname(oldIfname);
|
releaseIfname(oldIfname);
|
||||||
}
|
}
|
||||||
if (m_vpnProtocol) {
|
if (m_vpnProtocol) {
|
||||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||||
m_trafficGuard->teardown();
|
m_trafficGuard->flushAll();
|
||||||
m_vpnProtocol->stop();
|
m_vpnProtocol->stop();
|
||||||
m_vpnProtocol.reset();
|
m_vpnProtocol.reset();
|
||||||
}
|
}
|
||||||
@@ -223,7 +220,7 @@ void VpnConnection::connectToVpn(const QString &serverId, DockerContainer contai
|
|||||||
wireTunnelSignals(m_active, /*isActive=*/true);
|
wireTunnelSignals(m_active, /*isActive=*/true);
|
||||||
wireDaemonReconnectSignals();
|
wireDaemonReconnectSignals();
|
||||||
m_trafficGuard->setConfig(config);
|
m_trafficGuard->setConfig(config);
|
||||||
m_active->prepare();
|
m_trafficGuard->bringUp(m_active);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,8 +473,7 @@ void VpnConnection::disconnectFromVpn()
|
|||||||
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
if (m_staging) {
|
if (m_staging) {
|
||||||
m_trafficGuard->revokeEndpoint(m_staging->remoteAddress());
|
m_trafficGuard->tearDown(m_staging);
|
||||||
m_staging->deactivate();
|
|
||||||
releaseIfname(m_staging->ifname());
|
releaseIfname(m_staging->ifname());
|
||||||
delete m_staging;
|
delete m_staging;
|
||||||
m_staging = nullptr;
|
m_staging = nullptr;
|
||||||
@@ -485,9 +481,8 @@ void VpnConnection::disconnectFromVpn()
|
|||||||
|
|
||||||
if (m_active) {
|
if (m_active) {
|
||||||
setConnectionState(Vpn::ConnectionState::Disconnecting);
|
setConnectionState(Vpn::ConnectionState::Disconnecting);
|
||||||
m_trafficGuard->teardown();
|
m_trafficGuard->tearDown(m_active);
|
||||||
m_trafficGuard->revokeEndpoint(m_remoteAddress);
|
m_trafficGuard->flushAll();
|
||||||
m_active->deactivate();
|
|
||||||
releaseIfname(m_active->ifname());
|
releaseIfname(m_active->ifname());
|
||||||
delete m_active;
|
delete m_active;
|
||||||
m_active = nullptr;
|
m_active = nullptr;
|
||||||
@@ -515,7 +510,7 @@ void VpnConnection::disconnectFromVpn()
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
m_trafficGuard->teardown();
|
m_trafficGuard->flushAll();
|
||||||
#endif
|
#endif
|
||||||
m_vpnProtocol->stop();
|
m_vpnProtocol->stop();
|
||||||
|
|
||||||
@@ -549,31 +544,19 @@ void VpnConnection::startTunnelSwitch(DockerContainer container,
|
|||||||
wireTunnelSignals(m_staging, /*isActive=*/false);
|
wireTunnelSignals(m_staging, /*isActive=*/false);
|
||||||
|
|
||||||
setConnectionState(Vpn::ConnectionState::Switching);
|
setConnectionState(Vpn::ConnectionState::Switching);
|
||||||
m_staging->prepare();
|
m_trafficGuard->bringUp(m_staging);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnConnection::onTunnelPrepared()
|
void VpnConnection::onTunnelPrepared()
|
||||||
{
|
{
|
||||||
Tunnel* tunnel = qobject_cast<Tunnel*>(sender());
|
Tunnel* tunnel = qobject_cast<Tunnel*>(sender());
|
||||||
if (!tunnel) return;
|
if (!tunnel) return;
|
||||||
tunnel->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VpnConnection::onTunnelActivated()
|
if (tunnel == m_staging && m_active) {
|
||||||
{
|
const QString oldIfname = m_active->ifname();
|
||||||
Tunnel* tunnel = qobject_cast<Tunnel*>(sender());
|
m_trafficGuard->swap(m_active, m_staging);
|
||||||
if (!tunnel) return;
|
delete m_active;
|
||||||
|
releaseIfname(oldIfname);
|
||||||
if (tunnel == m_staging) {
|
|
||||||
// Make-before-break gate passed: new tunnel is primary, old still allowed by KS.
|
|
||||||
if (m_active) {
|
|
||||||
const QString oldRemote = m_active->remoteAddress();
|
|
||||||
const QString oldIfname = m_active->ifname();
|
|
||||||
m_active->deactivate();
|
|
||||||
delete m_active;
|
|
||||||
releaseIfname(oldIfname);
|
|
||||||
m_trafficGuard->revokeEndpoint(oldRemote);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_active = m_staging;
|
m_active = m_staging;
|
||||||
m_staging = nullptr;
|
m_staging = nullptr;
|
||||||
@@ -583,17 +566,23 @@ void VpnConnection::onTunnelActivated()
|
|||||||
m_vpnConfiguration = m_active->config();
|
m_vpnConfiguration = m_active->config();
|
||||||
m_remoteAddress = m_active->remoteAddress();
|
m_remoteAddress = m_active->remoteAddress();
|
||||||
m_trafficGuard->setConfig(m_vpnConfiguration);
|
m_trafficGuard->setConfig(m_vpnConfiguration);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_trafficGuard->commit(tunnel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnConnection::onTunnelActivated()
|
||||||
|
{
|
||||||
|
Tunnel* tunnel = qobject_cast<Tunnel*>(sender());
|
||||||
|
if (!tunnel) return;
|
||||||
|
|
||||||
|
if (tunnel == m_active) {
|
||||||
|
setConnectionState(Vpn::ConnectionState::Connected);
|
||||||
if (auto proto = m_active->protocol()) {
|
if (auto proto = m_active->protocol()) {
|
||||||
m_trafficGuard->applyFirewall(proto->vpnGateway(),
|
m_trafficGuard->applyFirewall(proto->vpnGateway(),
|
||||||
proto->vpnLocalAddress());
|
proto->vpnLocalAddress());
|
||||||
}
|
}
|
||||||
setConnectionState(Vpn::ConnectionState::Connected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tunnel == m_active) {
|
|
||||||
setConnectionState(Vpn::ConnectionState::Connected);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +592,7 @@ void VpnConnection::onTunnelFailed(amnezia::ErrorCode error)
|
|||||||
if (!tunnel) return;
|
if (!tunnel) return;
|
||||||
|
|
||||||
if (tunnel == m_staging) {
|
if (tunnel == m_staging) {
|
||||||
m_trafficGuard->revokeEndpoint(m_staging->remoteAddress());
|
m_trafficGuard->release(m_staging);
|
||||||
m_staging->deactivate();
|
m_staging->deactivate();
|
||||||
releaseIfname(m_staging->ifname());
|
releaseIfname(m_staging->ifname());
|
||||||
m_staging->deleteLater();
|
m_staging->deleteLater();
|
||||||
@@ -614,9 +603,8 @@ void VpnConnection::onTunnelFailed(amnezia::ErrorCode error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tunnel == m_active) {
|
if (tunnel == m_active) {
|
||||||
m_trafficGuard->teardown();
|
m_trafficGuard->tearDown(m_active);
|
||||||
m_trafficGuard->revokeEndpoint(m_remoteAddress);
|
m_trafficGuard->flushAll();
|
||||||
m_active->deactivate();
|
|
||||||
releaseIfname(m_active->ifname());
|
releaseIfname(m_active->ifname());
|
||||||
m_active->deleteLater();
|
m_active->deleteLater();
|
||||||
m_active = nullptr;
|
m_active = nullptr;
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ class IpcInterface
|
|||||||
SLOT( int routeAddList(const QString &gw, const QStringList &ips) );
|
SLOT( int routeAddList(const QString &gw, const QStringList &ips) );
|
||||||
SLOT( bool clearSavedRoutes() );
|
SLOT( bool clearSavedRoutes() );
|
||||||
SLOT( bool routeDeleteList(const QString &gw, const QStringList &ip) );
|
SLOT( bool routeDeleteList(const QString &gw, const QStringList &ip) );
|
||||||
|
SLOT( bool addExclusionRoute(const QString &addr) );
|
||||||
|
SLOT( bool delExclusionRoute(const QString &addr) );
|
||||||
|
SLOT( bool addAllowedIp(const QString &ifname, const QString &prefix) );
|
||||||
|
SLOT( bool delAllowedIp(const QString &ifname, const QString &prefix) );
|
||||||
|
SLOT( bool setTunnelResolvers(const QString &ifname, const QStringList &resolvers) );
|
||||||
|
SLOT( bool restoreTunnelResolvers() );
|
||||||
SLOT( bool flushDns() );
|
SLOT( bool flushDns() );
|
||||||
SLOT( void resetIpStack() );
|
SLOT( void resetIpStack() );
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
#include "killswitch.h"
|
#include "killswitch.h"
|
||||||
#include "xray.h"
|
#include "xray.h"
|
||||||
|
|
||||||
|
#include "../client/daemon/daemon.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include "tapcontroller_win.h"
|
#include "tapcontroller_win.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -91,6 +93,36 @@ bool IpcServer::routeDeleteList(const QString &gw, const QStringList &ips)
|
|||||||
return Router::routeDeleteList(gw, ips);
|
return Router::routeDeleteList(gw, ips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IpcServer::addExclusionRoute(const QString &addr)
|
||||||
|
{
|
||||||
|
return Daemon::instance() && Daemon::instance()->addExclusionRoute(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IpcServer::delExclusionRoute(const QString &addr)
|
||||||
|
{
|
||||||
|
return Daemon::instance() && Daemon::instance()->delExclusionRoute(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IpcServer::addAllowedIp(const QString &ifname, const QString &prefix)
|
||||||
|
{
|
||||||
|
return Daemon::instance() && Daemon::instance()->addAllowedIp(ifname, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IpcServer::delAllowedIp(const QString &ifname, const QString &prefix)
|
||||||
|
{
|
||||||
|
return Daemon::instance() && Daemon::instance()->delAllowedIp(ifname, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IpcServer::setTunnelResolvers(const QString &ifname, const QStringList &resolvers)
|
||||||
|
{
|
||||||
|
return Daemon::instance() && Daemon::instance()->setTunnelResolvers(ifname, resolvers);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IpcServer::restoreTunnelResolvers()
|
||||||
|
{
|
||||||
|
return Daemon::instance() && Daemon::instance()->restoreTunnelResolvers();
|
||||||
|
}
|
||||||
|
|
||||||
bool IpcServer::flushDns()
|
bool IpcServer::flushDns()
|
||||||
{
|
{
|
||||||
#ifdef MZ_DEBUG
|
#ifdef MZ_DEBUG
|
||||||
|
|||||||
@@ -17,11 +17,18 @@ class IpcServer : public IpcInterfaceSource
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit IpcServer(QObject *parent = nullptr);
|
explicit IpcServer(QObject *parent = nullptr);
|
||||||
|
|
||||||
virtual int createPrivilegedProcess() override;
|
virtual int createPrivilegedProcess() override;
|
||||||
|
|
||||||
virtual int routeAddList(const QString &gw, const QStringList &ips) override;
|
virtual int routeAddList(const QString &gw, const QStringList &ips) override;
|
||||||
virtual bool clearSavedRoutes() override;
|
virtual bool clearSavedRoutes() override;
|
||||||
virtual bool routeDeleteList(const QString &gw, const QStringList &ips) override;
|
virtual bool routeDeleteList(const QString &gw, const QStringList &ips) override;
|
||||||
|
virtual bool addExclusionRoute(const QString &addr) override;
|
||||||
|
virtual bool delExclusionRoute(const QString &addr) override;
|
||||||
|
virtual bool addAllowedIp(const QString &ifname, const QString &prefix) override;
|
||||||
|
virtual bool delAllowedIp(const QString &ifname, const QString &prefix) override;
|
||||||
|
virtual bool setTunnelResolvers(const QString &ifname, const QStringList &resolvers) override;
|
||||||
|
virtual bool restoreTunnelResolvers() override;
|
||||||
virtual bool flushDns() override;
|
virtual bool flushDns() override;
|
||||||
virtual void resetIpStack() override;
|
virtual void resetIpStack() override;
|
||||||
virtual bool checkAndInstallDriver() override;
|
virtual bool checkAndInstallDriver() override;
|
||||||
|
|||||||
@@ -56,14 +56,20 @@ LocalServer::LocalServer(QObject *parent) : QObject(parent),
|
|||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// Signal handling for a proper shutdown.
|
// Signal handling for a proper shutdown.
|
||||||
QObject::connect(qApp, &QCoreApplication::aboutToQuit,
|
QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]() {
|
||||||
[]() { LinuxDaemon::instance()->deactivate(); });
|
LinuxDaemon::instance()->deactivate();
|
||||||
|
m_ipcServer.restoreTunnelResolvers();
|
||||||
|
m_ipcServer.disableKillSwitch();
|
||||||
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
// Signal handling for a proper shutdown.
|
// Signal handling for a proper shutdown.
|
||||||
QObject::connect(qApp, &QCoreApplication::aboutToQuit,
|
QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]() {
|
||||||
[]() { MacOSDaemon::instance()->deactivate(); });
|
MacOSDaemon::instance()->deactivate();
|
||||||
|
m_ipcServer.restoreTunnelResolvers();
|
||||||
|
m_ipcServer.disableKillSwitch();
|
||||||
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|||||||
Reference in New Issue
Block a user