diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 214bb55ba930..a18975ab05a9 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -888,7 +888,7 @@ F06045EC2B2322A500B2D37A /* Jittered.swift in Sources */ = {isa = PBXBuildFile; fileRef = F06045EB2B2322A500B2D37A /* Jittered.swift */; }; F062B94D2C16E09700B6D47A /* TunnelSettingsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F062B94C2C16E09700B6D47A /* TunnelSettingsManagerTests.swift */; }; F0697C042C36B92700D7BAB3 /* PostQuantumKeyExchanging.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0697C032C36B92700D7BAB3 /* PostQuantumKeyExchanging.swift */; }; - F0697C062C37F73C00D7BAB3 /* PostQuantumKeyExchangingWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0697C052C37F73C00D7BAB3 /* PostQuantumKeyExchangingWrapper.swift */; }; + F0697C062C37F73C00D7BAB3 /* PostQuantumKeyExchangingFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0697C052C37F73C00D7BAB3 /* PostQuantumKeyExchangingFactory.swift */; }; F072D3CF2C07122400906F64 /* MultihopUpdaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F072D3CE2C07122400906F64 /* MultihopUpdaterTests.swift */; }; F072D3D22C071AD100906F64 /* ShadowsocksLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F072D3D12C071AD100906F64 /* ShadowsocksLoaderTests.swift */; }; F07BF2622A26279100042943 /* RedeemVoucherOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07BF2612A26279100042943 /* RedeemVoucherOperation.swift */; }; @@ -2185,7 +2185,7 @@ F06045EB2B2322A500B2D37A /* Jittered.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Jittered.swift; sourceTree = ""; }; F062B94C2C16E09700B6D47A /* TunnelSettingsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsManagerTests.swift; sourceTree = ""; }; F0697C032C36B92700D7BAB3 /* PostQuantumKeyExchanging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostQuantumKeyExchanging.swift; sourceTree = ""; }; - F0697C052C37F73C00D7BAB3 /* PostQuantumKeyExchangingWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostQuantumKeyExchangingWrapper.swift; sourceTree = ""; }; + F0697C052C37F73C00D7BAB3 /* PostQuantumKeyExchangingFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostQuantumKeyExchangingFactory.swift; sourceTree = ""; }; F072D3CE2C07122400906F64 /* MultihopUpdaterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultihopUpdaterTests.swift; sourceTree = ""; }; F072D3D12C071AD100906F64 /* ShadowsocksLoaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksLoaderTests.swift; sourceTree = ""; }; F07BF2572A26112D00042943 /* InputTextFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTextFormatterTests.swift; sourceTree = ""; }; @@ -3203,7 +3203,7 @@ 7AD0AA192AD69B6E00119E10 /* PacketTunnelActorProtocol.swift */, 44B3C4392BFE2C800079782C /* PacketTunnelActorReducer.swift */, F0697C032C36B92700D7BAB3 /* PostQuantumKeyExchanging.swift */, - F0697C052C37F73C00D7BAB3 /* PostQuantumKeyExchangingWrapper.swift */, + F0697C052C37F73C00D7BAB3 /* PostQuantumKeyExchangingFactory.swift */, A97D25AD2B0BB18100946B2D /* ProtocolObfuscator.swift */, 58E7A0312AA0715100C57861 /* Protocols */, 58ED3A132A7C199C0085CE65 /* StartOptions.swift */, @@ -5633,7 +5633,7 @@ buildActionMask = 2147483647; files = ( 58FE25F42AA9D730003D1918 /* PacketTunnelActor+Extensions.swift in Sources */, - F0697C062C37F73C00D7BAB3 /* PostQuantumKeyExchangingWrapper.swift in Sources */, + F0697C062C37F73C00D7BAB3 /* PostQuantumKeyExchangingFactory.swift in Sources */, 58DDA18F2ABC32380039C360 /* Timings.swift in Sources */, 58C7A4522A863FB50060C66F /* Pinger.swift in Sources */, 580D6B8C2AB3369300B2D6E0 /* BlockedStateErrorMapperProtocol.swift in Sources */, diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift index 9ea18a687420..2f24a1e1d11f 100644 --- a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift +++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift @@ -48,10 +48,7 @@ public actor PacketTunnelActor { let settingsReader: SettingsReaderProtocol let protocolObfuscator: ProtocolObfuscation - lazy var postQuantumKeyExchanging: PostQuantumKeyExchangingWrapper = { - PostQuantumKeyExchangingWrapper(packetTunnelActor: self) - }() - + var postQuantumKeyExchanging: PostQuantumKeyExchangingProtocol! nonisolated let eventChannel = EventChannel() public init( @@ -253,6 +250,8 @@ extension PacketTunnelActor { reason: ActorReconnectReason = .userInitiated ) async throws { let settings: Settings = try settingsReader.read() + postQuantumKeyExchanging = PostQuantumKeyExchangingFactory(rawValue: settings.multihopState) + .make(packetTunnelActor: self) if settings.quantumResistance.isEnabled { try await tryStartPostQuantumNegotiation(withSettings: settings, nextRelays: nextRelays, reason: reason) diff --git a/ios/PacketTunnelCore/Actor/PostQuantumKeyExchanging.swift b/ios/PacketTunnelCore/Actor/PostQuantumKeyExchanging.swift index e978a75889d1..9e1ef05552bd 100644 --- a/ios/PacketTunnelCore/Actor/PostQuantumKeyExchanging.swift +++ b/ios/PacketTunnelCore/Actor/PostQuantumKeyExchanging.swift @@ -9,7 +9,7 @@ import WireGuardKitTypes private let defaultGatewayAddressRange = [IPAddressRange(from: "10.64.0.1/32")!] -private let allTheTrafficRange = [IPAddressRange(from: "0.0.0.0/0")!, IPAddressRange(from: "::/0")!] +private let allTrafficRange = [IPAddressRange(from: "0.0.0.0/0")!, IPAddressRange(from: "::/0")!] protocol PostQuantumKeyExchangingProtocol { func negotiate( @@ -71,7 +71,7 @@ struct SingleHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol { interfaceAddresses: settings.interfaceAddresses, dns: settings.dnsServers, endpoint: connectionState.connectedEndpoint, - allowedIPs: allTheTrafficRange, + allowedIPs: allTrafficRange, preSharedKey: preSharedkey ) @@ -122,6 +122,8 @@ actor MultiHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol, Sendab return try? await negotiatingBetweenEntryAndExit(privateKey, entryPeerPresharedKey: preSharedkey) } else if state == .negotiatingBetweenEntryAndExit { return try? await connectToExit(with: preSharedkey, privateKey: privateKey) + } else if state == .connecting { + state = .initial } return nil } @@ -170,14 +172,13 @@ actor MultiHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol, Sendab settings: settings, reason: reason ) { - self.state = .negotiatingBetweenEntryAndExit let entryConfiguration: TunnelAdapterConfiguration? = if let entry = connectionState.selectedRelays.entry { try ConfigurationBuilder( privateKey: entryPeerNewPrivateKey, interfaceAddresses: settings.interfaceAddresses, dns: settings.dnsServers, endpoint: entry.endpoint, - allowedIPs: [IPAddressRange(from: "\(connectionState.selectedRelays.exit.endpoint.ipv4Relay)/32")!], + allowedIPs: [IPAddressRange(from: "\(connectionState.selectedRelays.exit.endpoint.ipv4Relay.ip)/32")!], preSharedKey: entryPeerPresharedKey ).makeConfiguration() } else { @@ -201,7 +202,7 @@ actor MultiHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol, Sendab } return nil } - + private func connectToExit(with preSharedkey: PreSharedKey, privateKey: PrivateKey) async throws -> State? { if let connectionState = try await packetTunnelActor.obfuscateConnection( nextRelays: nextRelays, @@ -229,7 +230,7 @@ actor MultiHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol, Sendab interfaceAddresses: settings.interfaceAddresses, dns: settings.dnsServers, endpoint: connectionState.selectedRelays.exit.endpoint, - allowedIPs: allTheTrafficRange + allowedIPs: allTrafficRange ).makeConfiguration() try await packetTunnelActor.tunnelAdapter.startMultihop( @@ -239,8 +240,11 @@ actor MultiHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol, Sendab await packetTunnelActor.stopDefaultPathObserver() - try? await packetTunnelActor.tunnelAdapter.startMultihop(exitConfiguration: exitConfiguration, entryConfiguration: entryConfiguration) - + try? await packetTunnelActor.tunnelAdapter.startMultihop( + exitConfiguration: exitConfiguration, + entryConfiguration: entryConfiguration + ) + self.state = .initial // Resume tunnel monitoring and use exit IPv4 gateway as a probe address. @@ -248,12 +252,9 @@ actor MultiHopPostQuantumKeyExchanging: PostQuantumKeyExchangingProtocol, Sendab // Restart default path observer and notify the observer with the current path that might have changed while // path observer was paused. await packetTunnelActor.startDefaultPathObserver(notifyObserverWithCurrentPath: false) - - - + return .connecting(connectionData) } return nil - } } diff --git a/ios/PacketTunnelCore/Actor/PostQuantumKeyExchangingFactory.swift b/ios/PacketTunnelCore/Actor/PostQuantumKeyExchangingFactory.swift new file mode 100644 index 000000000000..f2b663616aca --- /dev/null +++ b/ios/PacketTunnelCore/Actor/PostQuantumKeyExchangingFactory.swift @@ -0,0 +1,32 @@ +// +// PostQuantumKeyExchangingFactory.swift +// PacketTunnelCore +// +// Created by Mojgan on 2024-07-05. +// Copyright © 2024 Mullvad VPN AB. All rights reserved. +// +import MullvadSettings + +enum PostQuantumKeyExchangingFactory: Sendable { + typealias RawValue = MultihopState + + case singleHop, multihop + + init(rawValue: RawValue) { + switch rawValue { + case .on: + self = .multihop + case .off: + self = .singleHop + } + } + + func make(packetTunnelActor: PacketTunnelActor) -> PostQuantumKeyExchangingProtocol { + switch self { + case .multihop: + MultiHopPostQuantumKeyExchanging(packetTunnelActor: packetTunnelActor) + case .singleHop: + SingleHopPostQuantumKeyExchanging(packetTunnelActor: packetTunnelActor) + } + } +} diff --git a/ios/PacketTunnelCore/Actor/PostQuantumKeyExchangingWrapper.swift b/ios/PacketTunnelCore/Actor/PostQuantumKeyExchangingWrapper.swift deleted file mode 100644 index 980df149297b..000000000000 --- a/ios/PacketTunnelCore/Actor/PostQuantumKeyExchangingWrapper.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// PostQuantumKeyExchangingWrapper.swift -// PacketTunnelCore -// -// Created by Mojgan on 2024-07-05. -// Copyright © 2024 Mullvad VPN AB. All rights reserved. -// - -import WireGuardKitTypes - -struct PostQuantumKeyExchangingWrapper: PostQuantumKeyExchangingProtocol,Sendable { - let packetTunnelActor: PacketTunnelActor - let singleHop: SingleHopPostQuantumKeyExchanging - let multiHop: MultiHopPostQuantumKeyExchanging - - init(packetTunnelActor: PacketTunnelActor) { - self.packetTunnelActor = packetTunnelActor - singleHop = SingleHopPostQuantumKeyExchanging(packetTunnelActor: packetTunnelActor) - multiHop = MultiHopPostQuantumKeyExchanging(packetTunnelActor: packetTunnelActor) - } - - func negotiate(_ settings: Settings, nextRelays: NextRelays, reason: ActorReconnectReason) async throws -> State? { - switch settings.multihopState { - case .on: - try await multiHop.negotiate(settings, nextRelays: nextRelays, reason: reason) - case .off: - try await singleHop.negotiate(settings, nextRelays: nextRelays, reason: reason) - } - } - - func connect(with preSharedkey: PreSharedKey, privateKey: PrivateKey) async -> State? { - //add comment to mention maybe it causes the problem between changing state in multihop - guard let settings = try? packetTunnelActor.settingsReader.read() else { return nil } - return switch settings.multihopState { - case .on: - await multiHop.connect(with: preSharedkey, privateKey: privateKey) - case .off: - await singleHop.connect(with: preSharedkey, privateKey: privateKey) - } - } -}