diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9dfe0..a40749f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgrade OpenSSL to 1.1.1q. - Use natively async methods from NetworkExtension. [#284](https://github.com/passepartoutvpn/tunnelkit/pull/284) +- OpenVPN: Unmask PUSH_REPLY and network settings in logs. ### Fixed diff --git a/Sources/TunnelKitOpenVPNAppExtension/NetworkSettingsBuilder.swift b/Sources/TunnelKitOpenVPNAppExtension/NetworkSettingsBuilder.swift new file mode 100644 index 0000000..d54d34e --- /dev/null +++ b/Sources/TunnelKitOpenVPNAppExtension/NetworkSettingsBuilder.swift @@ -0,0 +1,298 @@ +// +// NetworkSettingsBuilder.swift +// TunnelKit +// +// Created by Davide De Rosa on 10/21/22. +// Copyright (c) 2022 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Foundation +import NetworkExtension +import TunnelKitCore +import TunnelKitOpenVPNCore +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +struct NetworkSettingsBuilder { + let remoteAddress: String + + let localOptions: OpenVPN.Configuration + + let remoteOptions: OpenVPN.Configuration + + init(remoteAddress: String, localOptions: OpenVPN.Configuration, remoteOptions: OpenVPN.Configuration) { + self.remoteAddress = remoteAddress + self.localOptions = localOptions + self.remoteOptions = remoteOptions + } + + func build() -> NEPacketTunnelNetworkSettings { + let ipv4Settings = computedIPv4Settings + let ipv6Settings = computedIPv6Settings + let dnsSettings = computedDNSSettings + let proxySettings = computedProxySettings + + // add direct routes to DNS servers + if !isGateway { + for server in dnsSettings?.servers ?? [] { + if server.contains(":") { + ipv6Settings?.includedRoutes?.insert(NEIPv6Route(destinationAddress: server, networkPrefixLength: 128), at: 0) + } else { + ipv4Settings?.includedRoutes?.insert(NEIPv4Route(destinationAddress: server, subnetMask: "255.255.255.255"), at: 0) + } + } + } + + let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress) + settings.ipv4Settings = ipv4Settings + settings.ipv6Settings = ipv6Settings + settings.dnsSettings = dnsSettings + settings.proxySettings = proxySettings + if let mtu = localOptions.mtu, mtu > 0 { + settings.mtu = NSNumber(value: mtu) + } + return settings + } +} + +extension NetworkSettingsBuilder { + private var pullRoutes: Bool { + !(localOptions.noPullMask?.contains(.routes) ?? false) + } + + private var pullDNS: Bool { + !(localOptions.noPullMask?.contains(.dns) ?? false) + } + + private var pullProxy: Bool { + !(localOptions.noPullMask?.contains(.proxy) ?? false) + } +} + +extension NetworkSettingsBuilder { + var isGateway: Bool { + isIPv4Gateway || isIPv6Gateway + } + + private var routingPolicies: [OpenVPN.RoutingPolicy]? { + pullRoutes ? (remoteOptions.routingPolicies ?? localOptions.routingPolicies) : localOptions.routingPolicies + } + + private var isIPv4Gateway: Bool { + routingPolicies?.contains(.IPv4) ?? false + } + + private var isIPv6Gateway: Bool { + routingPolicies?.contains(.IPv6) ?? false + } +} + +extension NetworkSettingsBuilder { + + // IPv4/6 address/mask MUST come from server options + // routes, instead, can both come from server and local options + // + // FIXME: routes from local options are ignored (#278) + + private var computedIPv4Settings: NEIPv4Settings? { + guard let ipv4 = remoteOptions.ipv4 else { + return nil + } + let ipv4Settings = NEIPv4Settings(addresses: [ipv4.address], subnetMasks: [ipv4.addressMask]) + if pullRoutes { + var routes: [NEIPv4Route] = [] + + // route all traffic to VPN? + if isIPv4Gateway { + let defaultRoute = NEIPv4Route.default() + defaultRoute.gatewayAddress = ipv4.defaultGateway + routes.append(defaultRoute) + log.info("Routing.IPv4: Setting default gateway to \(ipv4.defaultGateway)") + } + + for r in ipv4.routes { + let ipv4Route = NEIPv4Route(destinationAddress: r.destination, subnetMask: r.mask) + ipv4Route.gatewayAddress = r.gateway + routes.append(ipv4Route) + log.info("Routing.IPv4: Adding route \(r.destination)/\(r.mask) -> \(r.gateway)") + } + + ipv4Settings.includedRoutes = routes + ipv4Settings.excludedRoutes = [] + } + return ipv4Settings + } + + private var computedIPv6Settings: NEIPv6Settings? { + guard let ipv6 = remoteOptions.ipv6 else { + return nil + } + let ipv6Settings = NEIPv6Settings(addresses: [ipv6.address], networkPrefixLengths: [ipv6.addressPrefixLength as NSNumber]) + if pullRoutes { + var routes: [NEIPv6Route] = [] + + // route all traffic to VPN? + if isIPv6Gateway { + let defaultRoute = NEIPv6Route.default() + defaultRoute.gatewayAddress = ipv6.defaultGateway + routes.append(defaultRoute) + log.info("Routing.IPv6: Setting default gateway to \(ipv6.defaultGateway)") + } + + for r in ipv6.routes { + let ipv6Route = NEIPv6Route(destinationAddress: r.destination, networkPrefixLength: r.prefixLength as NSNumber) + ipv6Route.gatewayAddress = r.gateway + routes.append(ipv6Route) + log.info("Routing.IPv6: Adding route \(r.destination)/\(r.prefixLength) -> \(r.gateway)") + } + + ipv6Settings.includedRoutes = routes + ipv6Settings.excludedRoutes = [] + } + return ipv6Settings + } + + var hasGateway: Bool { + var hasGateway = false + if isIPv4Gateway && computedIPv4Settings != nil { + hasGateway = true + } + if isIPv6Gateway && computedIPv6Settings != nil { + hasGateway = true + } + return hasGateway + } +} + +extension NetworkSettingsBuilder { + private var computedDNSSettings: NEDNSSettings? { + guard localOptions.isDNSEnabled ?? true else { + return nil + } + var dnsSettings: NEDNSSettings? + var dnsServers: [String] = [] + if #available(iOS 14, macOS 11, *) { + switch localOptions.dnsProtocol { + case .https: + dnsServers = localOptions.dnsServers ?? [] + guard let serverURL = localOptions.dnsHTTPSURL else { + break + } + let specific = NEDNSOverHTTPSSettings(servers: dnsServers) + specific.serverURL = serverURL + dnsSettings = specific + log.info("DNS over HTTPS: Using servers \(dnsServers)") + log.info("\tHTTPS URL: \(serverURL)") + + case .tls: + dnsServers = localOptions.dnsServers ?? [] + guard let serverName = localOptions.dnsTLSServerName else { + break + } + let specific = NEDNSOverTLSSettings(servers: dnsServers) + specific.serverName = serverName + dnsSettings = specific + log.info("DNS over TLS: Using servers \(dnsServers)") + log.info("\tTLS server name: \(serverName)") + + default: + break + } + } + + // fall back + if dnsSettings == nil { + dnsServers = (pullDNS ? (remoteOptions.dnsServers ?? localOptions.dnsServers) : localOptions.dnsServers) ?? [] + if !dnsServers.isEmpty { + log.info("DNS: Using servers \(dnsServers)") + dnsSettings = NEDNSSettings(servers: dnsServers) + } else { +// log.warning("DNS: No servers provided, using fall-back servers: \(fallbackDNSServers)") +// dnsSettings = NEDNSSettings(servers: fallbackDNSServers) + if isGateway { + log.warning("DNS: No settings provided") + } else { + log.warning("DNS: No settings provided, using current network settings") + } + } + } + + // "hack" for split DNS (i.e. use VPN only for DNS) + if !isGateway { + dnsSettings?.matchDomains = [""] + } + + if let searchDomains = pullDNS ? (remoteOptions.searchDomains ?? localOptions.searchDomains) : localOptions.searchDomains { + log.info("DNS: Using search domains \(searchDomains)") + dnsSettings?.domainName = searchDomains.first + dnsSettings?.searchDomains = searchDomains + if !isGateway { + dnsSettings?.matchDomains = dnsSettings?.searchDomains + } + } + + return dnsSettings + } +} + +extension NetworkSettingsBuilder { + private var computedProxySettings: NEProxySettings? { + guard localOptions.isProxyEnabled ?? true else { + return nil + } + var proxySettings: NEProxySettings? + if let httpsProxy = pullProxy ? (remoteOptions.httpsProxy ?? localOptions.httpsProxy) : localOptions.httpsProxy { + proxySettings = NEProxySettings() + proxySettings?.httpsServer = httpsProxy.neProxy() + proxySettings?.httpsEnabled = true + log.info("Routing: Setting HTTPS proxy \(httpsProxy.address):\(httpsProxy.port)") + } + if let httpProxy = pullProxy ? (remoteOptions.httpProxy ?? localOptions.httpProxy) : localOptions.httpProxy { + if proxySettings == nil { + proxySettings = NEProxySettings() + } + proxySettings?.httpServer = httpProxy.neProxy() + proxySettings?.httpEnabled = true + log.info("Routing: Setting HTTP proxy \(httpProxy.address):\(httpProxy.port)") + } + if let pacURL = pullProxy ? (remoteOptions.proxyAutoConfigurationURL ?? localOptions.proxyAutoConfigurationURL) : localOptions.proxyAutoConfigurationURL { + if proxySettings == nil { + proxySettings = NEProxySettings() + } + proxySettings?.proxyAutoConfigurationURL = pacURL + proxySettings?.autoProxyConfigurationEnabled = true + log.info("Routing: Setting PAC \(pacURL)") + } + + // only set if there is a proxy (proxySettings set to non-nil above) + if let bypass = pullProxy ? (remoteOptions.proxyBypassDomains ?? localOptions.proxyBypassDomains) : localOptions.proxyBypassDomains { + proxySettings?.exceptionList = bypass + log.info("Routing: Setting proxy by-pass list: \(bypass)") + } + return proxySettings + } +} + +private extension Proxy { + func neProxy() -> NEProxyServer { + return NEProxyServer(address: address, port: Int(port)) + } +} diff --git a/Sources/TunnelKitOpenVPNAppExtension/OpenVPNTunnelProvider.swift b/Sources/TunnelKitOpenVPNAppExtension/OpenVPNTunnelProvider.swift index 77415ed..510687e 100644 --- a/Sources/TunnelKitOpenVPNAppExtension/OpenVPNTunnelProvider.swift +++ b/Sources/TunnelKitOpenVPNAppExtension/OpenVPNTunnelProvider.swift @@ -524,7 +524,7 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate { cfg._appexSetServerConfiguration(session.serverConfiguration() as? OpenVPN.Configuration) - bringNetworkUp(remoteAddress: remoteAddress, localOptions: session.configuration, options: options) { (error) in + bringNetworkUp(remoteAddress: remoteAddress, localOptions: session.configuration, remoteOptions: options) { (error) in // FIXME: XPC queue @@ -565,266 +565,52 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate { socket?.shutdown() } - private func bringNetworkUp(remoteAddress: String, localOptions: OpenVPN.Configuration, options: OpenVPN.Configuration, completionHandler: @escaping (Error?) -> Void) { - let pullMask = localOptions.pullMask - let pullRoutes = pullMask?.contains(.routes) ?? false - let pullDNS = pullMask?.contains(.dns) ?? false - let pullProxy = pullMask?.contains(.proxy) ?? false + private func bringNetworkUp(remoteAddress: String, localOptions: OpenVPN.Configuration, remoteOptions: OpenVPN.Configuration, completionHandler: @escaping (Error?) -> Void) { + let newSettings = NetworkSettingsBuilder(remoteAddress: remoteAddress, localOptions: localOptions, remoteOptions: remoteOptions) - let routingPolicies = pullRoutes ? options.routingPolicies : localOptions.routingPolicies - let isIPv4Gateway = routingPolicies?.contains(.IPv4) ?? false - let isIPv6Gateway = routingPolicies?.contains(.IPv6) ?? false - let isGateway = isIPv4Gateway || isIPv6Gateway - - var ipv4Settings: NEIPv4Settings? - if let ipv4 = options.ipv4 { - var routes: [NEIPv4Route] = [] - - // route all traffic to VPN? - if isIPv4Gateway { - let defaultRoute = NEIPv4Route.default() - defaultRoute.gatewayAddress = ipv4.defaultGateway - routes.append(defaultRoute) -// for network in ["0.0.0.0", "128.0.0.0"] { -// let route = NEIPv4Route(destinationAddress: network, subnetMask: "128.0.0.0") -// route.gatewayAddress = ipv4.defaultGateway -// routes.append(route) -// } - log.info("Routing.IPv4: Setting default gateway to \(ipv4.defaultGateway.maskedDescription)") - } - - if pullRoutes { - for r in ipv4.routes { - let ipv4Route = NEIPv4Route(destinationAddress: r.destination, subnetMask: r.mask) - ipv4Route.gatewayAddress = r.gateway - routes.append(ipv4Route) - log.info("Routing.IPv4: Adding route \(r.destination.maskedDescription)/\(r.mask) -> \(r.gateway)") - } - } - - ipv4Settings = NEIPv4Settings(addresses: [ipv4.address], subnetMasks: [ipv4.addressMask]) - ipv4Settings?.includedRoutes = routes - ipv4Settings?.excludedRoutes = [] - } - - var ipv6Settings: NEIPv6Settings? - if let ipv6 = options.ipv6 { - var routes: [NEIPv6Route] = [] - - // route all traffic to VPN? - if isIPv6Gateway { - let defaultRoute = NEIPv6Route.default() - defaultRoute.gatewayAddress = ipv6.defaultGateway - routes.append(defaultRoute) -// for network in ["2000::", "3000::"] { -// let route = NEIPv6Route(destinationAddress: network, networkPrefixLength: 4) -// route.gatewayAddress = ipv6.defaultGateway -// routes.append(route) -// } - log.info("Routing.IPv6: Setting default gateway to \(ipv6.defaultGateway.maskedDescription)") - } - - if pullRoutes { - for r in ipv6.routes { - let ipv6Route = NEIPv6Route(destinationAddress: r.destination, networkPrefixLength: r.prefixLength as NSNumber) - ipv6Route.gatewayAddress = r.gateway - routes.append(ipv6Route) - log.info("Routing.IPv6: Adding route \(r.destination.maskedDescription)/\(r.prefixLength) -> \(r.gateway)") - } - } - - ipv6Settings = NEIPv6Settings(addresses: [ipv6.address], networkPrefixLengths: [ipv6.addressPrefixLength as NSNumber]) - ipv6Settings?.includedRoutes = routes - ipv6Settings?.excludedRoutes = [] - } - - // shut down if default gateway is not attainable - var hasGateway = false - if isIPv4Gateway && (ipv4Settings != nil) { - hasGateway = true - } - if isIPv6Gateway && (ipv6Settings != nil) { - hasGateway = true - } - guard !isGateway || hasGateway else { + guard !newSettings.isGateway || newSettings.hasGateway else { session?.shutdown(error: OpenVPNProviderError.gatewayUnattainable) return } - - var dnsSettings: NEDNSSettings? - if localOptions.isDNSEnabled ?? true { - var dnsServers: [String] = [] - if #available(iOS 14, macOS 11, *) { - switch localOptions.dnsProtocol { - case .https: - dnsServers = localOptions.dnsServers ?? [] - guard let serverURL = localOptions.dnsHTTPSURL else { - break - } - let specific = NEDNSOverHTTPSSettings(servers: dnsServers) - specific.serverURL = serverURL - dnsSettings = specific - log.info("DNS over HTTPS: Using servers \(dnsServers.maskedDescription)") - log.info("\tHTTPS URL: \(serverURL.maskedDescription)") - case .tls: - dnsServers = localOptions.dnsServers ?? [] - guard let serverName = localOptions.dnsTLSServerName else { - break - } - let specific = NEDNSOverTLSSettings(servers: dnsServers) - specific.serverName = serverName - dnsSettings = specific - log.info("DNS over TLS: Using servers \(dnsServers.maskedDescription)") - log.info("\tTLS server name: \(serverName.maskedDescription)") +// // block LAN if desired +// if routingPolicies?.contains(.blockLocal) ?? false { +// let table = RoutingTable() +// if isIPv4Gateway, +// let gateway = table.defaultGateway4()?.gateway(), +// let route = table.broadestRoute4(matchingDestination: gateway) { +// +// route.partitioned()?.forEach { +// let destination = $0.network() +// guard let netmask = $0.networkMask() else { +// return +// } +// +// log.info("Block local: Suppressing IPv4 route \(destination)/\($0.prefix())") +// +// let included = NEIPv4Route(destinationAddress: destination, subnetMask: netmask) +// included.gatewayAddress = options.ipv4?.defaultGateway +// ipv4Settings?.includedRoutes?.append(included) +// } +// } +// if isIPv6Gateway, +// let gateway = table.defaultGateway6()?.gateway(), +// let route = table.broadestRoute6(matchingDestination: gateway) { +// +// route.partitioned()?.forEach { +// let destination = $0.network() +// let prefix = $0.prefix() +// +// log.info("Block local: Suppressing IPv6 route \(destination)/\($0.prefix())") +// +// let included = NEIPv6Route(destinationAddress: destination, networkPrefixLength: prefix as NSNumber) +// included.gatewayAddress = options.ipv6?.defaultGateway +// ipv6Settings?.includedRoutes?.append(included) +// } +// } +// } - default: - break - } - } - - // ensure that non-nil arrays also imply non-empty - if let array = options.dnsServers { - precondition(!array.isEmpty) - } - if let array = options.searchDomains { - precondition(!array.isEmpty) - } - if let array = options.proxyBypassDomains { - precondition(!array.isEmpty) - } - if let array = cfg.configuration.dnsServers { - precondition(!array.isEmpty) - } - if let array = cfg.configuration.searchDomains { - precondition(!array.isEmpty) - } - if let array = cfg.configuration.proxyBypassDomains { - precondition(!array.isEmpty) - } - - // fall back - if dnsSettings == nil { - dnsServers = (pullDNS ? options.dnsServers : localOptions.dnsServers) ?? [] - if !dnsServers.isEmpty { - log.info("DNS: Using servers \(dnsServers.maskedDescription)") - dnsSettings = NEDNSSettings(servers: dnsServers) - } else { -// log.warning("DNS: No servers provided, using fall-back servers: \(fallbackDNSServers.maskedDescription)") -// dnsSettings = NEDNSSettings(servers: fallbackDNSServers) - if isGateway { - log.warning("DNS: No settings provided, using current network settings") - } else { - log.warning("DNS: No settings provided") - } - } - } - - // "hack" for split DNS (i.e. use VPN only for DNS) - if !isGateway { - dnsSettings?.matchDomains = [""] - } - - if let searchDomains = pullDNS ? options.searchDomains : localOptions.searchDomains { - log.info("DNS: Using search domains \(searchDomains.maskedDescription)") - dnsSettings?.domainName = searchDomains.first - dnsSettings?.searchDomains = searchDomains - if !isGateway { - dnsSettings?.matchDomains = dnsSettings?.searchDomains - } - } - - // add direct routes to DNS servers - if !isGateway { - for server in dnsServers { - if server.contains(":") { - ipv6Settings?.includedRoutes?.insert(NEIPv6Route(destinationAddress: server, networkPrefixLength: 128), at: 0) - } else { - ipv4Settings?.includedRoutes?.insert(NEIPv4Route(destinationAddress: server, subnetMask: "255.255.255.255"), at: 0) - } - } - } - } - - var proxySettings: NEProxySettings? - if localOptions.isProxyEnabled ?? true { - if let httpsProxy = pullProxy ? options.httpsProxy : localOptions.httpsProxy { - proxySettings = NEProxySettings() - proxySettings?.httpsServer = httpsProxy.neProxy() - proxySettings?.httpsEnabled = true - log.info("Routing: Setting HTTPS proxy \(httpsProxy.address.maskedDescription):\(httpsProxy.port)") - } - if let httpProxy = pullProxy ? options.httpProxy : localOptions.httpProxy { - if proxySettings == nil { - proxySettings = NEProxySettings() - } - proxySettings?.httpServer = httpProxy.neProxy() - proxySettings?.httpEnabled = true - log.info("Routing: Setting HTTP proxy \(httpProxy.address.maskedDescription):\(httpProxy.port)") - } - if let pacURL = pullProxy ? options.proxyAutoConfigurationURL : localOptions.proxyAutoConfigurationURL { - if proxySettings == nil { - proxySettings = NEProxySettings() - } - proxySettings?.proxyAutoConfigurationURL = pacURL - proxySettings?.autoProxyConfigurationEnabled = true - log.info("Routing: Setting PAC \(pacURL.maskedDescription)") - } - - // only set if there is a proxy (proxySettings set to non-nil above) - if let bypass = pullProxy ? options.proxyBypassDomains : localOptions.proxyBypassDomains { - proxySettings?.exceptionList = bypass - log.info("Routing: Setting proxy by-pass list: \(bypass.maskedDescription)") - } - } - - // block LAN if desired - if routingPolicies?.contains(.blockLocal) ?? false { - let table = RoutingTable() - if isIPv4Gateway, - let gateway = table.defaultGateway4()?.gateway(), - let route = table.broadestRoute4(matchingDestination: gateway) { - - route.partitioned()?.forEach { - let destination = $0.network() - guard let netmask = $0.networkMask() else { - return - } - - log.info("Block local: Suppressing IPv4 route \(destination)/\($0.prefix())") - - let included = NEIPv4Route(destinationAddress: destination, subnetMask: netmask) - included.gatewayAddress = options.ipv4?.defaultGateway - ipv4Settings?.includedRoutes?.append(included) - } - } - if isIPv6Gateway, - let gateway = table.defaultGateway6()?.gateway(), - let route = table.broadestRoute6(matchingDestination: gateway) { - - route.partitioned()?.forEach { - let destination = $0.network() - let prefix = $0.prefix() - - log.info("Block local: Suppressing IPv6 route \(destination)/\($0.prefix())") - - let included = NEIPv6Route(destinationAddress: destination, networkPrefixLength: prefix as NSNumber) - included.gatewayAddress = options.ipv6?.defaultGateway - ipv6Settings?.includedRoutes?.append(included) - } - } - } - - let newSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress) - newSettings.ipv4Settings = ipv4Settings - newSettings.ipv6Settings = ipv6Settings - newSettings.dnsSettings = dnsSettings - newSettings.proxySettings = proxySettings - if let mtu = localOptions.mtu, mtu > 0 { - newSettings.mtu = NSNumber(value: mtu) - } - - setTunnelNetworkSettings(newSettings, completionHandler: completionHandler) + setTunnelNetworkSettings(newSettings.build(), completionHandler: completionHandler) } } @@ -948,12 +734,6 @@ extension OpenVPNTunnelProvider { } } -private extension Proxy { - func neProxy() -> NEProxyServer { - return NEProxyServer(address: address, port: Int(port)) - } -} - private extension NEPacketTunnelProvider { func forceExitOnMac() { #if os(macOS) diff --git a/Sources/TunnelKitOpenVPNCore/ConfigurationParser.swift b/Sources/TunnelKitOpenVPNCore/ConfigurationParser.swift index c9e4d1b..1d7a94e 100644 --- a/Sources/TunnelKitOpenVPNCore/ConfigurationParser.swift +++ b/Sources/TunnelKitOpenVPNCore/ConfigurationParser.swift @@ -732,6 +732,28 @@ extension OpenVPN { } } + // MARK: Post-processing + + // prepend search domains with main domain (if set) + if let domain = optDomain { + if optSearchDomains == nil { + optSearchDomains = [domain] + } else { + optSearchDomains?.insert(domain, at: 0) + } + } + + // ensure that non-nil network settings also imply non-empty + if let array = optDNSServers { + assert(!array.isEmpty) + } + if let array = optSearchDomains { + assert(!array.isEmpty) + } + if let array = optProxyBypass { + assert(!array.isEmpty) + } + // var sessionBuilder = ConfigurationBuilder() @@ -887,15 +909,6 @@ extension OpenVPN { ) } - // prepend search domains with main domain (if set) - if let domain = optDomain { - if optSearchDomains == nil { - optSearchDomains = [domain] - } else { - optSearchDomains?.insert(domain, at: 0) - } - } - sessionBuilder.dnsServers = optDNSServers sessionBuilder.searchDomains = optSearchDomains sessionBuilder.httpProxy = optHTTPProxy diff --git a/Sources/TunnelKitOpenVPNProtocol/OpenVPNSession.swift b/Sources/TunnelKitOpenVPNProtocol/OpenVPNSession.swift index 91bc371..8ed2e0e 100644 --- a/Sources/TunnelKitOpenVPNProtocol/OpenVPNSession.swift +++ b/Sources/TunnelKitOpenVPNProtocol/OpenVPNSession.swift @@ -944,7 +944,7 @@ public class OpenVPNSession: Session { return } reply = optionalReply - log.debug("Received PUSH_REPLY: \"\(reply.maskedDescription)\"") + log.debug("Received PUSH_REPLY: \"\(reply)\"") if let framing = reply.options.compressionFraming, let compression = reply.options.compressionAlgorithm { switch compression {