TunnelsManager: account for no or many endpoints
This commit is contained in:
parent
bf6b2b6cb1
commit
145b524954
|
@ -21,8 +21,6 @@ class ErrorPresenter {
|
||||||
return ("Unable to remove tunnel", "Internal error")
|
return ("Unable to remove tunnel", "Internal error")
|
||||||
|
|
||||||
// TunnelActivationError
|
// TunnelActivationError
|
||||||
case TunnelActivationError.noEndpoint:
|
|
||||||
return ("Endpoint missing", "There must be at least one peer with an endpoint")
|
|
||||||
case TunnelActivationError.dnsResolutionFailed:
|
case TunnelActivationError.dnsResolutionFailed:
|
||||||
return ("DNS resolution failure", "One or more endpoint domains could not be resolved")
|
return ("DNS resolution failure", "One or more endpoint domains could not be resolved")
|
||||||
case TunnelActivationError.tunnelActivationFailed:
|
case TunnelActivationError.tunnelActivationFailed:
|
||||||
|
|
|
@ -48,19 +48,23 @@ class PacketTunnelOptionsGenerator {
|
||||||
|
|
||||||
// Remote address
|
// Remote address
|
||||||
|
|
||||||
let remoteAddress: String
|
/* iOS requires a tunnel endpoint, whereas in WireGuard it's valid for
|
||||||
if let firstEndpoint = resolvedEndpoints.compactMap({ $0 }).first {
|
* a tunnel to have no endpoint, or for there to be many endpoints, in
|
||||||
switch (firstEndpoint.host) {
|
* which case, displaying a single one in settings doesn't really
|
||||||
|
* make sense. So, we fill it in with this placeholder, which is not
|
||||||
|
* a valid IP address that will actually route over the Internet.
|
||||||
|
*/
|
||||||
|
var remoteAddress: String = "0.0.0.0"
|
||||||
|
let endpointsCompact = resolvedEndpoints.compactMap({ $0 })
|
||||||
|
if endpointsCompact.count == 1 {
|
||||||
|
switch (endpointsCompact.first!.host) {
|
||||||
case .ipv4(let address):
|
case .ipv4(let address):
|
||||||
remoteAddress = "\(address)"
|
remoteAddress = "\(address)"
|
||||||
case .ipv6(let address):
|
case .ipv6(let address):
|
||||||
remoteAddress = "\(address)"
|
remoteAddress = "\(address)"
|
||||||
default:
|
default:
|
||||||
fatalError("Endpoint must be resolved")
|
break
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// We don't have any peer with an endpoint
|
|
||||||
remoteAddress = ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options[.remoteAddress] = remoteAddress as NSObject
|
options[.remoteAddress] = remoteAddress as NSObject
|
||||||
|
|
|
@ -13,7 +13,6 @@ protocol TunnelsManagerDelegate: class {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TunnelActivationError: Error {
|
enum TunnelActivationError: Error {
|
||||||
case noEndpoint
|
|
||||||
case dnsResolutionFailed
|
case dnsResolutionFailed
|
||||||
case tunnelActivationFailed
|
case tunnelActivationFailed
|
||||||
case attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: TunnelStatus)
|
case attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: TunnelStatus)
|
||||||
|
@ -214,14 +213,20 @@ extension NETunnelProviderProtocol {
|
||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
let appId = Bundle.main.bundleIdentifier!
|
let appId = Bundle.main.bundleIdentifier!
|
||||||
let firstValidEndpoint = tunnelConfiguration.peers.first(where: { $0.endpoint != nil })?.endpoint
|
|
||||||
|
|
||||||
providerBundleIdentifier = "\(appId).network-extension"
|
providerBundleIdentifier = "\(appId).network-extension"
|
||||||
providerConfiguration = [
|
providerConfiguration = [
|
||||||
"tunnelConfiguration": serializedTunnelConfiguration,
|
"tunnelConfiguration": serializedTunnelConfiguration,
|
||||||
"tunnelConfigurationVersion": 1
|
"tunnelConfigurationVersion": 1
|
||||||
]
|
]
|
||||||
serverAddress = firstValidEndpoint?.stringRepresentation() ?? "Unspecified"
|
|
||||||
|
let endpoints = tunnelConfiguration.peers.compactMap({$0.endpoint})
|
||||||
|
if endpoints.count == 1 {
|
||||||
|
serverAddress = endpoints.first!.stringRepresentation()
|
||||||
|
} else if endpoints.isEmpty {
|
||||||
|
serverAddress = "Unspecified"
|
||||||
|
} else {
|
||||||
|
serverAddress = "Multiple endpoints"
|
||||||
|
}
|
||||||
username = tunnelConfiguration.interface.name
|
username = tunnelConfiguration.interface.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,15 +267,6 @@ class TunnelContainer: NSObject {
|
||||||
guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
|
guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
|
||||||
let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
|
let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
|
||||||
|
|
||||||
// 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(TunnelActivationError.noEndpoint)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve DNS and start the tunnel
|
// Resolve DNS and start the tunnel
|
||||||
let dnsResolver = DNSResolver(endpoints: endpoints)
|
let dnsResolver = DNSResolver(endpoints: endpoints)
|
||||||
let resolvedEndpoints = dnsResolver.resolveWithoutNetworkRequests()
|
let resolvedEndpoints = dnsResolver.resolveWithoutNetworkRequests()
|
||||||
|
|
Loading…
Reference in New Issue