diff --git a/client/platforms/ios/Log.swift b/client/platforms/ios/Log.swift index f7f48b87..d9512dc6 100644 --- a/client/platforms/ios/Log.swift +++ b/client/platforms/ios/Log.swift @@ -38,7 +38,7 @@ struct Log { init(_ str: String) { self.records = str.split(whereSeparator: \.isNewline) .compactMap { - Record(String($0))! + Record(String($0)) } } diff --git a/client/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift b/client/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift index b7aaf3d8..a648281a 100644 --- a/client/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift +++ b/client/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift @@ -18,40 +18,32 @@ extension PacketTunnelProvider: OpenVPNAdapterDelegate { // send empty string to NEDNSSettings.matchDomains networkSettings?.dnsSettings?.matchDomains = [""] - if splitTunnelType == "1" { + if splitTunnelType == 1 { var ipv4IncludedRoutes = [NEIPv4Route]() - let STSdata = Data(splitTunnelSites!.utf8) - do { - guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return } - for allowedIPString in STSArray { - if let allowedIP = IPAddressRange(from: allowedIPString) { - ipv4IncludedRoutes.append(NEIPv4Route( - destinationAddress: "\(allowedIP.address)", - subnetMask: "\(allowedIP.subnetMask())")) - } + + for allowedIPString in splitTunnelSites { + if let allowedIP = IPAddressRange(from: allowedIPString) { + ipv4IncludedRoutes.append(NEIPv4Route( + destinationAddress: "\(allowedIP.address)", + subnetMask: "\(allowedIP.subnetMask())")) } - } catch { - wg_log(.error, message: "Parse JSONSerialization Error") } + networkSettings?.ipv4Settings?.includedRoutes = ipv4IncludedRoutes } else { - if splitTunnelType == "2" { + if splitTunnelType == 2 { var ipv4ExcludedRoutes = [NEIPv4Route]() var ipv4IncludedRoutes = [NEIPv4Route]() var ipv6IncludedRoutes = [NEIPv6Route]() - let STSdata = Data(splitTunnelSites!.utf8) - do { - guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return } - for excludeIPString in STSArray { - if let excludeIP = IPAddressRange(from: excludeIPString) { - ipv4ExcludedRoutes.append(NEIPv4Route( - destinationAddress: "\(excludeIP.address)", - subnetMask: "\(excludeIP.subnetMask())")) - } + + for excludeIPString in splitTunnelSites { + if let excludeIP = IPAddressRange(from: excludeIPString) { + ipv4ExcludedRoutes.append(NEIPv4Route( + destinationAddress: "\(excludeIP.address)", + subnetMask: "\(excludeIP.subnetMask())")) } - } catch { - wg_log(.error, message: "Parse JSONSerialization Error") } + if let allIPv4 = IPAddressRange(from: "0.0.0.0/0") { ipv4IncludedRoutes.append(NEIPv4Route( destinationAddress: "\(allIPv4.address)", diff --git a/client/platforms/ios/PacketTunnelProvider.swift b/client/platforms/ios/PacketTunnelProvider.swift index 36097c0d..37d3bc26 100644 --- a/client/platforms/ios/PacketTunnelProvider.swift +++ b/client/platforms/ios/PacketTunnelProvider.swift @@ -50,8 +50,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider { private let dispatchQueue = DispatchQueue(label: "PacketTunnel", qos: .utility) private var openVPNConfig: Data? - var splitTunnelType: String? - var splitTunnelSites: String? + var splitTunnelType: Int! + var splitTunnelSites: [String]! let vpnReachability = OpenVPNReachability() @@ -83,8 +83,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } if action == Constants.kActionStart { - splitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String - splitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String + // splitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String + // splitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String } let callbackWrapper: (NSNumber?) -> Void = { errorCode in @@ -169,110 +169,118 @@ class PacketTunnelProvider: NEPacketTunnelProvider { completionHandler: @escaping (Error?) -> Void) { guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, let providerConfiguration = protocolConfiguration.providerConfiguration, - let wgConfig: Data = providerConfiguration[Constants.wireGuardConfigKey] as? Data else { + let wgConfigData: Data = providerConfiguration[Constants.wireGuardConfigKey] as? Data else { wg_log(.error, message: "Can't start WireGuard config missing") completionHandler(nil) return } - guard let wgConfigStr = try? JSONDecoder().decode(WGConfig.self, from: wgConfig).wg, - let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr) - else { - wg_log(.error, message: "Can't parse WireGuard config") - completionHandler(nil) - return - } + do { + let wgConfig = try JSONDecoder().decode(WGConfig.self, from: wgConfigData) + let wgConfigStr = wgConfig.str + log(.info, message: "wgConfig: \(wgConfig.redux.replacingOccurrences(of: "\n", with: " "))") - log(.info, message: "wgConfig: \(wgConfigStr.replacingOccurrences(of: "\n", with: " "))") + let tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: wgConfigStr) - if tunnelConfiguration.peers.first!.allowedIPs - .map({ $0.stringRepresentation }) - .joined(separator: ", ") == "0.0.0.0/0, ::/0" { - if splitTunnelType == "1" { - for index in tunnelConfiguration.peers.indices { - tunnelConfiguration.peers[index].allowedIPs.removeAll() - var allowedIPs = [IPAddressRange]() - let STSdata = Data(splitTunnelSites!.utf8) - do { - guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return } - for allowedIPString in STSArray { + if tunnelConfiguration.peers.first!.allowedIPs + .map({ $0.stringRepresentation }) + .joined(separator: ", ") == "0.0.0.0/0, ::/0" { + if wgConfig.splitTunnelType == 1 { + for index in tunnelConfiguration.peers.indices { + tunnelConfiguration.peers[index].allowedIPs.removeAll() + var allowedIPs = [IPAddressRange]() + + for allowedIPString in wgConfig.splitTunnelSites { if let allowedIP = IPAddressRange(from: allowedIPString) { allowedIPs.append(allowedIP) } } - } catch { - wg_log(.error, message: "Parse JSONSerialization Error") + + tunnelConfiguration.peers[index].allowedIPs = allowedIPs } - tunnelConfiguration.peers[index].allowedIPs = allowedIPs - } - } else if splitTunnelType == "2" { - for index in tunnelConfiguration.peers.indices { - var excludeIPs = [IPAddressRange]() - let STSdata = Data(splitTunnelSites!.utf8) - do { - guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return } - for excludeIPString in STSArray { + } else if wgConfig.splitTunnelType == 2 { + for index in tunnelConfiguration.peers.indices { + var excludeIPs = [IPAddressRange]() + + for excludeIPString in wgConfig.splitTunnelSites { if let excludeIP = IPAddressRange(from: excludeIPString) { excludeIPs.append(excludeIP) } } - } catch { - wg_log(.error, message: "Parse JSONSerialization Error") + + tunnelConfiguration.peers[index].excludeIPs = excludeIPs } - tunnelConfiguration.peers[index].excludeIPs = excludeIPs } } - } - wg_log(.info, message: "Starting wireguard tunnel from the " + - (activationAttemptId == nil ? "OS directly, rather than the app" : "app")) + wg_log(.info, message: "Starting wireguard tunnel from the " + + (activationAttemptId == nil ? "OS directly, rather than the app" : "app")) - // Start the tunnel - wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in - guard let adapterError else { - let interfaceName = self.wgAdapter.interfaceName ?? "unknown" - wg_log(.info, message: "Tunnel interface is \(interfaceName)") - completionHandler(nil) - return - } - - switch adapterError { - case .cannotLocateTunnelFileDescriptor: - wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor") - errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor) - completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor) - case .dnsResolution(let dnsErrors): - let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address } - .joined(separator: ", ") - wg_log(.error, message: - "DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)") - errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure) - completionHandler(PacketTunnelProviderError.dnsResolutionFailure) - case .setNetworkSettings(let error): - wg_log(.error, message: - "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)") - errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings) - completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings) - case .startWireGuardBackend(let errorCode): - wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)") - errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend) - completionHandler(PacketTunnelProviderError.couldNotStartBackend) - case .invalidState: - fatalError() + // Start the tunnel + wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in + guard let adapterError else { + let interfaceName = self.wgAdapter.interfaceName ?? "unknown" + wg_log(.info, message: "Tunnel interface is \(interfaceName)") + completionHandler(nil) + return + } + + switch adapterError { + case .cannotLocateTunnelFileDescriptor: + wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor") + errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor) + completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor) + case .dnsResolution(let dnsErrors): + let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address } + .joined(separator: ", ") + wg_log(.error, message: + "DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)") + errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure) + completionHandler(PacketTunnelProviderError.dnsResolutionFailure) + case .setNetworkSettings(let error): + wg_log(.error, message: + "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)") + errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings) + completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings) + case .startWireGuardBackend(let errorCode): + wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)") + errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend) + completionHandler(PacketTunnelProviderError.couldNotStartBackend) + case .invalidState: + fatalError() + } } + } catch { + log(.error, message: "Can't parse WG config: \(error.localizedDescription)") + completionHandler(nil) + return } } private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) { guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, let providerConfiguration = protocolConfiguration.providerConfiguration, - let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else { - + let openVPNConfigData = providerConfiguration[Constants.ovpnConfigKey] as? Data else { wg_log(.error, message: "Can't start startOpenVPN()") return } - setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler) + do { + log(.info, message: "providerConfiguration: \(String(decoding: openVPNConfigData, as: UTF8.self).replacingOccurrences(of: "\n", with: " "))") + + let openVPNConfig = try JSONDecoder().decode(OpenVPNConfig.self, from: openVPNConfigData) + log(.info, message: "openVPNConfig: \(openVPNConfig.str.replacingOccurrences(of: "\n", with: " "))") + let ovpnConfiguration = Data(openVPNConfig.config.utf8) + setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler) + } catch { + log(.error, message: "Can't parse OpenVPN config: \(error.localizedDescription)") + + if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError { + log(.error, message: "Can't parse OpenVPN config: \(underlyingError.localizedDescription)") + } + + return + } } private func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { diff --git a/client/platforms/ios/WGConfig.swift b/client/platforms/ios/WGConfig.swift index d86dd471..de32d9ba 100644 --- a/client/platforms/ios/WGConfig.swift +++ b/client/platforms/ios/WGConfig.swift @@ -1,9 +1,41 @@ import Foundation -struct WGConfigData: Decodable { +struct WGConfig: Decodable { let h1, h2, h3, h4: String? let jc, jmax, jmin: String? let s1, s2: String? + let dns1: String + let dns2: String + let mtu: String + let hostName: String + let port: Int + let clientIP: String + let clientPrivateKey: String + let serverPublicKey: String + let presharedKey: String + var allowedIPs: [String] + var persistentKeepAlive: String + let splitTunnelType: Int + let splitTunnelSites: [String] + + enum CodingKeys: String, CodingKey { + case h1 = "H1", h2 = "H2", h3 = "H3", h4 = "H4" + case jc = "Jc", jmax = "Jmax", jmin = "Jmin" + case s1 = "S1", s2 = "S2" + case dns1 + case dns2 + case mtu + case hostName + case port + case clientIP = "client_ip" + case clientPrivateKey = "client_priv_key" + case serverPublicKey = "server_pub_key" + case presharedKey = "psk_key" + case allowedIPs = "allowed_ips" + case persistentKeepAlive = "persistent_keep_alive" + case splitTunnelType + case splitTunnelSites + } var settings: String { jc == nil ? "" : @@ -21,113 +53,48 @@ struct WGConfigData: Decodable { """ } - let clientIP: String - let clientPrivateKey: String - let clientPublicKey: String - let serverPublicKey: String - let presharedKey: String - let hostName: String - let port: Int - - var allowedIPs: [String] - var persistentKeepAlive: String - - enum CodingKeys: String, CodingKey { - case h1 = "H1", h2 = "H2", h3 = "H3", h4 = "H4" - case jc = "Jc", jmax = "Jmax", jmin = "Jmin" - case s1 = "S1", s2 = "S2" - - case clientIP = "client_ip" // "10.8.1.16" - case clientPrivateKey = "client_priv_key" - case clientPublicKey = "client_pub_key" - case serverPublicKey = "server_pub_key" - case presharedKey = "psk_key" - - case allowedIPs = "allowed_ips" - case persistentKeepAlive = "persistent_keep_alive" - case hostName - case port - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.h1 = try container.decodeIfPresent(String.self, forKey: .h1) - self.h2 = try container.decodeIfPresent(String.self, forKey: .h2) - self.h3 = try container.decodeIfPresent(String.self, forKey: .h3) - self.h4 = try container.decodeIfPresent(String.self, forKey: .h4) - self.jc = try container.decodeIfPresent(String.self, forKey: .jc) - self.jmax = try container.decodeIfPresent(String.self, forKey: .jmax) - self.jmin = try container.decodeIfPresent(String.self, forKey: .jmin) - self.s1 = try container.decodeIfPresent(String.self, forKey: .s1) - self.s2 = try container.decodeIfPresent(String.self, forKey: .s2) - self.clientIP = try container.decode(String.self, forKey: .clientIP) - self.clientPrivateKey = try container.decode(String.self, forKey: .clientPrivateKey) - self.clientPublicKey = try container.decode(String.self, forKey: .clientPublicKey) - self.serverPublicKey = try container.decode(String.self, forKey: .serverPublicKey) - self.presharedKey = try container.decode(String.self, forKey: .presharedKey) - self.allowedIPs = try container.decodeIfPresent([String].self, forKey: .allowedIPs) ?? ["0.0.0.0/0", "::/0"] - self.persistentKeepAlive = try container.decodeIfPresent(String.self, forKey: .persistentKeepAlive) ?? "25" - self.hostName = try container.decode(String.self, forKey: .hostName) - self.port = try container.decode(Int.self, forKey: .port) - } -} - -struct WGConfig: Decodable { - let data: WGConfigData - let configVersion: Int - let description: String - let dns1: String - let dns2: String - let hostName: String - let `protocol`: String - let splitTunnelSites: [String] - let splitTunnelType: Int - - enum CodingKeys: String, CodingKey { - case awgConfigData = "awg_config_data", wgConfigData = "wireguard_config_data" - case configData - case configVersion = "config_version" - case description - case dns1 - case dns2 - case hostName - case `protocol` - case splitTunnelSites - case splitTunnelType - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - if container.contains(.awgConfigData) { - self.data = try container.decode(WGConfigData.self, forKey: .awgConfigData) - } else { - self.data = try container.decode(WGConfigData.self, forKey: .wgConfigData) - } - - self.configVersion = try container.decode(Int.self, forKey: .configVersion) - self.description = try container.decode(String.self, forKey: .description) - self.dns1 = try container.decode(String.self, forKey: .dns1) - self.dns2 = try container.decode(String.self, forKey: .dns2) - self.hostName = try container.decode(String.self, forKey: .hostName) - self.protocol = try container.decode(String.self, forKey: .protocol) - self.splitTunnelSites = try container.decode([String].self, forKey: .splitTunnelSites) - self.splitTunnelType = try container.decode(Int.self, forKey: .splitTunnelType) - } - - var wg: String { + var str: String { """ [Interface] - Address = \(data.clientIP)/32 + Address = \(clientIP)/32 DNS = \(dns1), \(dns2) - PrivateKey = \(data.clientPrivateKey) - \(data.settings) + MTU = \(mtu) + PrivateKey = \(clientPrivateKey) + \(settings) [Peer] - PublicKey = \(data.serverPublicKey) - PresharedKey = \(data.presharedKey) - AllowedIPs = \(data.allowedIPs.joined(separator: ", ")) - Endpoint = \(data.hostName):\(data.port) - PersistentKeepalive = \(data.persistentKeepAlive) + PublicKey = \(serverPublicKey) + PresharedKey = \(presharedKey) + AllowedIPs = \(allowedIPs.joined(separator: ", ")) + Endpoint = \(hostName):\(port) + PersistentKeepalive = \(persistentKeepAlive) + """ + } + + var redux: String { + """ + [Interface] + Address = \(clientIP)/32 + DNS = \(dns1), \(dns2) + MTU = \(mtu) + PrivateKey = *** + \(settings) + [Peer] + PublicKey = *** + PresharedKey = *** + AllowedIPs = \(allowedIPs.joined(separator: ", ")) + Endpoint = \(hostName):\(port) + PersistentKeepalive = \(persistentKeepAlive) """ } } + +struct OpenVPNConfig: Decodable { + let config: String + let mtu: String + let splitTunnelType: Int + let splitTunnelSites: [String] + + var str: String { + "splitTunnelType: \(splitTunnelType) splitTunnelSites: \(splitTunnelSites) mtu: \(mtu) config: \(config)" + } +} diff --git a/client/platforms/ios/ios_controller.mm b/client/platforms/ios/ios_controller.mm index 0d5eadbc..1eb9da3d 100644 --- a/client/platforms/ios/ios_controller.mm +++ b/client/platforms/ios/ios_controller.mm @@ -357,7 +357,16 @@ bool IosController::setupOpenVPN() QJsonObject ovpn = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::OpenVpn)].toObject(); QString ovpnConfig = ovpn[config_key::config].toString(); - return startOpenVPN(ovpnConfig); + QJsonObject openVPNConfig {}; + openVPNConfig.insert(config_key::config, ovpnConfig); + openVPNConfig.insert(config_key::mtu, m_rawConfig[config_key::mtu]); + openVPNConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]); + openVPNConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]); + + QJsonDocument openVPNConfigDoc(openVPNConfig); + QString openVPNConfigStr(openVPNConfigDoc.toJson(QJsonDocument::Compact)); + + return startOpenVPN(openVPNConfigStr); } bool IosController::setupCloak() @@ -394,27 +403,100 @@ bool IosController::setupCloak() ovpnConfig.append(cloakBase64); ovpnConfig.append("\n\n"); - return startOpenVPN(ovpnConfig); + QJsonObject openVPNConfig {}; + openVPNConfig.insert(config_key::config, ovpnConfig); + openVPNConfig.insert(config_key::mtu, m_rawConfig[config_key::mtu]); + openVPNConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]); + openVPNConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]); + + QJsonDocument openVPNConfigDoc(openVPNConfig); + QString openVPNConfigStr(openVPNConfigDoc.toJson(QJsonDocument::Compact)); + + return startOpenVPN(openVPNConfigStr); } bool IosController::setupWireGuard() { QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject(); - - QJsonDocument doc(m_rawConfig); - QString wgConfig(doc.toJson(QJsonDocument::Compact)); - return startWireGuard(wgConfig); + QJsonObject wgConfig {}; + wgConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]); + wgConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]); + wgConfig.insert(config_key::mtu, config[config_key::mtu]); + wgConfig.insert(config_key::hostName, config[config_key::hostName]); + wgConfig.insert(config_key::port, config[config_key::port]); + wgConfig.insert(config_key::client_ip, config[config_key::client_ip]); + wgConfig.insert(config_key::client_priv_key, config[config_key::client_priv_key]); + wgConfig.insert(config_key::server_pub_key, config[config_key::server_pub_key]); + wgConfig.insert(config_key::psk_key, config[config_key::psk_key]); + wgConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]); + wgConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]); + + if (config.contains(config_key::allowed_ips)) { + wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]); + } else { + QJsonArray allowed_ips { "0.0.0.0/0", "::/0" }; + wgConfig.insert(config_key::allowed_ips, allowed_ips); + } + + if (config.contains(config_key::persistent_keep_alive)) { + wgConfig.insert(config_key::persistent_keep_alive, config[config_key::persistent_keep_alive]); + } else { + wgConfig.insert(config_key::persistent_keep_alive, "25"); + } + + QJsonDocument wgConfigDoc(wgConfig); + QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact)); + + return startWireGuard(wgConfigDocStr); } bool IosController::setupAwg() { QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject(); - QJsonDocument doc(m_rawConfig); - QString wgConfig(doc.toJson(QJsonDocument::Compact)); + QJsonObject wgConfig {}; + wgConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]); + wgConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]); + wgConfig.insert(config_key::mtu, config[config_key::mtu]); + wgConfig.insert(config_key::hostName, config[config_key::hostName]); + wgConfig.insert(config_key::port, config[config_key::port]); + wgConfig.insert(config_key::client_ip, config[config_key::client_ip]); + wgConfig.insert(config_key::client_priv_key, config[config_key::client_priv_key]); + wgConfig.insert(config_key::server_pub_key, config[config_key::server_pub_key]); + wgConfig.insert(config_key::psk_key, config[config_key::psk_key]); + wgConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]); + wgConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]); - return startWireGuard(wgConfig); + if (config.contains(config_key::allowed_ips)) { + wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]); + } else { + QJsonArray allowed_ips { "0.0.0.0/0", "::/0" }; + wgConfig.insert(config_key::allowed_ips, allowed_ips); + } + + if (config.contains(config_key::persistent_keep_alive)) { + wgConfig.insert(config_key::persistent_keep_alive, config[config_key::persistent_keep_alive]); + } else { + wgConfig.insert(config_key::persistent_keep_alive, "25"); + } + + wgConfig.insert(config_key::initPacketMagicHeader, config[config_key::initPacketMagicHeader]); + wgConfig.insert(config_key::responsePacketMagicHeader, config[config_key::responsePacketMagicHeader]); + wgConfig.insert(config_key::underloadPacketMagicHeader, config[config_key::underloadPacketMagicHeader]); + wgConfig.insert(config_key::transportPacketMagicHeader, config[config_key::transportPacketMagicHeader]); + + wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]); + wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]); + + wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]); + wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]); + wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]); + + QJsonDocument wgConfigDoc(wgConfig); + QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact)); + + return startWireGuard(wgConfigDocStr); } bool IosController::startOpenVPN(const QString &config) @@ -499,7 +581,7 @@ void IosController::startTunnel() NSDictionary* message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue, SplitTunnelTypeKey: SplitTunnelTypeValue, SplitTunnelSitesKey: SplitTunnelSitesValue}; - sendVpnExtensionMessage(message); +// sendVpnExtensionMessage(message); BOOL started = [m_currentTunnel.connection startVPNTunnelWithOptions:nil andReturnError:&startError]; diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 566f9959..18c9db1d 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -46,6 +46,7 @@ namespace amnezia constexpr char psk_key[] = "psk_key"; constexpr char mtu[] = "mtu"; constexpr char allowed_ips[] = "allowed_ips"; + constexpr char persistent_keep_alive[] = "persistent_keep_alive"; constexpr char client_ip[] = "client_ip"; // internal ip address diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index d267584a..65d30cd3 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -305,6 +305,11 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex, const ServerC // TODO: try to get hostName, port, description for 3rd party configs // vpnConfiguration[config_key::port] = ...; +#if defined Q_OS_IOS + QJsonObject awg = server[config_key::containers].toArray().first().toObject()[config_key::awg].toObject(); + QString mtu = awg[config_key::mtu].toString(protocols::awg::defaultMtu); + vpnConfiguration[config_key::mtu] = mtu; +#endif return vpnConfiguration; }