Killswitch and Splittunnel for MacOS IPSec

This commit is contained in:
Mykola Baibuz 2024-09-02 13:58:33 -07:00
parent f0e66e4ecf
commit a144d495ee
4 changed files with 184 additions and 173 deletions

View file

@ -29,6 +29,13 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/route.h> #include <net/route.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <libproc.h>
#include <netdb.h>
#include <netinet/in.h>
#include <semaphore.h>
#include <unistd.h>
#endif #endif
#include <QHostAddress> #include <QHostAddress>
@ -460,3 +467,112 @@ QString NetworkUtilities::getGatewayAndIface()
return gateway; return gateway;
#endif #endif
} }
#if defined(Q_OS_MAC)
QString NetworkUtilities::ipAddressByInterfaceName(const QString &interfaceName)
{
struct ifaddrs *ifaddr, *ifa;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1)
{
return "";
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
{
continue;
}
int family = ifa->ifa_addr->sa_family;
QString iname = QString::fromStdString(ifa->ifa_name);
if (family == AF_INET && iname == interfaceName)
{
int s = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);
if (s != 0)
{
continue;
}
return QString::fromStdString(host);
}
}
freeifaddrs(ifaddr);
return "";
}
QString NetworkUtilities::lastConnectedNetworkInterfaceName()
{
QString ifname("");
struct ifaddrs * interfaces = NULL;
struct ifaddrs * temp_addr = NULL;
if( getifaddrs(&interfaces) == 0 )
{
//Loop through linked list of interfaces
temp_addr = interfaces;
while( temp_addr != NULL )
{
if( temp_addr->ifa_addr->sa_family == AF_INET )
{
QString tname = temp_addr->ifa_name;
if( tname.startsWith("utun") )
ifname = tname;
else if( tname.startsWith("ipsec") )
ifname = tname;
else if( tname.startsWith("ppp") )
ifname = tname;
}
temp_addr = temp_addr->ifa_next;
}
freeifaddrs(interfaces);
}
return ifname;
}
QString execCmd(const QString &cmd)
{
char buffer[1024];
QString result = "";
FILE* pipe = popen(cmd.toStdString().c_str(), "r");
if (!pipe) return "";
while (!feof(pipe))
{
if (fgets(buffer, 1024, pipe) != NULL)
{
result += buffer;
}
}
pclose(pipe);
return result;
}
QStringList NetworkUtilities::getListOfDnsNetworkServiceEntries()
{
QStringList result;
QString command = "echo 'list' | scutil | grep /Network/Service | grep DNS";
QString cmdOutput = execCmd(command).trimmed();
// qDebug() << "Raw result: " << cmdOutput;
QStringList lines = cmdOutput.split('\n');
for (QString line : lines)
{
if (line.contains("="))
{
QString entry = line.mid(line.indexOf("=")+1).trimmed();
result.append(entry);
}
}
return result;
}
#endif

View file

@ -18,19 +18,24 @@ public:
static QString getGatewayAndIface(); static QString getGatewayAndIface();
// Returns the Interface Index that could Route to dst // Returns the Interface Index that could Route to dst
static int AdapterIndexTo(const QHostAddress& dst); static int AdapterIndexTo(const QHostAddress& dst);
static QRegularExpression ipAddressRegExp(); static QRegularExpression ipAddressRegExp();
static QRegularExpression ipAddressPortRegExp(); static QRegularExpression ipAddressPortRegExp();
static QRegExp ipAddressWithSubnetRegExp(); static QRegExp ipAddressWithSubnetRegExp();
static QRegExp ipNetwork24RegExp(); static QRegExp ipNetwork24RegExp();
static QRegExp ipPortRegExp(); static QRegExp ipPortRegExp();
static QRegExp domainRegExp(); static QRegExp domainRegExp();
static QString netMaskFromIpWithSubnet(const QString ip); static QString netMaskFromIpWithSubnet(const QString ip);
static QString ipAddressFromIpWithSubnet(const QString ip); static QString ipAddressFromIpWithSubnet(const QString ip);
static QStringList summarizeRoutes(const QStringList &ips, const QString cidr); static QStringList summarizeRoutes(const QStringList &ips, const QString cidr);
#if defined(Q_OS_MAC)
static QString ipAddressByInterfaceName(const QString &interfaceName);
static QString lastConnectedNetworkInterfaceName();
static QStringList getListOfDnsNetworkServiceEntries();
#endif
}; };
#endif // NETWORKUTILITIES_H #endif // NETWORKUTILITIES_H

