refactor: TrafficGuard owns xray DNS and uplink routes

This commit is contained in:
cd-amn
2026-06-08 13:41:02 +00:00
parent bff3e228fc
commit 54d28862f3
6 changed files with 80 additions and 49 deletions
-19
View File
@@ -39,12 +39,6 @@ XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent) :
m_tunName = QStringLiteral("tun2");
#endif
}
const QString primaryDns = configuration.value(amnezia::configKey::dns1).toString();
m_dnsServers.push_back(QHostAddress(primaryDns));
if (primaryDns != amnezia::protocols::dns::amneziaDnsIp) {
const QString secondaryDns = configuration.value(amnezia::configKey::dns2).toString();
m_dnsServers.push_back(QHostAddress(secondaryDns));
}
QJsonObject xrayConfiguration = configuration.value(ProtocolUtils::key_proto_config_data(Proto::Xray)).toObject();
if (xrayConfiguration.isEmpty()) {
@@ -133,10 +127,6 @@ void XrayProtocol::stop()
m_phase = Phase::Stopping;
IpcClient::withInterface([this](QSharedPointer<IpcInterfaceReplica> iface) {
auto restoreResolvers = iface->restoreResolvers();
if (!restoreResolvers.waitForFinished() || !restoreResolvers.returnValue())
qWarning() << "Failed to restore resolvers";
auto deleteTun = iface->deleteTun(m_tunName);
if (!deleteTun.waitForFinished() || !deleteTun.returnValue())
qWarning() << "Failed to delete tun";
@@ -282,21 +272,12 @@ ErrorCode XrayProtocol::setupRouting()
{
return IpcClient::withInterface(
[this](QSharedPointer<IpcInterfaceReplica> iface) -> ErrorCode {
#ifdef Q_OS_WIN
const int inetAdapterIndex = NetworkUtilities::AdapterIndexTo(QHostAddress(m_remoteAddress));
#endif
auto createTun = iface->createTun(m_tunName, amnezia::protocols::xray::defaultLocalAddr);
if (!createTun.waitForFinished() || !createTun.returnValue()) {
qCritical() << "Failed to assign IP address for TUN";
return ErrorCode::InternalError;
}
auto updateResolvers = iface->updateResolvers(m_tunName, m_dnsServers);
if (!updateResolvers.waitForFinished() || !updateResolvers.returnValue()) {
qCritical() << "Failed to set DNS resolvers for TUN";
return ErrorCode::InternalError;
}
emit tunnelAddressesUpdated(m_vpnGateway, m_vpnLocalAddress);
return ErrorCode::NoError;
},
-1
View File
@@ -34,7 +34,6 @@ private:
QJsonObject m_xrayConfig;
amnezia::RouteMode m_routeMode;
QList<QHostAddress> m_dnsServers;
QString m_remoteAddress;
QString m_socksUser;
+48 -2
View File
@@ -13,6 +13,7 @@
#endif
#include "core/utils/networkUtilities.h"
#include "core/utils/constants/protocolConstants.h"
#include "core/tunnel.h"
#include "mozilla/localsocketcontroller.h"
@@ -352,11 +353,40 @@ void VpnTrafficGuard::applyPolicy(Tunnel* tunnel)
{
if (!tunnel) return;
#ifdef AMNEZIA_DESKTOP
const QString ifname = tunnel->ifname();
if (VpnProtocol::isXrayBased(tunnel->container())) {
const QJsonObject cfg = tunnel->config();
const QString primary = cfg.value(amnezia::configKey::dns1).toString();
const QString secondary = cfg.value(amnezia::configKey::dns2).toString();
QList<QHostAddress> dns;
if (!primary.isEmpty()) dns.append(QHostAddress(primary));
if (!secondary.isEmpty() && secondary != primary) dns.append(QHostAddress(secondary));
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
auto updateRes = iface->updateResolvers(ifname, dns);
if (!updateRes.waitForFinished() || !updateRes.returnValue()) {
qWarning() << "VpnTrafficGuard::applyPolicy: updateResolvers failed for" << ifname;
}
#ifdef Q_OS_MAC
const auto gw = NetworkUtilities::getGatewayAndIface();
const QString uplinkIface = gw.second.name();
const QString uplinkGateway = gw.first;
if (!uplinkIface.isEmpty() && !uplinkGateway.isEmpty()) {
auto add = iface->xrayAddUplinkRoutes(uplinkIface, uplinkGateway);
if (!add.waitForFinished() || !add.returnValue()) {
qWarning() << "VpnTrafficGuard::applyPolicy: xrayAddUplinkRoutes failed on" << uplinkIface;
}
}
#endif
});
return;
}
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) {
@@ -379,10 +409,26 @@ void VpnTrafficGuard::revokePolicy(Tunnel* tunnel)
{
if (!tunnel) return;
#ifdef AMNEZIA_DESKTOP
const QString ifname = tunnel->ifname();
if (VpnProtocol::isXrayBased(tunnel->container())) {
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
iface->restoreResolvers();
#ifdef Q_OS_MAC
const auto gw = NetworkUtilities::getGatewayAndIface();
const QString uplinkIface = gw.second.name();
const QString uplinkGateway = gw.first;
if (!uplinkIface.isEmpty()) {
iface->xrayRemoveUplinkRoutes(uplinkIface, uplinkGateway);
}
#endif
});
return;
}
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) {
+2
View File
@@ -47,6 +47,8 @@ class IpcInterface
SLOT(bool xrayStart(const QString &ifname, const QString &config));
SLOT(bool xrayStop(const QString &ifname));
SLOT(bool xrayAddUplinkRoutes(const QString &uplinkIface, const QString &uplinkGateway));
SLOT(bool xrayRemoveUplinkRoutes(const QString &uplinkIface, const QString &uplinkGateway));
SLOT( bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) );
SLOT( bool stopNetworkCheck() );
+28 -23
View File
@@ -437,17 +437,6 @@ bool IpcServer::xrayStart(const QString& ifname, const QString& cfg)
}
}
#ifdef Q_OS_MAC
const auto gatewayAndIface = NetworkUtilities::getGatewayAndIface();
w.uplinkGateway = gatewayAndIface.first;
w.uplinkIface = gatewayAndIface.second.name();
if (!w.uplinkIface.isEmpty() && !w.uplinkGateway.isEmpty()) {
if (!RouterMac::Instance().routeAddXray(w.uplinkIface, w.uplinkGateway)) {
qWarning() << "[xray] failed to install xray routes on" << w.uplinkIface;
}
}
#endif
const QJsonObject startCmd{{QStringLiteral("op"), QStringLiteral("start")},
{QStringLiteral("config"), cfg}};
w.process->write(QJsonDocument(startCmd).toJson(QJsonDocument::Compact) + '\n');
@@ -457,7 +446,6 @@ bool IpcServer::xrayStart(const QString& ifname, const QString& cfg)
w.startResult = false;
loop.exec();
// Re-fetch: the worker entry may have been removed during the loop (e.g. process finished).
auto it = m_xrayWorkers.find(ifname);
if (it == m_xrayWorkers.end()) {
return false;
@@ -466,11 +454,6 @@ bool IpcServer::xrayStart(const QString& ifname, const QString& cfg)
const bool ok = it->startResult;
if (!ok) {
#ifdef Q_OS_MAC
if (!it->uplinkIface.isEmpty()) {
RouterMac::Instance().routeDeleteXray(it->uplinkIface, it->uplinkGateway);
}
#endif
m_xrayWorkers.remove(ifname);
}
@@ -499,12 +482,34 @@ bool IpcServer::xrayStop(const QString& ifname)
}
}
#ifdef Q_OS_MAC
if (!it->uplinkIface.isEmpty()) {
RouterMac::Instance().routeDeleteXray(it->uplinkIface, it->uplinkGateway);
}
#endif
m_xrayWorkers.remove(ifname);
return true;
}
bool IpcServer::xrayAddUplinkRoutes(const QString& uplinkIface, const QString& uplinkGateway)
{
#ifdef Q_OS_MAC
if (uplinkIface.isEmpty() || uplinkGateway.isEmpty()) {
return false;
}
return RouterMac::Instance().routeAddXray(uplinkIface, uplinkGateway);
#else
Q_UNUSED(uplinkIface)
Q_UNUSED(uplinkGateway)
return true;
#endif
}
bool IpcServer::xrayRemoveUplinkRoutes(const QString& uplinkIface, const QString& uplinkGateway)
{
#ifdef Q_OS_MAC
if (uplinkIface.isEmpty()) {
return false;
}
return RouterMac::Instance().routeDeleteXray(uplinkIface, uplinkGateway);
#else
Q_UNUSED(uplinkIface)
Q_UNUSED(uplinkGateway)
return true;
#endif
}
+2 -4
View File
@@ -57,6 +57,8 @@ public:
virtual bool restoreResolvers() override;
virtual bool xrayStart(const QString& ifname, const QString& cfg) override;
virtual bool xrayStop(const QString& ifname) override;
virtual bool xrayAddUplinkRoutes(const QString& uplinkIface, const QString& uplinkGateway) override;
virtual bool xrayRemoveUplinkRoutes(const QString& uplinkIface, const QString& uplinkGateway) override;
virtual bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) override;
virtual bool stopNetworkCheck() override;
@@ -83,10 +85,6 @@ private:
QByteArray stdoutBuf;
QPointer<QEventLoop> startLoop;
bool startResult = false;
#ifdef Q_OS_MAC
QString uplinkIface;
QString uplinkGateway;
#endif
};
QHash<QString, XrayWorker> m_xrayWorkers;