mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-19 02:00:45 +07:00
refactor: TrafficGuard owns xray DNS and uplink routes
This commit is contained in:
@@ -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;
|
||||
},
|
||||
|
||||
@@ -34,7 +34,6 @@ private:
|
||||
|
||||
QJsonObject m_xrayConfig;
|
||||
amnezia::RouteMode m_routeMode;
|
||||
QList<QHostAddress> m_dnsServers;
|
||||
QString m_remoteAddress;
|
||||
|
||||
QString m_socksUser;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user