View file

@ -20,7 +20,6 @@ public:
bool connect_to_vpn(const QString & vpn_name); bool connect_to_vpn(const QString & vpn_name);
bool disconnect_vpn(); bool disconnect_vpn();
void closeWindscribeActiveConnection(); void closeWindscribeActiveConnection();
ErrorCode start() override; ErrorCode start() override;
void stop() override; void stop() override;
@ -30,31 +29,15 @@ private slots:
void handleNotificationImpl(int status); void handleNotificationImpl(int status);
private: private:
enum {STATE_DISCONNECTED, STATE_START_CONNECT, STATE_START_DISCONNECTING, STATE_CONNECTED, STATE_DISCONNECTING_AUTH_ERROR, STATE_DISCONNECTING_ANY_ERROR};
int state_;
bool bConnected_;
mutable QRecursiveMutex mutex_; mutable QRecursiveMutex mutex_;
void *notificationId_; void *notificationId_;
bool isStateConnectingAfterClick_;
bool isDisconnectClicked_;
QString overrideDnsIp_;
QJsonObject m_config; QJsonObject m_config;
QJsonObject m_ikev2_config;
static constexpr int STATISTICS_UPDATE_PERIOD = 1000;
QTimer statisticsTimer_;
QString ipsecAdapterName_; QString ipsecAdapterName_;
int prevConnectionStatus_;
bool isPrevConnectionStatusInitialized_;
// True if startConnect() method was called and NEVPNManager emitted notification NEVPNStatusConnecting.
// False otherwise.
bool isConnectingStateReachedAfterStartingConnection_; bool isConnectingStateReachedAfterStartingConnection_;
void handleNotification(void *notification); void handleNotification(void *notification);
bool isFailedAuthError(QMap<time_t, QString> &logs); bool isFailedAuthError(QMap<time_t, QString> &logs);
bool isSocketError(QMap<time_t, QString> &logs); bool isSocketError(QMap<time_t, QString> &logs);

View file

