summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBug Magnet <marco.nikic@mullvad.net>2024-09-18 12:41:18 +0200
committerBug Magnet <marco.nikic@mullvad.net>2024-09-18 12:41:18 +0200
commit4dd0be399ea979202e1b5ea125ce0953e3790fbe (patch)
tree0b37bded666cb6ab1711c4ce5098ac03d0a80c50
parenteea642fa94d5244ab66bbdd320c98e003d9c479a (diff)
parentc5b0631a01d79b437d1a1b16b90930d8e4fe7bf1 (diff)
downloadmullvadvpn-4dd0be399ea979202e1b5ea125ce0953e3790fbe.tar.xz
mullvadvpn-4dd0be399ea979202e1b5ea125ce0953e3790fbe.zip
Merge branch 'fix-build-warnings-ios-784'
-rw-r--r--ios/MullvadREST/Transport/Shadowsocks/ShadowsocksRelaySelector.swift2
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj12
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift37
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift4
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift1
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift106
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsPromptAlertItem.swift32
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift143
-rw-r--r--ios/MullvadVPNTests/MullvadSettings/IPOverrideWrapperTests.swift8
-rw-r--r--ios/PacketTunnelCore/Actor/ConnectionConfigurationBuilder.swift142
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift39
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActor.swift39
12 files changed, 338 insertions, 227 deletions
diff --git a/ios/MullvadREST/Transport/Shadowsocks/ShadowsocksRelaySelector.swift b/ios/MullvadREST/Transport/Shadowsocks/ShadowsocksRelaySelector.swift
index 2cc3058798..c0d83bc701 100644
--- a/ios/MullvadREST/Transport/Shadowsocks/ShadowsocksRelaySelector.swift
+++ b/ios/MullvadREST/Transport/Shadowsocks/ShadowsocksRelaySelector.swift
@@ -43,6 +43,6 @@ final public class ShadowsocksRelaySelector: ShadowsocksRelaySelectorProtocol {
public func getBridges() throws -> REST.ServerShadowsocks? {
let cachedRelays = try relayCache.read()
- return RelaySelector.Shadowsocks.tcpBridge(from: try cachedRelays.relays)
+ return RelaySelector.Shadowsocks.tcpBridge(from: cachedRelays.relays)
}
}
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 3874f7550c..7e4fcbbfc2 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -862,6 +862,8 @@
F03580252A13842C00E5DAFD /* IncreasedHitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */; };
F03A69F72C2AD2D6000E2E7E /* TimeInterval+Timeout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03A69F62C2AD2D5000E2E7E /* TimeInterval+Timeout.swift */; };
F03A69F92C2AD414000E2E7E /* FormsheetPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03A69F82C2AD413000E2E7E /* FormsheetPresentationController.swift */; };
+ F041BE4F2C983C2B0083EC28 /* VPNSettingsPromptAlertItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F041BE4E2C983C2B0083EC28 /* VPNSettingsPromptAlertItem.swift */; };
+ F041BE532C9878B60083EC28 /* ConnectionConfigurationBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F041BE522C9878B60083EC28 /* ConnectionConfigurationBuilder.swift */; };
F04413612BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */; };
F04413622BA45CE30018A6EE /* CustomListLocationNodeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */; };
F04AF92D2C466013004A8314 /* EphemeralPeerNegotiationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04AF92C2C466013004A8314 /* EphemeralPeerNegotiationState.swift */; };
@@ -2077,6 +2079,8 @@
F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncreasedHitButton.swift; sourceTree = "<group>"; };
F03A69F62C2AD2D5000E2E7E /* TimeInterval+Timeout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TimeInterval+Timeout.swift"; sourceTree = "<group>"; };
F03A69F82C2AD413000E2E7E /* FormsheetPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormsheetPresentationController.swift; sourceTree = "<group>"; };
+ F041BE4E2C983C2B0083EC28 /* VPNSettingsPromptAlertItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsPromptAlertItem.swift; sourceTree = "<group>"; };
+ F041BE522C9878B60083EC28 /* ConnectionConfigurationBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionConfigurationBuilder.swift; sourceTree = "<group>"; };
F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomListLocationNodeBuilder.swift; sourceTree = "<group>"; };
F04AF92C2C466013004A8314 /* EphemeralPeerNegotiationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EphemeralPeerNegotiationState.swift; sourceTree = "<group>"; };
F04DD3D72C130DF600E03E28 /* TunnelSettingsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelSettingsManager.swift; sourceTree = "<group>"; };
@@ -2819,6 +2823,7 @@
587EB6732714520600123C75 /* VPNSettingsDataSourceDelegate.swift */,
7A6F2FAE2AFE36E7006D0856 /* VPNSettingsInfoButtonItem.swift */,
5871167E2910035700D41AAC /* VPNSettingsInteractor.swift */,
+ F041BE4E2C983C2B0083EC28 /* VPNSettingsPromptAlertItem.swift */,
58ACF6482655365700ACE4B7 /* VPNSettingsViewController.swift */,
587EB671271451E300123C75 /* VPNSettingsViewModel.swift */,
);
@@ -3084,6 +3089,9 @@
58BDEBA02A9CA14B00F578F2 /* AnyTask.swift */,
58F3F3652AA086A400D3B0A4 /* AutoCancellingTask.swift */,
583E60952A9F6D0800DC61EF /* ConfigurationBuilder.swift */,
+ F041BE522C9878B60083EC28 /* ConnectionConfigurationBuilder.swift */,
+ F05919742C45194B00C301F3 /* EphemeralPeerKey.swift */,
+ F04AF92C2C466013004A8314 /* EphemeralPeerNegotiationState.swift */,
5838322A2AC3EF9600EA2071 /* EventChannel.swift */,
580D6B892AB31AB400B2D6E0 /* NetworkPath+NetworkReachability.swift */,
58CF95A12AD6F35800B59F5D /* ObservedState.swift */,
@@ -3100,8 +3108,6 @@
583832282AC3DF1300EA2071 /* PacketTunnelActorCommand.swift */,
7AD0AA192AD69B6E00119E10 /* PacketTunnelActorProtocol.swift */,
44B3C4392BFE2C800079782C /* PacketTunnelActorReducer.swift */,
- F05919742C45194B00C301F3 /* EphemeralPeerKey.swift */,
- F04AF92C2C466013004A8314 /* EphemeralPeerNegotiationState.swift */,
A97D25AD2B0BB18100946B2D /* ProtocolObfuscator.swift */,
58E7A0312AA0715100C57861 /* Protocols */,
58ED3A132A7C199C0085CE65 /* StartOptions.swift */,
@@ -5495,6 +5501,7 @@
5838322B2AC3EF9600EA2071 /* EventChannel.swift in Sources */,
586C145A2AC4735F00245C01 /* PacketTunnelActor+Public.swift in Sources */,
F0DAC8AD2C16EFE400F80144 /* TunnelSettingsManager.swift in Sources */,
+ F041BE532C9878B60083EC28 /* ConnectionConfigurationBuilder.swift in Sources */,
58342C042AAB61FB003BA12D /* State+Extensions.swift in Sources */,
A95EEE382B722DFC00A8A39B /* PingStats.swift in Sources */,
583832272AC3193600EA2071 /* PacketTunnelActor+SleepCycle.swift in Sources */,
@@ -5573,6 +5580,7 @@
7AC8A3AF2ABC71D600DC4939 /* TermsOfServiceCoordinator.swift in Sources */,
58FF9FE22B075BA600E4C97D /* EditAccessMethodSectionIdentifier.swift in Sources */,
F0C2AEFD2A0BB5CC00986207 /* NotificationProviderIdentifier.swift in Sources */,
+ F041BE4F2C983C2B0083EC28 /* VPNSettingsPromptAlertItem.swift in Sources */,
7A58699B2B482FE200640D27 /* UITableViewCell+Disable.swift in Sources */,
7AB2B6702BA1EB8C00B03E3B /* ListCustomListViewController.swift in Sources */,
7A9CCCB72A96302800DD6A34 /* RevokedCoordinator.swift in Sources */,
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift
index 40fa74e0f6..5280cd00a5 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift
@@ -102,38 +102,9 @@ extension CustomDNSViewController: DNSSettingsDataSourceDelegate {
}
func showInfo(for item: VPNSettingsInfoButtonItem) {
- var message = NSAttributedString()
-
- switch item {
- case .contentBlockers:
- message = NSAttributedString(markdownString: NSLocalizedString(
- "VPN_SETTINGS_CONTENT_BLOCKERS_GENERAL",
- tableName: "ContentBlockers",
- value: """
- When this feature is enabled it stops the device from contacting certain \
- domains or websites known for distributing ads, malware, trackers and more. \
-
- This might cause issues on certain websites, services, and apps.
- Attention: this setting cannot be used in combination with **Use custom DNS server**.
- """,
- comment: ""
- ), options: MarkdownStylingOptions(font: .preferredFont(forTextStyle: .body)))
-
- case .blockMalware:
- message = NSAttributedString(markdownString: NSLocalizedString(
- "VPN_SETTINGS_CONTENT_BLOCKERS_MALWARE",
- tableName: "ContentBlockers",
- value: """
- Warning: The malware blocker is not an anti-virus and should not \
- be treated as such, this is just an extra layer of protection.
- """,
- comment: ""
- ), options: MarkdownStylingOptions(font: .preferredFont(forTextStyle: .body)))
-
- default:
- assertionFailure("No matching InfoButtonItem")
- }
-
- showInfo(with: message)
+ showInfo(with: NSAttributedString(
+ markdownString: item.description,
+ options: MarkdownStylingOptions(font: .preferredFont(forTextStyle: .body))
+ ))
}
}
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift
index 45dbc344ab..bd24a10f6d 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift
@@ -461,8 +461,8 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
header.accessibilityCustomActionName = title
header.isExpanded = isExpanded(.wireGuardPorts)
header.infoButtonHandler = { [weak self] in
- if let self {
- self.delegate?.showInfo(for: .wireGuardPorts)
+ if let self, let humanReadablePortRepresentation = delegate?.humanReadablePortRepresentation() {
+ self.delegate?.showInfo(for: .wireGuardPorts(humanReadablePortRepresentation))
}
}
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift
index f6482e80ef..84bf9795d0 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift
@@ -22,4 +22,5 @@ protocol VPNSettingsDataSourceDelegate: AnyObject {
func showIPOverrides()
func didSelectWireGuardPort(_ port: UInt16?)
func showPrompt(for: VPNSettingsPromptAlertItem, onSave: @escaping () -> Void, onDiscard: @escaping () -> Void)
+ func humanReadablePortRepresentation() -> String
}
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift
index f8cb79bb41..1ba6343015 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift
@@ -6,18 +6,112 @@
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//
-enum VPNSettingsInfoButtonItem {
+import Foundation
+
+enum VPNSettingsInfoButtonItem: CustomStringConvertible {
case contentBlockers
case blockMalware
- case wireGuardPorts
+ case wireGuardPorts(String)
case wireGuardObfuscation
case wireGuardObfuscationPort
case quantumResistance
case multihop
case daita
-}
-enum VPNSettingsPromptAlertItem {
- case daitaSettingIncompatibleWithSinglehop
- case daitaSettingIncompatibleWithMultihop
+ var description: String {
+ switch self {
+ case .contentBlockers:
+ NSLocalizedString(
+ "VPN_SETTINGS_CONTENT_BLOCKERS_GENERAL",
+ tableName: "ContentBlockers",
+ value: """
+ When this feature is enabled it stops the device from contacting certain \
+ domains or websites known for distributing ads, malware, trackers and more. \
+
+ This might cause issues on certain websites, services, and apps.
+ Attention: this setting cannot be used in combination with **Use custom DNS server**.
+ """,
+ comment: ""
+ )
+ case .blockMalware:
+ NSLocalizedString(
+ "VPN_SETTINGS_CONTENT_BLOCKERS_MALWARE",
+ tableName: "ContentBlockers",
+ value: """
+ Warning: The malware blocker is not an anti-virus and should not \
+ be treated as such, this is just an extra layer of protection.
+ """,
+ comment: ""
+ )
+ case let .wireGuardPorts(portsString):
+ String(
+ format: NSLocalizedString(
+ "VPN_SETTINGS_WIRE_GUARD_PORTS_GENERAL",
+ tableName: "WireGuardPorts",
+ value: """
+ The automatic setting will randomly choose from the valid port ranges shown below.
+ The custom port can be any value inside the valid ranges:
+ %@
+ """,
+ comment: ""
+ ),
+ portsString
+ )
+ case .wireGuardObfuscation:
+ NSLocalizedString(
+ "VPN_SETTINGS_WIRE_GUARD_OBFUSCATION_GENERAL",
+ tableName: "WireGuardObfuscation",
+ value: """
+ Obfuscation hides the WireGuard traffic inside another protocol. \
+ It can be used to help circumvent censorship and other types of filtering, \
+ where a plain WireGuard connect would be blocked.
+ """,
+ comment: ""
+ )
+ case .wireGuardObfuscationPort:
+ NSLocalizedString(
+ "VPN_SETTINGS_WIRE_GUARD_OBFUSCATION_PORT_GENERAL",
+ tableName: "WireGuardObfuscation",
+ value: "Which TCP port the UDP-over-TCP obfuscation protocol should connect to on the VPN server.",
+ comment: ""
+ )
+ case .quantumResistance:
+ NSLocalizedString(
+ "VPN_SETTINGS_QUANTUM_RESISTANCE_GENERAL",
+ tableName: "QuantumResistance",
+ value: """
+ This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers.
+ It does this by performing an extra key exchange using a quantum safe algorithm and mixing \
+ the result into WireGuard’s regular encryption.
+ This extra step uses approximately 500 kiB of traffic every time a new tunnel is established.
+ """,
+ comment: ""
+ )
+ case .multihop:
+ NSLocalizedString(
+ "MULTIHOP_INFORMATION_TEXT",
+ tableName: "Multihop",
+ value: """
+ Multihop routes your traffic into one WireGuard server and out another, making it harder to trace.
+ This results in increased latency but increases anonymity online.
+ """,
+ comment: ""
+ )
+ case .daita:
+ NSLocalizedString(
+ "DAITA_INFORMATION_TEXT",
+ tableName: "DAITA",
+ value: """
+ DAITA (Defence against AI-guided Traffic Analysis) hides patterns in your encrypted VPN traffic. \
+ If anyone is monitoring your connection, this makes it significantly harder for them to identify \
+ what websites you are visiting. It does this by carefully adding network noise and making all \
+ network packets the same size.
+ Attention: Since this increases your total network traffic, \
+ be cautious if you have a limited data plan. \
+ It can also negatively impact your network speed and battery usage.
+ """,
+ comment: ""
+ )
+ }
+ }
}
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsPromptAlertItem.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsPromptAlertItem.swift
new file mode 100644
index 0000000000..74cc90b8d8
--- /dev/null
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsPromptAlertItem.swift
@@ -0,0 +1,32 @@
+//
+// VPNSettingsPromptAlertItem.swift
+// MullvadVPN
+//
+// Created by Mojgan on 2024-09-16.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+enum VPNSettingsPromptAlertItem: CustomStringConvertible {
+ case daitaSettingIncompatibleWithSinglehop
+ case daitaSettingIncompatibleWithMultihop
+
+ var description: String {
+ switch self {
+ case .daitaSettingIncompatibleWithSinglehop:
+ """
+ DAITA isn’t available on the current server. After enabling, please go to the Switch \
+ location view and select a location that supports DAITA.
+ Attention: Since this increases your total network traffic, be cautious if you have a \
+ limited data plan. It can also negatively impact your network speed and battery usage.
+ """
+ case .daitaSettingIncompatibleWithMultihop:
+ """
+ DAITA isn’t available on the current entry server. After enabling, please go to the Switch \
+ location view and select an entry location that supports DAITA.
+ Attention: Since this increases your total network traffic, be cautious if you have a \
+ limited data plan. It can also negatively impact your network speed and battery usage.
+ """
+ }
+ }
+}
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift
index 201043c941..32facd0eca 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift
@@ -70,12 +70,31 @@ class VPNSettingsViewController: UITableViewController {
size: CGSize(width: 0, height: UIMetrics.TableView.sectionSpacing)
))
}
+}
+
+extension VPNSettingsViewController: VPNSettingsDataSourceDelegate {
+ func humanReadablePortRepresentation() -> String {
+ let ranges = interactor.cachedRelays?.relays.wireguard.portRanges ?? []
+ return ranges
+ .compactMap { range in
+ if let minPort = range.first, let maxPort = range.last {
+ return minPort == maxPort ? String(minPort) : "\(minPort)-\(maxPort)"
+ } else {
+ return nil
+ }
+ }
+ .joined(separator: ", ")
+ }
+
+ func didUpdateTunnelSettings(_ update: TunnelSettingsUpdate) {
+ interactor.updateSettings([update])
+ }
- private func showInfo(with message: String) {
+ func showInfo(for item: VPNSettingsInfoButtonItem) {
let presentation = AlertPresentation(
id: "vpn-settings-content-blockers-alert",
icon: .info,
- message: message,
+ message: item.description,
buttons: [
AlertAction(
title: NSLocalizedString(
@@ -92,107 +111,6 @@ class VPNSettingsViewController: UITableViewController {
alertPresenter.showAlert(presentation: presentation, animated: true)
}
- private func humanReadablePortRepresentation(_ ranges: [[UInt16]]) -> String {
- ranges
- .compactMap { range in
- if let minPort = range.first, let maxPort = range.last {
- return minPort == maxPort ? String(minPort) : "\(minPort)-\(maxPort)"
- } else {
- return nil
- }
- }
- .joined(separator: ", ")
- }
-}
-
-extension VPNSettingsViewController: VPNSettingsDataSourceDelegate {
- func didUpdateTunnelSettings(_ update: TunnelSettingsUpdate) {
- interactor.updateSettings([update])
- }
-
- // swiftlint:disable:next function_body_length
- func showInfo(for item: VPNSettingsInfoButtonItem) { switch item {
- case .wireGuardPorts:
- let portsString = humanReadablePortRepresentation(
- interactor.cachedRelays?.relays.wireguard.portRanges ?? []
- )
-
- showInfo(with: String(
- format: NSLocalizedString(
- "VPN_SETTINGS_WIRE_GUARD_PORTS_GENERAL",
- tableName: "WireGuardPorts",
- value: """
- The automatic setting will randomly choose from the valid port ranges shown below.
- The custom port can be any value inside the valid ranges:
- %@
- """,
- comment: ""
- ),
- portsString
- ))
-
- case .wireGuardObfuscation:
- showInfo(with: NSLocalizedString(
- "VPN_SETTINGS_WIRE_GUARD_OBFUSCATION_GENERAL",
- tableName: "WireGuardObfuscation",
- value: """
- Obfuscation hides the WireGuard traffic inside another protocol. \
- It can be used to help circumvent censorship and other types of filtering, \
- where a plain WireGuard connect would be blocked.
- """,
- comment: ""
- ))
-
- case .wireGuardObfuscationPort:
- showInfo(with: NSLocalizedString(
- "VPN_SETTINGS_WIRE_GUARD_OBFUSCATION_PORT_GENERAL",
- tableName: "WireGuardObfuscation",
- value: "Which TCP port the UDP-over-TCP obfuscation protocol should connect to on the VPN server.",
- comment: ""
- ))
-
- case .quantumResistance:
- showInfo(with: NSLocalizedString(
- "VPN_SETTINGS_QUANTUM_RESISTANCE_GENERAL",
- tableName: "QuantumResistance",
- value: """
- This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers.
- It does this by performing an extra key exchange using a quantum safe algorithm and mixing \
- the result into WireGuard’s regular encryption.
- This extra step uses approximately 500 kiB of traffic every time a new tunnel is established.
- """,
- comment: ""
- ))
-
- case .multihop:
- showInfo(with: NSLocalizedString(
- "MULTIHOP_INFORMATION_TEXT",
- tableName: "Multihop",
- value: """
- Multihop routes your traffic into one WireGuard server and out another, making it harder to trace.
- This results in increased latency but increases anonymity online.
- """,
- comment: ""
- ))
- case .daita:
- showInfo(with: NSLocalizedString(
- "DAITA_INFORMATION_TEXT",
- tableName: "DAITA",
- value: """
- DAITA (Defence against AI-guided Traffic Analysis) hides patterns in your encrypted VPN traffic. \
- If anyone is monitoring your connection, this makes it significantly harder for them to identify \
- what websites you are visiting. It does this by carefully adding network noise and making all \
- network packets the same size.
- Attention: Since this increases your total network traffic, be cautious if you have a limited data plan. \
- It can also negatively impact your network speed and battery usage.
- """,
- comment: ""
- ))
- default:
- assertionFailure("No matching InfoButtonItem")
- }
- }
-
func showDNSSettings() {
let viewController = CustomDNSViewController(interactor: interactor, alertPresenter: alertPresenter)
navigationController?.pushViewController(viewController, animated: true)
@@ -215,23 +133,6 @@ extension VPNSettingsViewController: VPNSettingsDataSourceDelegate {
onSave: @escaping () -> Void,
onDiscard: @escaping () -> Void
) {
- let messageString = switch item {
- case .daitaSettingIncompatibleWithSinglehop:
- """
- DAITA isn’t available on the current server. After enabling, please go to the Switch \
- location view and select a location that supports DAITA.
- Attention: Since this increases your total network traffic, be cautious if you have a \
- limited data plan. It can also negatively impact your network speed and battery usage.
- """
- case .daitaSettingIncompatibleWithMultihop:
- """
- DAITA isn’t available on the current entry server. After enabling, please go to the Switch \
- location view and select an entry location that supports DAITA.
- Attention: Since this increases your total network traffic, be cautious if you have a \
- limited data plan. It can also negatively impact your network speed and battery usage.
- """
- }
-
let presentation = AlertPresentation(
id: "vpn-settings-content-blockers-alert",
accessibilityIdentifier: .daitaPromptAlert,
@@ -239,7 +140,7 @@ extension VPNSettingsViewController: VPNSettingsDataSourceDelegate {
message: NSLocalizedString(
"VPN_SETTINGS_VPN_DAITA_ENABLE_TEXT",
tableName: "DAITA",
- value: messageString,
+ value: item.description,
comment: ""
),
buttons: [
diff --git a/ios/MullvadVPNTests/MullvadSettings/IPOverrideWrapperTests.swift b/ios/MullvadVPNTests/MullvadSettings/IPOverrideWrapperTests.swift
index c694f50f90..5f5648c06b 100644
--- a/ios/MullvadVPNTests/MullvadSettings/IPOverrideWrapperTests.swift
+++ b/ios/MullvadVPNTests/MullvadSettings/IPOverrideWrapperTests.swift
@@ -32,12 +32,12 @@ final class IPOverrideWrapperTests: XCTestCase {
let storedCache = try overrideWrapper.read()
// Assert that relay was overridden.
- let host1 = try storedCache.relays.wireguard.relays.first
+ let host1 = storedCache.relays.wireguard.relays.first
XCTAssertEqual(host1?.ipv4AddrIn, .loopback)
XCTAssertEqual(host1?.ipv6AddrIn, .broadcast)
// Assert that relay was NOT overridden.
- let host2 = try storedCache.relays.wireguard.relays.last
+ let host2 = storedCache.relays.wireguard.relays.last
XCTAssertEqual(host2?.ipv4AddrIn, .any)
XCTAssertEqual(host2?.ipv6AddrIn, .any)
}
@@ -62,11 +62,11 @@ final class IPOverrideWrapperTests: XCTestCase {
let storedCache = try overrideWrapper.read()
// Assert that relay was overridden.
- let host1 = try storedCache.relays.bridge.relays.first
+ let host1 = storedCache.relays.bridge.relays.first
XCTAssertEqual(host1?.ipv4AddrIn, .loopback)
// Assert that relay was NOT overridden.
- let host2 = try storedCache.relays.bridge.relays.last
+ let host2 = storedCache.relays.bridge.relays.last
XCTAssertEqual(host2?.ipv4AddrIn, .any)
}
}
diff --git a/ios/PacketTunnelCore/Actor/ConnectionConfigurationBuilder.swift b/ios/PacketTunnelCore/Actor/ConnectionConfigurationBuilder.swift
new file mode 100644
index 0000000000..54eca7b54d
--- /dev/null
+++ b/ios/PacketTunnelCore/Actor/ConnectionConfigurationBuilder.swift
@@ -0,0 +1,142 @@
+//
+// ConnectionConfigurationBuilder.swift
+// PacketTunnelCore
+//
+// Created by Mojgan on 2024-09-16.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import WireGuardKitTypes
+
+protocol Configuration {
+ var name: String { get }
+ func make() throws -> ConnectionConfiguration
+}
+
+struct ConnectionConfiguration {
+ let entryConfiguration: TunnelAdapterConfiguration?
+ let exitConfiguration: TunnelAdapterConfiguration
+}
+
+struct ConnectionConfigurationBuilder {
+ enum ConnectionType {
+ case normal
+ case ephemeral(EphemeralPeerNegotiationState)
+ }
+
+ let type: ConnectionType
+ let settings: Settings
+ let connectionData: State.ConnectionData
+
+ func make() throws -> ConnectionConfiguration {
+ switch type {
+ case .normal:
+ try NormalConnectionConfiguration(settings: settings, connectionData: connectionData).make()
+ case let .ephemeral(ephemeralPeerNegotiationState):
+ try EphemeralConnectionConfiguration(
+ settings: settings,
+ connectionData: connectionData,
+ ephemeralPeerNegotiationState: ephemeralPeerNegotiationState
+ ).make()
+ }
+ }
+}
+
+private struct NormalConnectionConfiguration: Configuration {
+ let settings: Settings
+ let connectionData: State.ConnectionData
+
+ var name: String {
+ "Normal connection configuration"
+ }
+
+ private var activeKey: PrivateKey {
+ switch connectionData.keyPolicy {
+ case .useCurrent:
+ settings.privateKey
+ case let .usePrior(priorKey, _):
+ priorKey
+ }
+ }
+
+ func make() throws -> ConnectionConfiguration {
+ let entryConfiguration: TunnelAdapterConfiguration? = if connectionData.selectedRelays.entry != nil {
+ try ConfigurationBuilder(
+ privateKey: activeKey,
+ interfaceAddresses: settings.interfaceAddresses,
+ dns: settings.dnsServers,
+ endpoint: connectionData.connectedEndpoint,
+ allowedIPs: [
+ IPAddressRange(from: "\(connectionData.selectedRelays.exit.endpoint.ipv4Relay.ip)/32")!,
+ ]
+ ).makeConfiguration()
+ } else {
+ nil
+ }
+ let exitConfiguration = try ConfigurationBuilder(
+ privateKey: activeKey,
+ interfaceAddresses: settings.interfaceAddresses,
+ dns: settings.dnsServers,
+ endpoint: (entryConfiguration != nil)
+ ? connectionData.selectedRelays.exit.endpoint
+ : connectionData.connectedEndpoint,
+ allowedIPs: [
+ IPAddressRange(from: "0.0.0.0/0")!,
+ IPAddressRange(from: "::/0")!,
+ ]
+ ).makeConfiguration()
+
+ return ConnectionConfiguration(
+ entryConfiguration: entryConfiguration,
+ exitConfiguration: exitConfiguration
+ )
+ }
+}
+
+private struct EphemeralConnectionConfiguration: Configuration {
+ let settings: Settings
+ let connectionData: State.ConnectionData
+ let ephemeralPeerNegotiationState: EphemeralPeerNegotiationState
+
+ var name: String {
+ "Ephemeral connection configuration"
+ }
+
+ func make() throws -> ConnectionConfiguration {
+ switch ephemeralPeerNegotiationState {
+ case let .single(hop):
+ let exitConfiguration = try ConfigurationBuilder(
+ privateKey: hop.configuration.privateKey,
+ interfaceAddresses: settings.interfaceAddresses,
+ dns: settings.dnsServers,
+ endpoint: connectionData.connectedEndpoint,
+ allowedIPs: hop.configuration.allowedIPs,
+ preSharedKey: hop.configuration.preSharedKey
+ ).makeConfiguration()
+
+ return ConnectionConfiguration(entryConfiguration: nil, exitConfiguration: exitConfiguration)
+
+ case let .multi(firstHop, secondHop):
+ let entryConfiguration = try ConfigurationBuilder(
+ privateKey: firstHop.configuration.privateKey,
+ interfaceAddresses: settings.interfaceAddresses,
+ dns: settings.dnsServers,
+ endpoint: connectionData.connectedEndpoint,
+ allowedIPs: firstHop.configuration.allowedIPs,
+ preSharedKey: firstHop.configuration.preSharedKey
+ ).makeConfiguration()
+
+ let exitConfiguration = try ConfigurationBuilder(
+ privateKey: secondHop.configuration.privateKey,
+ interfaceAddresses: settings.interfaceAddresses,
+ dns: settings.dnsServers,
+ endpoint: secondHop.relay.endpoint,
+ allowedIPs: secondHop.configuration.allowedIPs,
+ preSharedKey: secondHop.configuration.preSharedKey
+ ).makeConfiguration()
+
+ return ConnectionConfiguration(entryConfiguration: entryConfiguration, exitConfiguration: exitConfiguration)
+ }
+ }
+}
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift
index 4bebc5c324..3b3c5ad560 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift
@@ -76,38 +76,23 @@ extension PacketTunnelActor {
switch configuration {
case let .single(hop):
- let exitConfiguration = try ConfigurationBuilder(
- privateKey: hop.configuration.privateKey,
- interfaceAddresses: settings.interfaceAddresses,
- dns: settings.dnsServers,
- endpoint: connectionData.connectedEndpoint,
- allowedIPs: hop.configuration.allowedIPs,
- preSharedKey: hop.configuration.preSharedKey
- ).makeConfiguration()
-
+ let exitConfiguration = try ConnectionConfigurationBuilder(
+ type: .ephemeral(.single(hop)),
+ settings: settings,
+ connectionData: connectionData
+ ).make().exitConfiguration
try await tunnelAdapter.start(configuration: exitConfiguration, daita: daitaConfiguration)
case let .multi(firstHop, secondHop):
- let entryConfiguration = try ConfigurationBuilder(
- privateKey: firstHop.configuration.privateKey,
- interfaceAddresses: settings.interfaceAddresses,
- dns: settings.dnsServers,
- endpoint: connectionData.connectedEndpoint,
- allowedIPs: firstHop.configuration.allowedIPs,
- preSharedKey: firstHop.configuration.preSharedKey
- ).makeConfiguration()
-
- let exitConfiguration = try ConfigurationBuilder(
- privateKey: secondHop.configuration.privateKey,
- interfaceAddresses: settings.interfaceAddresses,
- dns: settings.dnsServers,
- endpoint: secondHop.relay.endpoint,
- allowedIPs: secondHop.configuration.allowedIPs,
- preSharedKey: secondHop.configuration.preSharedKey
- ).makeConfiguration()
+ let connectionConfiguration = try ConnectionConfigurationBuilder(
+ type: .ephemeral(.multi(entry: firstHop, exit: secondHop)),
+ settings: settings,
+ connectionData: connectionData
+ ).make()
try await tunnelAdapter.startMultihop(
- entryConfiguration: entryConfiguration, exitConfiguration: exitConfiguration, daita: daitaConfiguration
+ entryConfiguration: connectionConfiguration.entryConfiguration,
+ exitConfiguration: connectionConfiguration.exitConfiguration, daita: daitaConfiguration
)
}
}
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift
index 0a4b9dc493..98dbeea262 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift
@@ -287,35 +287,11 @@ extension PacketTunnelActor {
) async throws {
guard let connectionState = try obfuscateConnection(nextRelays: nextRelays, settings: settings, reason: reason),
let targetState = state.targetStateForReconnect else { return }
-
- let activeKey = activeKey(from: connectionState, in: settings)
-
- let entryConfiguration: TunnelAdapterConfiguration? = if connectionState.selectedRelays.entry != nil {
- try ConfigurationBuilder(
- privateKey: activeKey,
- interfaceAddresses: settings.interfaceAddresses,
- dns: settings.dnsServers,
- endpoint: connectionState.connectedEndpoint,
- allowedIPs: [
- IPAddressRange(from: "\(connectionState.selectedRelays.exit.endpoint.ipv4Relay.ip)/32")!,
- ]
- ).makeConfiguration()
- } else {
- nil
- }
-
- let exitConfiguration = try ConfigurationBuilder(
- privateKey: activeKey,
- interfaceAddresses: settings.interfaceAddresses,
- dns: settings.dnsServers,
- endpoint: (entryConfiguration != nil)
- ? connectionState.selectedRelays.exit.endpoint
- : connectionState.connectedEndpoint,
- allowedIPs: [
- IPAddressRange(from: "0.0.0.0/0")!,
- IPAddressRange(from: "::/0")!,
- ]
- ).makeConfiguration()
+ let configuration = try ConnectionConfigurationBuilder(
+ type: .normal,
+ settings: settings,
+ connectionData: connectionState
+ ).make()
/*
Stop default path observer while updating WireGuard configuration since it will call the system method
@@ -341,8 +317,8 @@ extension PacketTunnelActor {
}
try await tunnelAdapter.startMultihop(
- entryConfiguration: entryConfiguration,
- exitConfiguration: exitConfiguration,
+ entryConfiguration: configuration.entryConfiguration,
+ exitConfiguration: configuration.exitConfiguration,
daita: daitaConfiguration
)
@@ -528,4 +504,5 @@ extension PacketTunnelActor {
}
extension PacketTunnelActor: PacketTunnelActorProtocol {}
+
// swiftlint:disable:this file_length