aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift26
-rw-r--r--WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift46
2 files changed, 30 insertions, 42 deletions
diff --git a/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift b/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift
index 02fbd4c..1b74d5d 100644
--- a/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift
+++ b/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift
@@ -8,6 +8,9 @@ class ErrorNotifier {
let activationAttemptId: String?
weak var tunnelProvider: NEPacketTunnelProvider?
+ var tunnelName: String?
+ var isActivateOnDemandEnabled = false
+
init(activationAttemptId: String?, tunnelProvider: NEPacketTunnelProvider) {
self.activationAttemptId = activationAttemptId
self.tunnelProvider = tunnelProvider
@@ -17,17 +20,13 @@ class ErrorNotifier {
func errorMessage(for error: PacketTunnelProviderError) -> (String, String)? {
switch error {
case .savedProtocolConfigurationIsInvalid:
- return ("Activation failure", "Could not retrieve tunnel information from the saved configuration")
- case .dnsResolutionFailure(let tunnelName, let isActivateOnDemandEnabled):
- if isActivateOnDemandEnabled {
- return ("DNS resolution failure", "This tunnel has Activate On Demand enabled, so activation might be retried. You may turn off Activate On Demand in the WireGuard app by navigating to: '\(tunnelName)' > Edit")
- } else {
- return ("DNS resolution failure", "One or more endpoint domains could not be resolved")
- }
+ return ("Activation failure", "Could not retrieve tunnel information from the saved configuration.")
+ case .dnsResolutionFailure:
+ return ("DNS resolution failure", "One or more endpoint domains could not be resolved.")
case .couldNotStartWireGuard:
- return ("Activation failure", "WireGuard backend could not be started")
+ return ("Activation failure", "WireGuard backend could not be started.")
case .coultNotSetNetworkSettings:
- return ("Activation failure", "Error applying network settings on the tunnel")
+ return ("Activation failure", "Error applying network settings on the tunnel.")
}
}
@@ -35,13 +34,16 @@ class ErrorNotifier {
guard let (title, message) = errorMessage(for: error) else { return }
if let activationAttemptId = activationAttemptId, let lastErrorFilePath = FileManager.networkExtensionLastErrorFileURL?.path {
// The tunnel was started from the app
- let errorMessageData = "\(activationAttemptId)\n\(title)\n\(message)".data(using: .utf8)
+ let onDemandMessage = isActivateOnDemandEnabled ? " This tunnel has Activate On Demand enabled, so this tunnel might be activated automatically. You may turn off Activate On Demand in the WireGuard app by navigating to: '\(tunnelName ?? "tunnel")' > Edit." : ""
+ let errorMessageData = "\(activationAttemptId)\n\(title)\n\(message)\(onDemandMessage)".data(using: .utf8)
FileManager.default.createFile(atPath: lastErrorFilePath, contents: errorMessageData, attributes: nil)
} else {
- // The tunnel was probably started from iOS Settings app
+ // The tunnel was probably started from iOS Settings app or activated on-demand
if let tunnelProvider = self.tunnelProvider {
// displayMessage() is deprecated, but there's no better alternative if invoked from iOS Settings
- tunnelProvider.displayMessage("\(title): \(message)") { _ in }
+ if !isActivateOnDemandEnabled { // If using activate-on-demand, don't use displayMessage
+ tunnelProvider.displayMessage("\(title): \(message)") { _ in }
+ }
}
}
}
diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
index f0ae3e7..f678ca7 100644
--- a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
+++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
@@ -8,7 +8,7 @@ import os.log
enum PacketTunnelProviderError: Error {
case savedProtocolConfigurationIsInvalid
- case dnsResolutionFailure(tunnelName: String, isActivateOnDemandEnabled: Bool)
+ case dnsResolutionFailure
case couldNotStartWireGuard
case coultNotSetNetworkSettings
}
@@ -54,9 +54,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
wg_log(.info, staticMessage: "Tunnel has Activate On Demand disabled")
}
+ errorNotifier.isActivateOnDemandEnabled = isActivateOnDemandEnabled
+ errorNotifier.tunnelName = tunnelName
+
let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
- guard let resolvedEndpoints = resolveDomainNames(endpoints: endpoints, isActivateOnDemandEnabled: isActivateOnDemandEnabled) else {
- let dnsError = PacketTunnelProviderError.dnsResolutionFailure(tunnelName: tunnelName, isActivateOnDemandEnabled: isActivateOnDemandEnabled)
+ guard let resolvedEndpoints = resolveDomainNames(endpoints: endpoints) else {
+ wg_log(.error, staticMessage: "Starting tunnel failed: DNS resolution failure")
+ let dnsError = PacketTunnelProviderError.dnsResolutionFailure
errorNotifier.notify(dnsError)
startTunnelCompletionHandler(dnsError)
return
@@ -148,34 +152,16 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}
}
- private func resolveDomainNames(endpoints: [Endpoint?], isActivateOnDemandEnabled: Bool) -> [Endpoint?]? {
- var resolvedEndpoints = [Endpoint?]()
- let dnsResolutionAttemptsCount = isActivateOnDemandEnabled ? 10 : 1
- var isDNSResolved = false
-
- for attemptIndex in 0 ..< dnsResolutionAttemptsCount {
- do {
- resolvedEndpoints = try DNSResolver.resolveSync(endpoints: endpoints)
- isDNSResolved = true
- } catch DNSResolverError.dnsResolutionFailed(let hostnames) {
- wg_log(.error, staticMessage: "Starting tunnel failed: DNS resolution failure")
- wg_log(.error, message: "Hostnames for which DNS resolution failed: \(hostnames.joined(separator: ", "))")
- } catch {
- // There can be no other errors from DNSResolver.resolveSync()
- fatalError()
- }
- if isDNSResolved {
- break
- } else {
- let isLastAttempt = attemptIndex == dnsResolutionAttemptsCount - 1
- if !isLastAttempt {
- Thread.sleep(forTimeInterval: 4 /* seconds */)
- wg_log(.error, message: "Retrying DNS resolution (Attempt \(attemptIndex + 2))")
- }
- }
+ private func resolveDomainNames(endpoints: [Endpoint?]) -> [Endpoint?]? {
+ do {
+ return try DNSResolver.resolveSync(endpoints: endpoints)
+ } catch DNSResolverError.dnsResolutionFailed(let hostnames) {
+ wg_log(.error, message: "DNS resolution failed for the following hostnames: \(hostnames.joined(separator: ", "))")
+ } catch {
+ // There can be no other errors from DNSResolver.resolveSync()
+ fatalError()
}
-
- return isDNSResolved ? resolvedEndpoints : nil
+ return nil
}
private func connect(interfaceName: String, settings: String, fileDescriptor: Int32) -> Int32 {