@ -1,7 +1,6 @@
#include "ikev2_vpn_protocol_mac.h" #include "ikev2_vpn_protocol_mac.h"
#include <core/networkUtilities.h>
#include <SystemConfiguration/SCSchemaDefinitions.h> #include <SystemConfiguration/SCSchemaDefinitions.h>
#include <SystemConfiguration/SCNetwork.h> #include <SystemConfiguration/SCNetwork.h>
#include <SystemConfiguration/SCNetworkConnection.h> #include <SystemConfiguration/SCNetworkConnection.h>
@ -20,16 +19,15 @@
#include <net/if.h> #include <net/if.h>
#include <net/route.h> #include <net/route.h>
static NSString * const IKEv1ServiceName = @"AmneziaVPN";
static NSString * const IKEv2ServiceName = @"AmneziaVPN IKEv2"; static NSString * const IKEv2ServiceName = @"AmneziaVPN IKEv2";
static Ikev2Protocol* self = nullptr; static Ikev2Protocol* self = nullptr;
Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent) : Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent) :
VpnProtocol(configuration, parent) VpnProtocol(configuration, parent)
{ {
qDebug() << "IpsecProtocol::IpsecProtocol()"; qDebug() << "IpsecProtocol::IpsecProtocol()";
m_routeGateway = NetworkUtilities::getGatewayAndIface();
self = this; self = this;
readIkev2Configuration(configuration); readIkev2Configuration(configuration);
} }
@ -38,6 +36,7 @@ Ikev2Protocol::~Ikev2Protocol()
{ {
qDebug() << "IpsecProtocol::~IpsecProtocol()"; qDebug() << "IpsecProtocol::~IpsecProtocol()";
disconnect_vpn(); disconnect_vpn();
QThread::msleep(1000);
Ikev2Protocol::stop(); Ikev2Protocol::stop();
} }
@ -47,12 +46,13 @@ void Ikev2Protocol::stop()
qDebug() << "IpsecProtocol::stop()"; qDebug() << "IpsecProtocol::stop()";
} }
void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration) void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration)
{ {
qDebug() << "IpsecProtocol::readIkev2Configuration"; qDebug() << "IpsecProtocol::readIkev2Configuration";
QJsonObject ikev2_data = configuration.value(ProtocolProps::key_proto_config_data(Proto::Ikev2)).toObject(); m_config = configuration;
m_config = QJsonDocument::fromJson(ikev2_data.value(config_key::config).toString().toUtf8()).object(); auto ikev2_data = m_config.value(ProtocolProps::key_proto_config_data(Proto::Ikev2)).toObject();
m_ikev2_config = QJsonDocument::fromJson(ikev2_data.value(config_key::config).toString().toUtf8()).object();
} }
CFDataRef CreatePersistentRefForIdentity(SecIdentityRef identity) CFDataRef CreatePersistentRefForIdentity(SecIdentityRef identity)
@ -75,16 +75,16 @@ CFDataRef CreatePersistentRefForIdentity(SecIdentityRef identity)
NSData *searchKeychainCopyMatching(const char *certName) NSData *searchKeychainCopyMatching(const char *certName)
{ {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:(__bridge id)kSecClassCertificate forKey:(__bridge id)kSecClass]; [dict setObject:(__bridge id)kSecClassCertificate forKey:(__bridge id)kSecClass];
[dict setObject:[NSString stringWithUTF8String:certName] forKey:(__bridge id)kSecAttrLabel]; [dict setObject:[NSString stringWithUTF8String:certName] forKey:(__bridge id)kSecAttrLabel];
[dict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; [dict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
[dict setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef]; [dict setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef];
CFTypeRef result = NULL; CFTypeRef result = NULL;
SecItemCopyMatching((__bridge CFDictionaryRef)dict, &result); SecItemCopyMatching((__bridge CFDictionaryRef)dict, &result);
return (NSData *)result; return (NSData *)result;
} }
ErrorCode Ikev2Protocol::start() ErrorCode Ikev2Protocol::start()
@ -122,11 +122,11 @@ ErrorCode Ikev2Protocol::start()
EVP_PKEY *pkey; EVP_PKEY *pkey;
X509 *cert; X509 *cert;
BIO_write(p12, QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8()), BIO_write(p12, QByteArray::fromBase64(m_ikev2_config[config_key::cert].toString().toUtf8()),
QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8()).size()); QByteArray::fromBase64(m_ikev2_config[config_key::cert].toString().toUtf8()).size());
PKCS12 *pkcs12 = d2i_PKCS12_bio(p12, NULL); PKCS12 *pkcs12 = d2i_PKCS12_bio(p12, NULL);
PKCS12_parse(pkcs12, m_config[config_key::password].toString().toStdString().c_str(), &pkey, &cert, &certstack); PKCS12_parse(pkcs12, m_ikev2_config[config_key::password].toString().toStdString().c_str(), &pkey, &cert, &certstack);
// We output everything in PEM // We output everything in PEM
obio = BIO_new(BIO_s_mem()); obio = BIO_new(BIO_s_mem());
@ -152,7 +152,7 @@ ErrorCode Ikev2Protocol::start()
output = [NSData dataWithBytes: bptr->data length: bptr->length]; output = [NSData dataWithBytes: bptr->data length: bptr->length];
NSData *PKCS12Data = [[NSData alloc] initWithBase64EncodedString:m_config[config_key::cert].toString().toNSString() options:0] ; NSData *PKCS12Data = [[NSData alloc] initWithBase64EncodedString:m_ikev2_config[config_key::cert].toString().toNSString() options:0];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus ret = SecPKCS12Import( OSStatus ret = SecPKCS12Import(
@ -168,12 +168,12 @@ ErrorCode Ikev2Protocol::start()
SecIdentityRef identity = (__bridge SecIdentityRef)(firstItem[(__bridge id)kSecImportItemIdentity]); SecIdentityRef identity = (__bridge SecIdentityRef)(firstItem[(__bridge id)kSecImportItemIdentity]);
NEVPNProtocolIKEv2 *protocol = [[NEVPNProtocolIKEv2 alloc] init]; NEVPNProtocolIKEv2 *protocol = [[NEVPNProtocolIKEv2 alloc] init];
protocol.serverAddress = m_config.value(amnezia::config_key::hostName).toString().toNSString(); protocol.serverAddress = m_ikev2_config.value(amnezia::config_key::hostName).toString().toNSString();
protocol.certificateType = NEVPNIKEv2CertificateTypeRSA; protocol.certificateType = NEVPNIKEv2CertificateTypeRSA;
protocol.remoteIdentifier = m_config.value(amnezia::config_key::hostName).toString().toNSString(); protocol.remoteIdentifier = m_ikev2_config.value(amnezia::config_key::hostName).toString().toNSString();
protocol.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate; protocol.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate;
protocol.identityReference = searchKeychainCopyMatching(m_config.value(amnezia::config_key::userName).toString().toLocal8Bit().data()); protocol.identityReference = searchKeychainCopyMatching(m_ikev2_config.value(amnezia::config_key::userName).toString().toLocal8Bit().data());
protocol.useExtendedAuthentication = NO; protocol.useExtendedAuthentication = NO;
protocol.enablePFS = YES; protocol.enablePFS = YES;
@ -187,15 +187,17 @@ ErrorCode Ikev2Protocol::start()
protocol.childSecurityAssociationParameters.diffieHellmanGroup = NEVPNIKEv2DiffieHellmanGroup19; protocol.childSecurityAssociationParameters.diffieHellmanGroup = NEVPNIKEv2DiffieHellmanGroup19;
protocol.childSecurityAssociationParameters.integrityAlgorithm = NEVPNIKEv2IntegrityAlgorithmSHA256; protocol.childSecurityAssociationParameters.integrityAlgorithm = NEVPNIKEv2IntegrityAlgorithmSHA256;
protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440; protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440;
[manager setEnabled:YES]; [manager setEnabled:YES];
[manager setProtocolConfiguration:(protocol)]; [manager setProtocolConfiguration:(protocol)];
[manager setOnDemandEnabled:NO]; [manager setOnDemandEnabled:NO];
[manager setLocalizedDescription:@"Amnezia VPN"]; [manager setLocalizedDescription:@"Amnezia VPN"];
#ifdef QT_DEBUG
NSString *strProtocol = [NSString stringWithFormat:@"{Protocol: %@", protocol]; NSString *strProtocol = [NSString stringWithFormat:@"{Protocol: %@", protocol];
qDebug() << QString::fromNSString(strProtocol); qDebug() << QString::fromNSString(strProtocol);
#endif
// do config stuff // do config stuff
[manager saveToPreferencesWithCompletionHandler:^(NSError *err) [manager saveToPreferencesWithCompletionHandler:^(NSError *err)
{ {
@ -253,7 +255,6 @@ ErrorCode Ikev2Protocol::start()
} }
}]; }];
// waitConditionLocal.wait(&mutexLocal);
mutexLocal.unlock(); mutexLocal.unlock();
setConnectionState(Vpn::ConnectionState::Connected); setConnectionState(Vpn::ConnectionState::Connected);
@ -261,24 +262,22 @@ ErrorCode Ikev2Protocol::start()
} }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Ikev2Protocol::create_new_vpn(const QString & vpn_name, bool Ikev2Protocol::create_new_vpn(const QString & vpn_name,
const QString & serv_addr){ const QString & serv_addr) {
qDebug() << "Ikev2Protocol::create_new_vpn()"; qDebug() << "Ikev2Protocol::create_new_vpn()";
return true; return true;
} }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Ikev2Protocol::delete_vpn_connection(const QString &vpn_name){ bool Ikev2Protocol::delete_vpn_connection(const QString &vpn_name) {
return false; return false;
} }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Ikev2Protocol::connect_to_vpn(const QString & vpn_name){ bool Ikev2Protocol::connect_to_vpn(const QString & vpn_name) {
return false; return false;
} }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Ikev2Protocol::disconnect_vpn() { bool Ikev2Protocol::disconnect_vpn() {
QMutexLocker locker(&mutex_);
NEVPNManager *manager = [NEVPNManager sharedManager]; NEVPNManager *manager = [NEVPNManager sharedManager];
// #713: If user had started connecting to IKev2 on Mac and quickly started after this connecting to Wireguard // #713: If user had started connecting to IKev2 on Mac and quickly started after this connecting to Wireguard
@ -303,17 +302,12 @@ bool Ikev2Protocol::disconnect_vpn() {
void Ikev2Protocol::closeWindscribeActiveConnection() void Ikev2Protocol::closeWindscribeActiveConnection()
{ {
static QWaitCondition waitCondition;
static QMutex mutex;
mutex.lock();
NEVPNManager *manager = [NEVPNManager sharedManager]; NEVPNManager *manager = [NEVPNManager sharedManager];
if (manager) if (manager)
{ {
[manager loadFromPreferencesWithCompletionHandler:^(NSError *err) [manager loadFromPreferencesWithCompletionHandler:^(NSError *err)
{ {
mutex.lock();
if (!err) if (!err)
{ {
NEVPNConnection * connection = [manager connection]; NEVPNConnection * connection = [manager connection];
@ -326,12 +320,9 @@ void Ikev2Protocol::closeWindscribeActiveConnection()
} }
} }
} }
waitCondition.wakeAll();
mutex.unlock();
}]; }];
} }
waitCondition.wait(&mutex);
mutex.unlock();
} }
void Ikev2Protocol::handleNotificationImpl(int status) void Ikev2Protocol::handleNotificationImpl(int status)
@ -349,44 +340,44 @@ void Ikev2Protocol::handleNotificationImpl(int status)
else if (status == NEVPNStatusDisconnected) else if (status == NEVPNStatusDisconnected)
{ {
qDebug() << "Connection status changed: NEVPNStatusDisconnected"; qDebug() << "Connection status changed: NEVPNStatusDisconnected";
IpcClient::Interface()->disableKillSwitch();
setConnectionState(Vpn::ConnectionState::Disconnected); setConnectionState(Vpn::ConnectionState::Disconnected);
if (state_ == STATE_DISCONNECTING_ANY_ERROR) [[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection];
{
[[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection];
// state_ = STATE_DISCONNECTED;
// emit error(IKEV_FAILED_TO_CONNECT);
setConnectionState(Vpn::ConnectionState::Disconnected);
}
else if (state_ != STATE_DISCONNECTED)
{
[[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection];
// state_ = STATE_DISCONNECTED;
setConnectionState(Vpn::ConnectionState::Disconnected);
}
} }
else if (status == NEVPNStatusConnecting) else if (status == NEVPNStatusConnecting)
{ {
isConnectingStateReachedAfterStartingConnection_ = true; isConnectingStateReachedAfterStartingConnection_ = true;
setConnectionState(Vpn::ConnectionState::Connecting);
qDebug() << "Connection status changed: NEVPNStatusConnecting"; qDebug() << "Connection status changed: NEVPNStatusConnecting";
} }
else if (status == NEVPNStatusConnected) else if (status == NEVPNStatusConnected)
{ {
if (!overrideDnsIp_.isEmpty()) { qDebug() << "Connection status changed: NEVPNStatusConnected";
if (!setCustomDns(overrideDnsIp_)) {
qDebug() << "Failed to set custom DNS ip for ikev2"; QString ipsecAdapterName_ = NetworkUtilities::lastConnectedNetworkInterfaceName();
} m_vpnLocalAddress = NetworkUtilities::ipAddressByInterfaceName(ipsecAdapterName_);
m_vpnGateway = m_vpnLocalAddress;
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_config.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_config.value(config_key::dns2).toString()));
IpcClient::Interface()->updateResolvers(ipsecAdapterName_, dnsAddr);
if (QVariant(m_config.value(config_key::killSwitchOption).toString()).toBool()) {
qDebug() << "enable killswitch";
IpcClient::Interface()->enableKillSwitch(m_config, 0);
} }
qDebug() << "Connection status changed: NEVPNStatusConnected"; if (m_config.value(amnezia::config_key::splitTunnelType).toInt() == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_config.value(amnezia::config_key::hostName).toString());
}
setConnectionState(Vpn::ConnectionState::Connected); setConnectionState(Vpn::ConnectionState::Connected);
// note: route gateway not used for ikev2 in AdapterGatewayInfo
// AdapterGatewayInfo cai;
// ipsecAdapterName_ = NetworkUtils_mac::lastConnectedNetworkInterfaceName();
// cai.setAdapterName(ipsecAdapterName_);
// cai.setAdapterIp(NetworkUtils_mac::ipAddressByInterfaceName(ipsecAdapterName_));
//cai.setDnsServers(NetworkUtils_mac::getDnsServersForInterface(ipsecAdapterName_));
} }
else if (status == NEVPNStatusReasserting) else if (status == NEVPNStatusReasserting)
{ {
@ -397,33 +388,8 @@ void Ikev2Protocol::handleNotificationImpl(int status)
{ {
qDebug() << "Connection status changed: NEVPNStatusDisconnecting"; qDebug() << "Connection status changed: NEVPNStatusDisconnecting";
setConnectionState(Vpn::ConnectionState::Disconnecting); setConnectionState(Vpn::ConnectionState::Disconnecting);
/* if (state_ == STATE_START_CONNECT)
{
QMap<time_t, QString> logs = networkExtensionLog_.collectNext();
for (QMap<time_t, QString>::iterator it = logs.begin(); it != logs.end(); ++it)
{
qDebug() << it.value();
}
if (isSocketError(logs))
{
state_ = STATE_DISCONNECTING_ANY_ERROR;
}
else
{
if (isFailedAuthError(logs))
{
state_ = STATE_DISCONNECTING_AUTH_ERROR;
}
else
{
state_ = STATE_DISCONNECTING_ANY_ERROR;
}
}
}*/
} }
prevConnectionStatus_ = status;
isPrevConnectionStatusInitialized_ = true;
} }
@ -435,62 +401,3 @@ void Ikev2Protocol::handleNotification(void *notification)
QMetaObject::invokeMethod(this, "handleNotificationImpl", Q_ARG(int, (int)connection.status)); QMetaObject::invokeMethod(this, "handleNotificationImpl", Q_ARG(int, (int)connection.status));
} }
bool Ikev2Protocol::isFailedAuthError(QMap<time_t, QString> &logs)
{
for (QMap<time_t, QString>::iterator it = logs.begin(); it != logs.end(); ++it)
{
if (it.value().contains("Failed", Qt::CaseInsensitive) && it.value().contains("IKE", Qt::CaseInsensitive) && it.value().contains("Auth", Qt::CaseInsensitive))
{
if (!(it.value().contains("Failed", Qt::CaseInsensitive) && it.value().contains("IKEv2 socket", Qt::CaseInsensitive)))
{
return true;
}
}
}
return false;
}
bool Ikev2Protocol::isSocketError(QMap<time_t, QString> &logs)
{
for (QMap<time_t, QString>::iterator it = logs.begin(); it != logs.end(); ++it)
{
if (it.value().contains("Failed", Qt::CaseInsensitive) && it.value().contains("initialize", Qt::CaseInsensitive) && it.value().contains("socket", Qt::CaseInsensitive))
{
return true;
}
}
return false;
}
bool Ikev2Protocol::setCustomDns(const QString &overrideDnsIpAddress)
{
// get list of entries of interest
// QStringList networkServices = NetworkUtils_mac::getListOfDnsNetworkServiceEntries();
// filter list to only ikev2 entries
QStringList dnsNetworkServices;
// for (const QString &service : networkServices)
// if (MacUtils::dynamicStoreEntryHasKey(service, "ConfirmedServiceID"))
// dnsNetworkServices.append(service);
qDebug() << "Applying custom 'while connected' DNS change to network services: " << dnsNetworkServices;
if (dnsNetworkServices.isEmpty()) {
qDebug() << "No network services to configure 'while connected' DNS";
return false;
}
// change DNS on each entry
bool successAll = true;
for (const QString &service : dnsNetworkServices) {
// if (!helper_->setDnsOfDynamicStoreEntry(overrideDnsIpAddress, service)) {
// successAll = false;
// qDebug() << "Failed to set network service DNS: " << service;
// break;
// }
}
return successAll;
}