aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/WireGuard/VPN
diff options
context:
space:
mode:
authorRoopesh Chander <roop@roopc.net>2018-10-30 16:34:46 +0530
committerRoopesh Chander <roop@roopc.net>2018-10-30 18:36:28 +0530
commitfd241fac4087f1d7d559e5ff554fc359d6b9a77e (patch)
tree194d047114c849afd19354f07a5b681fd2b815b3 /WireGuard/WireGuard/VPN
parentNE: Print error when unable to start the tunnel (diff)
downloadwireguard-apple-fd241fac4087f1d7d559e5ff554fc359d6b9a77e.tar.xz
wireguard-apple-fd241fac4087f1d7d559e5ff554fc359d6b9a77e.zip
VPN: Refactor use of DNS resolution while activating the tunnel
Signed-off-by: Roopesh Chander <roop@roopc.net>
Diffstat (limited to 'WireGuard/WireGuard/VPN')
-rw-r--r--WireGuard/WireGuard/VPN/TunnelsManager.swift96
1 files changed, 56 insertions, 40 deletions
diff --git a/WireGuard/WireGuard/VPN/TunnelsManager.swift b/WireGuard/WireGuard/VPN/TunnelsManager.swift
index 9be3492..d9b2195 100644
--- a/WireGuard/WireGuard/VPN/TunnelsManager.swift
+++ b/WireGuard/WireGuard/VPN/TunnelsManager.swift
@@ -258,58 +258,74 @@ class TunnelContainer: NSObject {
fileprivate func startActivation(completionHandler: @escaping (Error?) -> Void) {
assert(status == .inactive)
+ assert(self.dnsResolver == nil)
+
guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
- let dnsResolver = DNSResolver(endpoints: endpoints)
- assert(self.dnsResolver == nil)
- if let endpoints = dnsResolver.resolveWithoutNetworkRequests() {
- guard (endpoints.contains(where: { $0 != nil })) else {
+
+ // Ensure there's a tunner server address we can give to iOS
+ guard (endpoints.contains(where: { $0 != nil })) else {
+ DispatchQueue.main.async { [weak self] in
+ self?.status = .inactive
completionHandler(TunnelsManagerError.noEndpoint)
- status = .inactive
- return
- }
- self.tunnelProvider.loadFromPreferences { [weak self] (error) in
- guard let s = self else { return }
- s.startObservingTunnelStatus()
- let session = (s.tunnelProvider.connection as! NETunnelProviderSession)
- do {
- let tunnelOptions = PacketTunnelOptionsGenerator.generateOptions(
- from: tunnelConfiguration, withResolvedEndpoints: endpoints)
- try session.startTunnel(options: tunnelOptions)
- } catch (let error) {
- os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
- completionHandler(error)
- s.status = .inactive
- return
- }
- completionHandler(nil)
}
+ return
+ }
+
+ // Resolve DNS and start the tunnel
+ let dnsResolver = DNSResolver(endpoints: endpoints)
+ let resolvedEndpoints = dnsResolver.resolveWithoutNetworkRequests()
+ if let resolvedEndpoints = resolvedEndpoints {
+ // If we don't have to make a DNS network request, we never
+ // change the status to .resolvingEndpointDomains
+ startActivation(tunnelConfiguration: tunnelConfiguration,
+ resolvedEndpoints: resolvedEndpoints,
+ completionHandler: completionHandler)
} else {
- self.dnsResolver = dnsResolver
status = .resolvingEndpointDomains
- dnsResolver.resolve { [weak self] endpoints in
+ self.dnsResolver = dnsResolver
+ dnsResolver.resolve { [weak self] resolvedEndpoints in
guard let s = self else { return }
assert(s.status == .resolvingEndpointDomains)
s.dnsResolver = nil
- guard let endpoints = endpoints else {
- completionHandler(TunnelsManagerError.dnsResolutionFailed)
+ guard let resolvedEndpoints = resolvedEndpoints else {
s.status = .inactive
+ completionHandler(TunnelsManagerError.dnsResolutionFailed)
return
}
- s.tunnelProvider.loadFromPreferences { [weak s] (error) in
- guard let s = s else { return }
- s.startObservingTunnelStatus()
- let session = (s.tunnelProvider.connection as! NETunnelProviderSession)
- do {
- let tunnelOptions = PacketTunnelOptionsGenerator.generateOptions(
- from: tunnelConfiguration, withResolvedEndpoints: endpoints)
- try session.startTunnel(options: tunnelOptions)
- } catch (let error) {
- os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
- s.status = .inactive
- return
- }
- }
+ s.startActivation(tunnelConfiguration: tunnelConfiguration,
+ resolvedEndpoints: resolvedEndpoints,
+ completionHandler: completionHandler)
+ }
+ }
+ }
+
+ fileprivate func startActivation(tunnelConfiguration: TunnelConfiguration,
+ resolvedEndpoints: [Endpoint?],
+ completionHandler: @escaping (Error?) -> Void) {
+ // resolvedEndpoints should contain only IP addresses, not any named endpoints
+ assert(resolvedEndpoints.allSatisfy { (resolvedEndpoint) in
+ guard let resolvedEndpoint = resolvedEndpoint else { return true }
+ switch (resolvedEndpoint.host) {
+ case .ipv4(_): return true
+ case .ipv6(_): return true
+ case .name(_, _): return false
+ }
+ })
+ // Start the tunnel
+ self.tunnelProvider.loadFromPreferences { [weak self] (error) in
+ guard let s = self else { return }
+ s.startObservingTunnelStatus()
+ let session = (s.tunnelProvider.connection as! NETunnelProviderSession)
+ do {
+ let tunnelOptions = PacketTunnelOptionsGenerator.generateOptions(
+ from: tunnelConfiguration, withResolvedEndpoints: resolvedEndpoints)
+ try session.startTunnel(options: tunnelOptions)
+ completionHandler(nil)
+ } catch (let error) {
+ os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
+ s.status = .inactive
+ completionHandler(error)
}
}
}