diff --git a/client/cmake/macos.cmake b/client/cmake/macos.cmake index 7b7cd3812..57c2f0281 100644 --- a/client/cmake/macos.cmake +++ b/client/cmake/macos.cmake @@ -18,17 +18,22 @@ set(LIBS ${LIBS} ${FW_NETWORK_EXTENSION} ) -set_target_properties(${PROJECT} PROPERTIES MACOSX_BUNDLE TRUE) +set_target_properties(${PROJECT} PROPERTIES + MACOSX_BUNDLE TRUE + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/macos/app/AmneziaVPN.entitlements" +) set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) set(HEADERS ${HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/ui/macos_util.h + ${CMAKE_CURRENT_SOURCE_DIR}/protocols/ikev2_vpn_protocol_mac.h ) set(SOURCES ${SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/ui/macos_util.mm + ${CMAKE_CURRENT_SOURCE_DIR}/protocols/ikev2_vpn_protocol_mac.mm ) set(ICON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/images/app.icns) diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index 7647c1664..b7df2ab53 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -294,7 +294,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c) #elif defined(Q_OS_MAC) switch (c) { case DockerContainer::WireGuard: return true; - case DockerContainer::Ipsec: return false; + case DockerContainer::Ipsec: return true; default: return true; } diff --git a/client/core/networkUtilities.cpp b/client/core/networkUtilities.cpp index a5825f0d4..abd2d2abf 100644 --- a/client/core/networkUtilities.cpp +++ b/client/core/networkUtilities.cpp @@ -29,6 +29,13 @@ #include #include #include + #include + #include + #include + #include + #include + #include + #include #endif #include @@ -463,3 +470,112 @@ QString NetworkUtilities::getGatewayAndIface() return gateway; #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 diff --git a/client/core/networkUtilities.h b/client/core/networkUtilities.h index 3057b8528..2c5c7109c 100644 --- a/client/core/networkUtilities.h +++ b/client/core/networkUtilities.h @@ -18,19 +18,24 @@ class NetworkUtilities : public QObject static QString getGatewayAndIface(); // Returns the Interface Index that could Route to dst static int AdapterIndexTo(const QHostAddress& dst); - + static QRegularExpression ipAddressRegExp(); static QRegularExpression ipAddressPortRegExp(); static QRegExp ipAddressWithSubnetRegExp(); static QRegExp ipNetwork24RegExp(); static QRegExp ipPortRegExp(); static QRegExp domainRegExp(); - + static QString netMaskFromIpWithSubnet(const QString ip); static QString ipAddressFromIpWithSubnet(const QString ip); - + 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 diff --git a/client/macos/app/AmneziaVPN.entitlements b/client/macos/app/AmneziaVPN.entitlements new file mode 100644 index 000000000..10636b1b5 --- /dev/null +++ b/client/macos/app/AmneziaVPN.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + + diff --git a/client/protocols/ikev2_vpn_protocol_mac.h b/client/protocols/ikev2_vpn_protocol_mac.h new file mode 100644 index 000000000..b2ef4dcfe --- /dev/null +++ b/client/protocols/ikev2_vpn_protocol_mac.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + + +#include "openvpnprotocol.h" + + +class Ikev2Protocol : public VpnProtocol +{ + Q_OBJECT +public: + explicit Ikev2Protocol(const QJsonObject& configuration, QObject* parent = nullptr); + virtual ~Ikev2Protocol() override; + + void readIkev2Configuration(const QJsonObject &configuration); + bool create_new_vpn(const QString &vpn_name, const QString &serv_addr); + bool delete_vpn_connection(const QString &vpn_name); + bool connect_to_vpn(const QString & vpn_name); + bool disconnect_vpn(); + void closeWindscribeActiveConnection(); + ErrorCode start() override; + void stop() override; + + static QString tunnelName() { return "AmneziaVPN IKEv2"; } + +private slots: + void handleNotificationImpl(int status); + +private: + mutable QRecursiveMutex mutex_; + void *notificationId_; + QJsonObject m_config; + QJsonObject m_ikev2_config; + + QString ipsecAdapterName_; + + bool isConnectingStateReachedAfterStartingConnection_; + + void handleNotification(void *notification); + bool isFailedAuthError(QMap &logs); + bool isSocketError(QMap &logs); + bool setCustomDns(const QString &overrideDnsIpAddress); +}; diff --git a/client/protocols/ikev2_vpn_protocol_mac.mm b/client/protocols/ikev2_vpn_protocol_mac.mm new file mode 100644 index 000000000..a749882b5 --- /dev/null +++ b/client/protocols/ikev2_vpn_protocol_mac.mm @@ -0,0 +1,397 @@ +#include "ikev2_vpn_protocol_mac.h" + +#include +#include +#include +#include +#include +#import +#import +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +static NSString * const IKEv2ServiceName = @"AmneziaVPN IKEv2"; + +static Ikev2Protocol* self = nullptr; + +Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent) : + VpnProtocol(configuration, parent) +{ + qDebug() << "IpsecProtocol::IpsecProtocol()"; + m_routeGateway = NetworkUtilities::getGatewayAndIface(); + self = this; + readIkev2Configuration(configuration); +} + +Ikev2Protocol::~Ikev2Protocol() +{ + qDebug() << "IpsecProtocol::~IpsecProtocol()"; + disconnect_vpn(); + QThread::msleep(1000); + Ikev2Protocol::stop(); +} + +void Ikev2Protocol::stop() +{ + setConnectionState(Vpn::ConnectionState::Disconnected); + qDebug() << "IpsecProtocol::stop()"; +} + +void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration) +{ + qDebug() << "IpsecProtocol::readIkev2Configuration"; + m_config = configuration; + 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) +{ + CFTypeRef persistent_ref = NULL; + const void *keys[] = { kSecReturnPersistentRef, kSecValueRef }; + const void *values[] = { kCFBooleanTrue, identity }; + CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), NULL, NULL); + + if (SecItemCopyMatching(dict, &persistent_ref) != 0) { + SecItemAdd(dict, &persistent_ref); + } + + if (dict) + CFRelease(dict); + + return (CFDataRef)persistent_ref; +} + +NSData *searchKeychainCopyMatching(const char *certName) +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setObject:(__bridge id)kSecClassCertificate forKey:(__bridge id)kSecClass]; + [dict setObject:[NSString stringWithUTF8String:certName] forKey:(__bridge id)kSecAttrLabel]; + [dict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + [dict setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef]; + + CFTypeRef result = NULL; + SecItemCopyMatching((__bridge CFDictionaryRef)dict, &result); + + return (NSData *)result; +} + +ErrorCode Ikev2Protocol::start() +{ + + qDebug() << "IpsecProtocol::start"; + + static QMutex mutexLocal; + mutexLocal.lock(); + + setConnectionState(Vpn::ConnectionState::Disconnected); + NEVPNManager *manager = [NEVPNManager sharedManager]; + + [manager loadFromPreferencesWithCompletionHandler:^(NSError *err) + { + mutexLocal.lock(); + + if (err) + { + qDebug() << "First load vpn preferences failed:" << QString::fromNSString(err.localizedDescription); + setConnectionState(Vpn::ConnectionState::Disconnected); + mutexLocal.unlock(); + } + else + { + + NSData *output = NULL; + + BIO *ibio, *obio = NULL; + BUF_MEM *bptr; + + STACK_OF(X509) *certstack = sk_X509_new_null(); + BIO *p12 = BIO_new(BIO_s_mem()); + + EVP_PKEY *pkey; + X509 *cert; + + BIO_write(p12, QByteArray::fromBase64(m_ikev2_config[config_key::cert].toString().toUtf8()), + QByteArray::fromBase64(m_ikev2_config[config_key::cert].toString().toUtf8()).size()); + + PKCS12 *pkcs12 = d2i_PKCS12_bio(p12, NULL); + PKCS12_parse(pkcs12, m_ikev2_config[config_key::password].toString().toStdString().c_str(), &pkey, &cert, &certstack); + + // We output everything in PEM + obio = BIO_new(BIO_s_mem()); + + // TODO: support protecting the private key with a PEM passphrase + if (pkey) + { + PEM_write_bio_PrivateKey(obio, pkey, NULL, NULL, 0, NULL, NULL); + } + + if (cert) + { + PEM_write_bio_X509(obio, cert); + } + + if (certstack && sk_X509_num(certstack)) + { + for (int i = 0; i < sk_X509_num(certstack); i++) + PEM_write_bio_X509_AUX(obio, sk_X509_value(certstack, i)); + } + + BIO_get_mem_ptr(obio, &bptr); + + output = [NSData dataWithBytes: bptr->data length: bptr->length]; + + NSData *PKCS12Data = [[NSData alloc] initWithBase64EncodedString:m_ikev2_config[config_key::cert].toString().toNSString() options:0]; + + CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); + OSStatus ret = SecPKCS12Import( + (__bridge CFDataRef)output, + (__bridge CFDictionaryRef)@{(id)kSecImportExportPassphrase:@""}, + &items); + + if (ret != errSecSuccess) { + qDebug() << "import err ret " << ret; + } + + NSDictionary *firstItem = [(__bridge_transfer NSArray *)items firstObject]; + SecIdentityRef identity = (__bridge SecIdentityRef)(firstItem[(__bridge id)kSecImportItemIdentity]); + + NEVPNProtocolIKEv2 *protocol = [[NEVPNProtocolIKEv2 alloc] init]; + protocol.serverAddress = m_ikev2_config.value(amnezia::config_key::hostName).toString().toNSString(); + protocol.certificateType = NEVPNIKEv2CertificateTypeRSA; + + protocol.remoteIdentifier = m_ikev2_config.value(amnezia::config_key::hostName).toString().toNSString(); + protocol.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate; + protocol.identityReference = searchKeychainCopyMatching(m_ikev2_config.value(amnezia::config_key::userName).toString().toLocal8Bit().data()); + + protocol.useExtendedAuthentication = NO; + protocol.enablePFS = YES; + + protocol.IKESecurityAssociationParameters.encryptionAlgorithm = NEVPNIKEv2EncryptionAlgorithmAES256; + protocol.IKESecurityAssociationParameters.diffieHellmanGroup = NEVPNIKEv2DiffieHellmanGroup19; + protocol.IKESecurityAssociationParameters.integrityAlgorithm = NEVPNIKEv2IntegrityAlgorithmSHA256; + protocol.IKESecurityAssociationParameters.lifetimeMinutes = 1440; + + protocol.childSecurityAssociationParameters.encryptionAlgorithm = NEVPNIKEv2EncryptionAlgorithmAES256; + protocol.childSecurityAssociationParameters.diffieHellmanGroup = NEVPNIKEv2DiffieHellmanGroup19; + protocol.childSecurityAssociationParameters.integrityAlgorithm = NEVPNIKEv2IntegrityAlgorithmSHA256; + protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440; + + [manager setEnabled:YES]; + [manager setProtocolConfiguration:(protocol)]; + [manager setOnDemandEnabled:NO]; + [manager setLocalizedDescription:@"Amnezia VPN"]; + +#ifdef QT_DEBUG + NSString *strProtocol = [NSString stringWithFormat:@"{Protocol: %@", protocol]; + qDebug() << QString::fromNSString(strProtocol); +#endif + + // do config stuff + [manager saveToPreferencesWithCompletionHandler:^(NSError *err) + { + if (err) + { + qDebug() << "First save vpn preferences failed:" << QString::fromNSString(err.localizedDescription); + setConnectionState(Vpn::ConnectionState::Disconnected); + mutexLocal.unlock(); + } + else + { + // load and save preferences again, otherwise Mac bug (https://forums.developer.apple.com/thread/25928) + [manager loadFromPreferencesWithCompletionHandler:^(NSError *err) + { + if (err) + { + qDebug() << "Second load vpn preferences failed:" << QString::fromNSString(err.localizedDescription); + setConnectionState(Vpn::ConnectionState::Disconnected); + mutexLocal.unlock(); + } + else + { + [manager saveToPreferencesWithCompletionHandler:^(NSError *err) + { + if (err) + { + qDebug() << "Second Save vpn preferences failed:" << QString::fromNSString(err.localizedDescription); + setConnectionState(Vpn::ConnectionState::Disconnected); + mutexLocal.unlock(); + } + else + { + notificationId_ = [[NSNotificationCenter defaultCenter] addObserverForName: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection queue: nil usingBlock: ^ (NSNotification *notification) + { + this->handleNotification(notification); + }]; + + qDebug() << "NEVPNConnection current status:" << (int)manager.connection.status; + + NSError *startError; + [manager.connection startVPNTunnelAndReturnError:&startError]; + if (startError) + { + qDebug() << "Error starting ikev2 connection:" << QString::fromNSString(startError.localizedDescription); + [[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection]; + setConnectionState(Vpn::ConnectionState::Disconnected); + } + mutexLocal.unlock(); + } + }]; + } + }]; + } + }]; + } + }]; + + mutexLocal.unlock(); + + setConnectionState(Vpn::ConnectionState::Connected); + return ErrorCode::NoError; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool Ikev2Protocol::create_new_vpn(const QString & vpn_name, + const QString & serv_addr) { + qDebug() << "Ikev2Protocol::create_new_vpn()"; + return true; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool Ikev2Protocol::delete_vpn_connection(const QString &vpn_name) { + + return false; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool Ikev2Protocol::connect_to_vpn(const QString & vpn_name) { + return false; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool Ikev2Protocol::disconnect_vpn() { + + NEVPNManager *manager = [NEVPNManager sharedManager]; + + // #713: If user had started connecting to IKev2 on Mac and quickly started after this connecting to Wireguard + + // then manager.connection.status doesn't have time to change to NEVPNStatusConnecting + // and remains NEVPNStatusDisconnected as it was before connection tries. + // Then we should check below isConnectingStateReachedAfterStartingConnection_ flag to be sure that connecting started. + // Without this check we will start connecting to the Wireguard when IKEv2 connecting process hasn't finished yet. + if (manager.connection.status == NEVPNStatusDisconnected && isConnectingStateReachedAfterStartingConnection_) + { + [[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection]; + setConnectionState(Vpn::ConnectionState::Disconnected); + } + else + { + [manager.connection stopVPNTunnel]; + } + + return true; +} + + +void Ikev2Protocol::closeWindscribeActiveConnection() +{ + + NEVPNManager *manager = [NEVPNManager sharedManager]; + if (manager) + { + [manager loadFromPreferencesWithCompletionHandler:^(NSError *err) + { + if (!err) + { + NEVPNConnection * connection = [manager connection]; + if (connection.status == NEVPNStatusConnected || connection.status == NEVPNStatusConnecting) + { + if ([manager.localizedDescription isEqualToString:@"Amnezia VPN"] == YES) + { + qDebug() << "Previous IKEv2 connection is active. Stop it."; + [connection stopVPNTunnel]; + } + } + } + }]; + } + +} + +void Ikev2Protocol::handleNotificationImpl(int status) +{ + QMutexLocker locker(&mutex_); + + NEVPNManager *manager = [NEVPNManager sharedManager]; + + if (status == NEVPNStatusInvalid) + { + qDebug() << "Connection status changed: NEVPNStatusInvalid"; + [[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection]; + setConnectionState(Vpn::ConnectionState::Disconnected); + } + else if (status == NEVPNStatusDisconnected) + { + qDebug() << "Connection status changed: NEVPNStatusDisconnected"; + IpcClient::Interface()->disableKillSwitch(); + + setConnectionState(Vpn::ConnectionState::Disconnected); + [[NSNotificationCenter defaultCenter] removeObserver: (id)notificationId_ name: (NSString *)NEVPNStatusDidChangeNotification object: manager.connection]; + + } + else if (status == NEVPNStatusConnecting) + { + isConnectingStateReachedAfterStartingConnection_ = true; + setConnectionState(Vpn::ConnectionState::Connecting); + qDebug() << "Connection status changed: NEVPNStatusConnecting"; + } + else if (status == NEVPNStatusConnected) + { + qDebug() << "Connection status changed: NEVPNStatusConnected"; + + QString ipsecAdapterName_ = NetworkUtilities::lastConnectedNetworkInterfaceName(); + m_vpnLocalAddress = NetworkUtilities::ipAddressByInterfaceName(ipsecAdapterName_); + m_vpnGateway = m_vpnLocalAddress; + + QList 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); + } + + setConnectionState(Vpn::ConnectionState::Connected); + } + else if (status == NEVPNStatusReasserting) + { + qDebug() << "Connection status changed: NEVPNStatusReasserting"; + setConnectionState(Vpn::ConnectionState::Connecting); + } + else if (status == NEVPNStatusDisconnecting) + { + qDebug() << "Connection status changed: NEVPNStatusDisconnecting"; + setConnectionState(Vpn::ConnectionState::Disconnecting); + } + +} + + +void Ikev2Protocol::handleNotification(void *notification) +{ + QMutexLocker locker(&mutex_); + NSNotification *nsNotification = (NSNotification *)notification; + NEVPNConnection *connection = nsNotification.object; + QMetaObject::invokeMethod(this, "handleNotificationImpl", Q_ARG(int, (int)connection.status)); +} + diff --git a/client/protocols/vpnprotocol.cpp b/client/protocols/vpnprotocol.cpp index 40b22dca0..7524b4832 100644 --- a/client/protocols/vpnprotocol.cpp +++ b/client/protocols/vpnprotocol.cpp @@ -17,7 +17,11 @@ #endif #ifdef Q_OS_LINUX -#include "ikev2_vpn_protocol_linux.h" + #include "ikev2_vpn_protocol_linux.h" +#endif + +#ifdef Q_OS_MACX + #include "ikev2_vpn_protocol_mac.h" #endif VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject *parent) @@ -110,9 +114,6 @@ QString VpnProtocol::vpnGateway() const VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject &configuration) { switch (container) { -#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) - case DockerContainer::Ipsec: return new Ikev2Protocol(configuration); -#endif #if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration); case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration); @@ -121,6 +122,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject & case DockerContainer::Awg: return new WireguardProtocol(configuration); case DockerContainer::Xray: return new XrayProtocol(configuration); case DockerContainer::SSXray: return new XrayProtocol(configuration); + case DockerContainer::Ipsec: return new Ikev2Protocol(configuration); #endif default: return nullptr; } diff --git a/deploy/data/macos/pf/amn.200.allowVPN.conf b/deploy/data/macos/pf/amn.200.allowVPN.conf index 6e1b74bc6..fe4f5407c 100644 --- a/deploy/data/macos/pf/amn.200.allowVPN.conf +++ b/deploy/data/macos/pf/amn.200.allowVPN.conf @@ -1,9 +1,11 @@ # Exempt the tunnel interface(s) used by the VPN connection -utunInterfaces = "{ \ - utun0, utun1, utun2, utun3, utun4, utun5, utun6, utun7, utun8, utun9, utun10, \ - utun11, utun12, utun13, utun14, utun15, utun16, utun17, utun18, utun19, utun20, \ - utun21, utun22, utun23, utun24, utun25, utun26, utun27, utun28, utun29, utun30 \ +utunInterfaces = "{ \ + utun0, utun1, utun2, utun3, utun4, utun5, utun6, utun7, utun8, utun9, utun10, \ + utun11, utun12, utun13, utun14, utun15, utun16, utun17, utun18, utun19, utun20, \ + utun21, utun22, utun23, utun24, utun25, utun26, utun27, utun28, utun29, utun30, \ + ipsec0, ipsec1, ipsec2, ipsec3, ipsec4, ipsec5, ipsec6, ipsec7, ipsec8, ipsec9, \ + ipsec10, ipsec11, ipsec12, ipsec13, ipsec14, ipsec15, ipsec16, ipsec17, ipsec18, ipsec19 \ }" pass out on $utunInterfaces flags any no state diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp index 679c34405..aa6ed74f7 100644 --- a/ipc/ipcserver.cpp +++ b/ipc/ipcserver.cpp @@ -6,8 +6,9 @@ #include #include -#include "logger.h" +#include "qjsonarray.h" #include "router.h" +#include "logger.h" #include "../core/networkUtilities.h" #include "../client/protocols/protocols_defs.h"