mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-30 23:31:14 +03:00
Compare commits
5 Commits
bugfix/lin
...
feat/add-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06ea7b9316 | ||
|
|
498607cd16 | ||
|
|
cd03e11dde | ||
|
|
1f9f71f244 | ||
|
|
d230043ead |
@@ -13,6 +13,7 @@
|
||||
#include <QNetworkInterface>
|
||||
#include "qendian.h"
|
||||
#include <QSettings>
|
||||
#pragma comment(lib, "iphlpapi.lib")
|
||||
#endif
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <arpa/inet.h>
|
||||
@@ -23,6 +24,28 @@
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusReply>
|
||||
#include <QDBusArgument>
|
||||
#include <QDBusObjectPath>
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QNetworkInterface>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include "platforms/linux/daemon/dbustypeslinux.h"
|
||||
|
||||
constexpr const char* DBUS_RESOLVE_SERVICE = "org.freedesktop.resolve1";
|
||||
constexpr const char* DBUS_RESOLVE_PATH = "/org/freedesktop/resolve1";
|
||||
constexpr const char* DBUS_RESOLVE_MANAGER = "org.freedesktop.resolve1.Manager";
|
||||
constexpr const char* DBUS_PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
|
||||
#endif
|
||||
#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
@@ -30,10 +53,17 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/route.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QRegularExpression>
|
||||
#endif
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QHostInfo>
|
||||
#include <QPair>
|
||||
#include "logger.h"
|
||||
|
||||
QRegularExpression NetworkUtilities::ipAddressRegExp()
|
||||
{
|
||||
@@ -277,7 +307,7 @@ QString NetworkUtilities::getGatewayAndIface()
|
||||
free(pAdapterAddresses);
|
||||
return result;
|
||||
#endif
|
||||
#ifdef Q_OS_LINUX
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
constexpr int BUFFER_SIZE = 100;
|
||||
int received_bytes = 0, msg_len = 0, route_attribute_len = 0;
|
||||
int sock = -1, msgseq = 0;
|
||||
@@ -475,3 +505,310 @@ QString NetworkUtilities::getGatewayAndIface()
|
||||
return gateway;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
namespace {
|
||||
struct LinkInfo {
|
||||
int ifindex;
|
||||
bool defaultRoute;
|
||||
quint32 routeMetric;
|
||||
QStringList dnsServers;
|
||||
|
||||
bool operator<(const LinkInfo& other) const {
|
||||
// Sort by defaultRoute first (true comes first), then by routeMetric (lower is better)
|
||||
if (defaultRoute != other.defaultRoute) {
|
||||
return defaultRoute > other.defaultRoute;
|
||||
}
|
||||
return routeMetric < other.routeMetric;
|
||||
}
|
||||
};
|
||||
|
||||
QStringList extractDnsFromDbusArgument(const QDBusArgument& arg) {
|
||||
QStringList dnsServers;
|
||||
QDBusArgument dnsArg = arg;
|
||||
QList<DnsResolver> resolverList = qdbus_cast<QList<DnsResolver>>(dnsArg);
|
||||
|
||||
for (const auto& resolver : resolverList) {
|
||||
if (resolver.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
const QString dnsStr = resolver.toString();
|
||||
if (NetworkUtilities::checkIPv4Format(dnsStr) && !dnsServers.contains(dnsStr)) {
|
||||
dnsServers.append(dnsStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dnsServers;
|
||||
}
|
||||
|
||||
QList<LinkInfo> getDnsFromInterfaces(const QDBusConnection& bus) {
|
||||
QList<LinkInfo> links;
|
||||
|
||||
// Get all network interfaces
|
||||
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
|
||||
|
||||
for (const QNetworkInterface& iface : interfaces) {
|
||||
int ifindex = iface.index();
|
||||
if (ifindex <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Call GetLink to get the link object path
|
||||
QDBusMessage getLinkMsg = QDBusMessage::createMethodCall(
|
||||
DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH, DBUS_RESOLVE_MANAGER, "GetLink");
|
||||
getLinkMsg << ifindex;
|
||||
|
||||
QDBusReply<QDBusObjectPath> linkReply = bus.call(getLinkMsg);
|
||||
if (!linkReply.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString linkPath = linkReply.value().path();
|
||||
|
||||
// Get properties from the link object
|
||||
QDBusMessage getPropMsg = QDBusMessage::createMethodCall(
|
||||
DBUS_RESOLVE_SERVICE, linkPath, DBUS_PROPERTY_INTERFACE, "GetAll");
|
||||
getPropMsg << QString("org.freedesktop.resolve1.Link");
|
||||
|
||||
QDBusReply<QVariantMap> propReply = bus.call(getPropMsg);
|
||||
if (!propReply.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariantMap properties = propReply.value();
|
||||
|
||||
// Check if DefaultRoute is true
|
||||
bool defaultRoute = properties.value("DefaultRoute").toBool();
|
||||
|
||||
// Get RouteMetric (default to maximum if not available)
|
||||
quint32 routeMetric = std::numeric_limits<quint32>::max();
|
||||
if (properties.contains("RouteMetric")) {
|
||||
routeMetric = properties.value("RouteMetric").toUInt();
|
||||
}
|
||||
|
||||
// Get DNS servers - use Get method directly for DNS property
|
||||
QDBusMessage getDnsMsg = QDBusMessage::createMethodCall(
|
||||
DBUS_RESOLVE_SERVICE, linkPath, DBUS_PROPERTY_INTERFACE, "Get");
|
||||
getDnsMsg << QString("org.freedesktop.resolve1.Link");
|
||||
getDnsMsg << QString("DNS");
|
||||
|
||||
QDBusReply<QVariant> dnsReply = bus.call(getDnsMsg);
|
||||
if (!dnsReply.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariant dnsVariant = dnsReply.value();
|
||||
QStringList dnsServers;
|
||||
if (dnsVariant.canConvert<QDBusArgument>()) {
|
||||
QDBusArgument dnsArg = qvariant_cast<QDBusArgument>(dnsVariant);
|
||||
dnsServers = extractDnsFromDbusArgument(dnsArg);
|
||||
}
|
||||
|
||||
if (!dnsServers.isEmpty()) {
|
||||
LinkInfo info;
|
||||
info.ifindex = ifindex;
|
||||
info.defaultRoute = defaultRoute;
|
||||
info.routeMetric = routeMetric;
|
||||
info.dnsServers = dnsServers;
|
||||
links.append(info);
|
||||
}
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QPair<QString, QString> NetworkUtilities::getSystemDnsAddress()
|
||||
{
|
||||
QPair<QString, QString> result;
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
// Try systemd-resolved via D-Bus first
|
||||
QDBusConnection bus = QDBusConnection::systemBus();
|
||||
if (bus.isConnected()) {
|
||||
// Try to get DNS from Resolve DNS property using org.freedesktop.DBus.Properties
|
||||
QDBusMessage message = QDBusMessage::createMethodCall(
|
||||
DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH, DBUS_PROPERTY_INTERFACE, "Get");
|
||||
message << QString(DBUS_RESOLVE_MANAGER);
|
||||
message << QString("DNS");
|
||||
|
||||
QDBusReply<QVariant> dnsReply = bus.call(message);
|
||||
|
||||
if (dnsReply.isValid()) {
|
||||
QDBusArgument dnsArg = qvariant_cast<QDBusArgument>(dnsReply.value());
|
||||
QList<DnsResolver> resolverList = qdbus_cast<QList<DnsResolver>>(dnsArg);
|
||||
|
||||
QStringList dnsServers;
|
||||
for (const auto& resolver : resolverList) {
|
||||
if (resolver.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
QString dnsStr = resolver.toString();
|
||||
if (checkIPv4Format(dnsStr) && !dnsServers.contains(dnsStr)) {
|
||||
dnsServers.append(dnsStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dnsServers.isEmpty()) {
|
||||
result.first = dnsServers.first();
|
||||
if (dnsServers.size() > 1) {
|
||||
result.second = dnsServers.at(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// If no global DNS, try to get DNS from interfaces
|
||||
QList<LinkInfo> links = getDnsFromInterfaces(bus);
|
||||
if (!links.isEmpty()) {
|
||||
// Sort by priority: DefaultRoute first, then by RouteMetric
|
||||
std::sort(links.begin(), links.end());
|
||||
|
||||
// Get DNS from the highest priority interface
|
||||
const LinkInfo& bestLink = links.first();
|
||||
result.first = bestLink.dnsServers.first();
|
||||
if (bestLink.dnsServers.size() > 1) {
|
||||
result.second = bestLink.dnsServers.at(1);
|
||||
}
|
||||
qDebug() << "Got DNS from interface" << bestLink.ifindex
|
||||
<< "DefaultRoute:" << bestLink.defaultRoute
|
||||
<< "RouteMetric:" << bestLink.routeMetric;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to /etc/resolv.conf
|
||||
QFile resolvConf("/etc/resolv.conf");
|
||||
if (resolvConf.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream in(&resolvConf);
|
||||
QStringList dnsServers;
|
||||
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine().trimmed();
|
||||
if (line.startsWith("nameserver")) {
|
||||
QStringList parts = line.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
|
||||
if (parts.size() >= 2) {
|
||||
QString dns = parts.at(1);
|
||||
if (checkIPv4Format(dns)) {
|
||||
dnsServers.append(dns);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dnsServers.isEmpty()) {
|
||||
result.first = dnsServers.first();
|
||||
if (dnsServers.size() > 1) {
|
||||
result.second = dnsServers.at(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Failed to get system DNS on Linux";
|
||||
return result; // Return empty pair
|
||||
|
||||
#elif defined(Q_OS_WIN)
|
||||
// Use GetAdaptersAddresses to get DNS servers
|
||||
ULONG bufferSize = 0;
|
||||
DWORD ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize);
|
||||
|
||||
if (ret == ERROR_BUFFER_OVERFLOW) {
|
||||
PIP_ADAPTER_ADDRESSES adapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufferSize);
|
||||
if (adapterAddresses) {
|
||||
ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, adapterAddresses, &bufferSize);
|
||||
|
||||
if (ret == NO_ERROR) {
|
||||
PIP_ADAPTER_ADDRESSES currentAdapter = adapterAddresses;
|
||||
QStringList dnsServers;
|
||||
|
||||
while (currentAdapter) {
|
||||
// Check if adapter is active and has IP addresses
|
||||
if (currentAdapter->OperStatus == IfOperStatusUp &&
|
||||
currentAdapter->FirstUnicastAddress != nullptr) {
|
||||
|
||||
PIP_ADAPTER_DNS_SERVER_ADDRESS dnsServer = currentAdapter->FirstDnsServerAddress;
|
||||
while (dnsServer) {
|
||||
if (dnsServer->Address.lpSockaddr->sa_family == AF_INET) {
|
||||
struct sockaddr_in* sa_in = (struct sockaddr_in*)dnsServer->Address.lpSockaddr;
|
||||
char ipstr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &sa_in->sin_addr, ipstr, INET_ADDRSTRLEN);
|
||||
QString dns = QString::fromLatin1(ipstr);
|
||||
if (checkIPv4Format(dns) && !dnsServers.contains(dns)) {
|
||||
dnsServers.append(dns);
|
||||
}
|
||||
}
|
||||
dnsServer = dnsServer->Next;
|
||||
}
|
||||
}
|
||||
|
||||
currentAdapter = currentAdapter->Next;
|
||||
}
|
||||
|
||||
if (!dnsServers.isEmpty()) {
|
||||
result.first = dnsServers.first();
|
||||
if (dnsServers.size() > 1) {
|
||||
result.second = dnsServers.at(1);
|
||||
}
|
||||
qDebug() << "Got system DNS from Windows:" << result.first << result.second;
|
||||
free(adapterAddresses);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
free(adapterAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Failed to get system DNS on Windows";
|
||||
return result; // Return empty pair
|
||||
|
||||
#elif defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
|
||||
// Use SCDynamicStore to get DNS from system configuration
|
||||
SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("amneziavpn"), nullptr, nullptr);
|
||||
if (store) {
|
||||
CFDictionaryRef dnsDict = (CFDictionaryRef)SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/DNS"));
|
||||
|
||||
if (dnsDict) {
|
||||
CFArrayRef dnsServersArray = (CFArrayRef)CFDictionaryGetValue(dnsDict, CFSTR("ServerAddresses"));
|
||||
|
||||
if (dnsServersArray && CFArrayGetCount(dnsServersArray) > 0) {
|
||||
QStringList dnsServers;
|
||||
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(dnsServersArray); i++) {
|
||||
CFStringRef dnsString = (CFStringRef)CFArrayGetValueAtIndex(dnsServersArray, i);
|
||||
if (dnsString) {
|
||||
char buffer[256];
|
||||
if (CFStringGetCString(dnsString, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {
|
||||
QString dns = QString::fromLatin1(buffer);
|
||||
if (checkIPv4Format(dns)) {
|
||||
dnsServers.append(dns);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dnsServers.isEmpty()) {
|
||||
result.first = dnsServers.first();
|
||||
if (dnsServers.size() > 1) {
|
||||
result.second = dnsServers.at(1);
|
||||
}
|
||||
qDebug() << "Got system DNS from macOS:" << result.first << result.second;
|
||||
CFRelease(dnsDict);
|
||||
CFRelease(store);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(dnsDict);
|
||||
}
|
||||
|
||||
CFRelease(store);
|
||||
}
|
||||
|
||||
qWarning() << "Failed to get system DNS on macOS";
|
||||
return result; // Return empty pair
|
||||
|
||||
#else
|
||||
qWarning() << "System DNS reading not implemented for this platform";
|
||||
return result; // Return empty pair
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <QString>
|
||||
#include <QHostAddress>
|
||||
#include <QNetworkReply>
|
||||
#include <QPair>
|
||||
|
||||
|
||||
class NetworkUtilities : public QObject
|
||||
@@ -31,6 +32,9 @@ public:
|
||||
static QString netMaskFromIpWithSubnet(const QString ip);
|
||||
static QString ipAddressFromIpWithSubnet(const QString ip);
|
||||
static QStringList summarizeRoutes(const QStringList &ips, const QString cidr);
|
||||
|
||||
// Returns pair of (primary DNS, secondary DNS) or empty strings on error
|
||||
static QPair<QString, QString> getSystemDnsAddress();
|
||||
};
|
||||
|
||||
#endif // NETWORKUTILITIES_H
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <QDBusArgument>
|
||||
#include <QHostAddress>
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <QtEndian>
|
||||
|
||||
/* D-Bus metatype for marshalling arguments to the SetLinkDNS method */
|
||||
class DnsResolver : public QHostAddress {
|
||||
@@ -25,12 +26,8 @@ class DnsResolver : public QHostAddress {
|
||||
args << AF_INET6;
|
||||
args << QByteArray::fromRawData((const char*)&addrv6, sizeof(addrv6));
|
||||
} else {
|
||||
quint32 addrv4 = ip.toIPv4Address();
|
||||
QByteArray data(4, 0);
|
||||
data[0] = (addrv4 >> 24) & 0xff;
|
||||
data[1] = (addrv4 >> 16) & 0xff;
|
||||
data[2] = (addrv4 >> 8) & 0xff;
|
||||
data[3] = (addrv4 >> 0) & 0xff;
|
||||
quint32 addrv4 = qToBigEndian(ip.toIPv4Address());
|
||||
QByteArray data = QByteArray::fromRawData((const char*)&addrv4, sizeof(addrv4));
|
||||
args << AF_INET;
|
||||
args << data;
|
||||
}
|
||||
@@ -46,12 +43,8 @@ class DnsResolver : public QHostAddress {
|
||||
args.endStructure();
|
||||
if (family == AF_INET6) {
|
||||
ip.setAddress(data.constData());
|
||||
} else if (data.count() >= 4) {
|
||||
quint32 addrv4 = 0;
|
||||
addrv4 |= (data[0] << 24);
|
||||
addrv4 |= (data[1] << 16);
|
||||
addrv4 |= (data[2] << 8);
|
||||
addrv4 |= (data[3] << 0);
|
||||
} else if (data.size() >= 4) {
|
||||
const quint32 addrv4 = qFromBigEndian<quint32>(data.constData());
|
||||
ip.setAddress(addrv4);
|
||||
}
|
||||
return args;
|
||||
|
||||
@@ -145,6 +145,15 @@ public:
|
||||
setValue("Conf/useAmneziaDns", enabled);
|
||||
}
|
||||
|
||||
bool useSystemDnsAddress() const
|
||||
{
|
||||
return value("Conf/useSystemDnsAddress", false).toBool();
|
||||
}
|
||||
void setUseSystemDnsAddress(bool enabled)
|
||||
{
|
||||
setValue("Conf/useSystemDnsAddress", enabled);
|
||||
}
|
||||
|
||||
QString primaryDns() const;
|
||||
QString secondaryDns() const;
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ void ConnectionController::openConnection()
|
||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||
|
||||
auto dns = m_serversModel->getDnsPair(serverIndex);
|
||||
|
||||
// Check if DNS retrieval failed (empty pair means system DNS retrieval failed)
|
||||
if (dns.first.isEmpty() && dns.second.isEmpty()) {
|
||||
emit connectionErrorOccurred(ErrorCode::InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container);
|
||||
emit connectToVpn(serverIndex, credentials, container, vpnConfiguration);
|
||||
|
||||
@@ -79,6 +79,17 @@ bool SettingsController::isAmneziaDnsEnabled()
|
||||
return m_settings->useAmneziaDns();
|
||||
}
|
||||
|
||||
bool SettingsController::isUseSystemDnsAddressEnabled()
|
||||
{
|
||||
return m_settings->useSystemDnsAddress();
|
||||
}
|
||||
|
||||
void SettingsController::setUseSystemDnsAddress(bool enable)
|
||||
{
|
||||
m_settings->setUseSystemDnsAddress(enable);
|
||||
emit useSystemDnsAddressChanged(enable);
|
||||
}
|
||||
|
||||
QString SettingsController::getPrimaryDns()
|
||||
{
|
||||
return m_settings->primaryDns();
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
Q_PROPERTY(bool isNotificationPermissionGranted READ isNotificationPermissionGranted NOTIFY onNotificationStateChanged)
|
||||
Q_PROPERTY(bool isKillSwitchEnabled READ isKillSwitchEnabled WRITE toggleKillSwitch NOTIFY killSwitchEnabledChanged)
|
||||
Q_PROPERTY(bool strictKillSwitchEnabled READ isStrictKillSwitchEnabled WRITE toggleStrictKillSwitch NOTIFY strictKillSwitchEnabledChanged)
|
||||
Q_PROPERTY(bool useSystemDnsAddressEnabled READ isUseSystemDnsAddressEnabled WRITE setUseSystemDnsAddress NOTIFY useSystemDnsAddressChanged)
|
||||
|
||||
Q_PROPERTY(bool isDevModeEnabled READ isDevModeEnabled NOTIFY devModeEnabled)
|
||||
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
|
||||
@@ -41,6 +42,9 @@ public slots:
|
||||
void toggleAmneziaDns(bool enable);
|
||||
bool isAmneziaDnsEnabled();
|
||||
|
||||
bool isUseSystemDnsAddressEnabled();
|
||||
void setUseSystemDnsAddress(bool enable);
|
||||
|
||||
QString getPrimaryDns();
|
||||
void setPrimaryDns(const QString &dns);
|
||||
|
||||
@@ -126,6 +130,8 @@ signals:
|
||||
|
||||
void amneziaDnsToggled(bool enable);
|
||||
|
||||
void useSystemDnsAddressChanged(bool enabled);
|
||||
|
||||
void loggingDisableByWatcher();
|
||||
|
||||
void onNotificationStateChanged();
|
||||
|
||||
@@ -621,6 +621,26 @@ QPair<QString, QString> ServersModel::getDnsPair(int serverIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if system DNS should be used
|
||||
if (m_settings->useSystemDnsAddress() && apiUtils::isPremiumServer(server)) {
|
||||
auto systemDns = NetworkUtilities::getSystemDnsAddress();
|
||||
bool hasPrimary = !systemDns.first.isEmpty() && NetworkUtilities::checkIPv4Format(systemDns.first);
|
||||
bool hasSecondary = !systemDns.second.isEmpty() && NetworkUtilities::checkIPv4Format(systemDns.second);
|
||||
|
||||
if (hasPrimary || hasSecondary) {
|
||||
if (hasPrimary) {
|
||||
dns.first = systemDns.first;
|
||||
}
|
||||
if (hasSecondary) {
|
||||
dns.second = systemDns.second;
|
||||
}
|
||||
qDebug() << "VpnConfigurator::getDnsForConfig using system DNS:" << dns.first << dns.second;
|
||||
} else {
|
||||
qWarning() << "Failed to get system DNS for premium config, connection will fail";
|
||||
}
|
||||
return dns;
|
||||
}
|
||||
|
||||
dns.first = server.value(config_key::dns1).toString();
|
||||
dns.second = server.value(config_key::dns2).toString();
|
||||
|
||||
|
||||
@@ -75,6 +75,29 @@ PageType {
|
||||
|
||||
DividerType {}
|
||||
|
||||
SwitcherType {
|
||||
id: useSystemDnsSwitch
|
||||
|
||||
visible: ServersModel.processedServerIsPremium
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 16
|
||||
|
||||
text: qsTr("Use system DNS")
|
||||
descriptionText: qsTr("Use system DNS servers")
|
||||
|
||||
checked: SettingsController.useSystemDnsAddressEnabled
|
||||
onToggled: function() {
|
||||
if (checked !== SettingsController.useSystemDnsAddressEnabled) {
|
||||
SettingsController.setUseSystemDnsAddress(checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: ServersModel.processedServerIsPremium
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: dnsServersButton
|
||||
|
||||
|
||||
Reference in New Issue
Block a user