summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadREST/Relay/ObfuscationMethodSelector.swift1
-rw-r--r--ios/MullvadREST/Relay/ObfuscatorPortSelector.swift4
-rw-r--r--ios/MullvadSettings/WireGuardObfuscationSettings.swift13
-rw-r--r--ios/MullvadVPN/Classes/AccessbilityIdentifier.swift3
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift2
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift15
-rw-r--r--ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift81
-rw-r--r--ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift32
-rw-r--r--ios/MullvadVPNUITests/Pages/TunnelControlPage.swift1
-rw-r--r--ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift5
-rw-r--r--ios/MullvadVPNUITests/RelayTests.swift41
-rw-r--r--ios/PacketTunnelCore/Actor/ProtocolObfuscator.swift11
12 files changed, 183 insertions, 26 deletions
diff --git a/ios/MullvadREST/Relay/ObfuscationMethodSelector.swift b/ios/MullvadREST/Relay/ObfuscationMethodSelector.swift
index 069365b64e..dcc7cf05da 100644
--- a/ios/MullvadREST/Relay/ObfuscationMethodSelector.swift
+++ b/ios/MullvadREST/Relay/ObfuscationMethodSelector.swift
@@ -15,6 +15,7 @@ public struct ObfuscationMethodSelector {
connectionAttemptCount: UInt,
tunnelSettings: LatestTunnelSettings
) -> WireGuardObfuscationState {
+ // TODO: Revisit this when QUIC obfuscation is added
if tunnelSettings.wireGuardObfuscation.state == .automatic {
if connectionAttemptCount.isOrdered(nth: 3, forEverySetOf: 4) {
.shadowsocks
diff --git a/ios/MullvadREST/Relay/ObfuscatorPortSelector.swift b/ios/MullvadREST/Relay/ObfuscatorPortSelector.swift
index 988f6d00e3..0b1939927b 100644
--- a/ios/MullvadREST/Relay/ObfuscatorPortSelector.swift
+++ b/ios/MullvadREST/Relay/ObfuscatorPortSelector.swift
@@ -55,6 +55,10 @@ struct ObfuscatorPortSelector {
tunnelSettings: tunnelSettings,
shadowsocksPortRanges: relays.wireguard.shadowsocksPortRanges
)
+ #if DEBUG
+ case .quic:
+ port = .only(443)
+ #endif
default:
break
}
diff --git a/ios/MullvadSettings/WireGuardObfuscationSettings.swift b/ios/MullvadSettings/WireGuardObfuscationSettings.swift
index 9d7dc1103b..80a4a6d425 100644
--- a/ios/MullvadSettings/WireGuardObfuscationSettings.swift
+++ b/ios/MullvadSettings/WireGuardObfuscationSettings.swift
@@ -18,6 +18,9 @@ public enum WireGuardObfuscationState: Codable, Sendable {
case automatic
case udpOverTcp
case shadowsocks
+ #if DEBUG
+ case quic
+ #endif
case off
public init(from decoder: Decoder) throws {
@@ -42,14 +45,24 @@ public enum WireGuardObfuscationState: Codable, Sendable {
self = .udpOverTcp
case .shadowsocks:
self = .shadowsocks
+ #if DEBUG
+ case .quic:
+ self = .quic
+ #endif
case .off:
self = .off
}
}
+ #if DEBUG
+ public var isEnabled: Bool {
+ [.udpOverTcp, .shadowsocks, .quic].contains(self)
+ }
+ #else
public var isEnabled: Bool {
[.udpOverTcp, .shadowsocks].contains(self)
}
+ #endif
}
public enum WireGuardObfuscationUdpOverTcpPort: Codable, Equatable, CustomStringConvertible, Sendable {
diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
index 2b82be84cf..aeae92875e 100644
--- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
+++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
@@ -194,6 +194,9 @@ public enum AccessibilityIdentifier: Equatable {
case wireGuardObfuscationOff
case wireGuardObfuscationUdpOverTcp
case wireGuardObfuscationShadowsocks
+ #if DEBUG
+ case wireGuardObfuscationQuic
+ #endif
case wireGuardObfuscationUdpOverTcpPort
case wireGuardObfuscationShadowsocksPort
case wireGuardPort(UInt16?)
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift
index 974821fe25..fb77076abd 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift
@@ -324,7 +324,7 @@ private extension WireGuardObfuscationState {
switch self {
case .shadowsocks:
true
- case .on, .off, .automatic, .udpOverTcp:
+ case .on, .off, .automatic, .udpOverTcp, .quic:
false
}
}
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift
index f86242b756..eca4097f31 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift
@@ -224,6 +224,21 @@ final class VPNSettingsCellFactory: @preconcurrency CellFactoryProtocol {
self?.delegate?.showDetails(for: .wireguardOverShadowsocks)
}
+ #if DEBUG
+ case .wireGuardObfuscationQuic:
+ guard let cell = cell as? SelectableSettingsCell else { return }
+
+ cell.titleLabel.text = NSLocalizedString(
+ "WIREGUARD_OBFUSCATION_QUIC_LABEL",
+ tableName: "VPNSettings",
+ value: "QUIC",
+ comment: ""
+ )
+
+ cell.setAccessibilityIdentifier(item.accessibilityIdentifier)
+ cell.detailTitleLabel.setAccessibilityIdentifier(.wireGuardObfuscationQuic)
+ cell.applySubCellStyling()
+ #endif
case .wireGuardObfuscationOff:
guard let cell = cell as? SelectableSettingsCell else { return }
diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift
index 6126feaa4e..75f5e974a7 100644
--- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift
+++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift
@@ -83,6 +83,9 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
case wireGuardObfuscationAutomatic
case wireGuardObfuscationUdpOverTcp
case wireGuardObfuscationShadowsocks
+ #if DEBUG
+ case wireGuardObfuscationQuic
+ #endif
case wireGuardObfuscationOff
case wireGuardObfuscationPort(_ port: WireGuardObfuscationUdpOverTcpPort)
case quantumResistanceAutomatic
@@ -96,15 +99,26 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
return [.wireGuardPort(nil)] + defaultPorts + [.wireGuardCustomPort]
}
+ #if DEBUG
static var wireGuardObfuscation: [Item] {
[
.wireGuardObfuscationAutomatic,
.wireGuardObfuscationShadowsocks,
.wireGuardObfuscationUdpOverTcp,
+ .wireGuardObfuscationQuic,
.wireGuardObfuscationOff,
]
}
-
+ #else
+ static var wireGuardObfuscation: [Item] {
+ [
+ .wireGuardObfuscationAutomatic,
+ .wireGuardObfuscationShadowsocks,
+ .wireGuardObfuscationUdpOverTcp,
+ .wireGuardObfuscationOff,
+ ]
+ }
+ #endif
static var wireGuardObfuscationPort: [Item] {
[
.wireGuardObfuscationPort(.automatic),
@@ -120,58 +134,67 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
var accessibilityIdentifier: AccessibilityIdentifier {
switch self {
case .includeAllNetworks:
- return .includeAllNetworks
+ .includeAllNetworks
case .localNetworkSharing:
- return .localNetworkSharing
+ .localNetworkSharing
case .dnsSettings:
- return .dnsSettings
+ .dnsSettings
case .ipOverrides:
- return .ipOverrides
+ .ipOverrides
case let .wireGuardPort(port):
- return .wireGuardPort(port)
+ .wireGuardPort(port)
case .wireGuardCustomPort:
- return .wireGuardCustomPort
+ .wireGuardCustomPort
case .wireGuardObfuscationAutomatic:
- return .wireGuardObfuscationAutomatic
+ .wireGuardObfuscationAutomatic
case .wireGuardObfuscationUdpOverTcp:
- return .wireGuardObfuscationUdpOverTcp
+ .wireGuardObfuscationUdpOverTcp
case .wireGuardObfuscationShadowsocks:
- return .wireGuardObfuscationShadowsocks
+ .wireGuardObfuscationShadowsocks
+ #if DEBUG
+ case .wireGuardObfuscationQuic:
+ .wireGuardObfuscationQuic
+ #endif
case .wireGuardObfuscationOff:
- return .wireGuardObfuscationOff
+ .wireGuardObfuscationOff
case .wireGuardObfuscationPort:
- return .wireGuardObfuscationPort
+ .wireGuardObfuscationPort
case .quantumResistanceAutomatic:
- return .quantumResistanceAutomatic
+ .quantumResistanceAutomatic
case .quantumResistanceOn:
- return .quantumResistanceOn
+ .quantumResistanceOn
case .quantumResistanceOff:
- return .quantumResistanceOff
+ .quantumResistanceOff
}
}
var reuseIdentifier: CellReuseIdentifiers {
switch self {
case .includeAllNetworks:
- return .includeAllNetworks
+ .includeAllNetworks
case .localNetworkSharing:
- return .localNetworkSharing
+ .localNetworkSharing
case .dnsSettings:
- return .dnsSettings
+ .dnsSettings
case .ipOverrides:
- return .ipOverrides
+ .ipOverrides
case .wireGuardPort:
- return .wireGuardPort
+ .wireGuardPort
case .wireGuardCustomPort:
- return .wireGuardCustomPort
+ .wireGuardCustomPort
+ #if DEBUG
+ case .wireGuardObfuscationAutomatic, .wireGuardObfuscationOff, .wireGuardObfuscationQuic:
+ .wireGuardObfuscation
+ #else
case .wireGuardObfuscationAutomatic, .wireGuardObfuscationOff:
- return .wireGuardObfuscation
+ .wireGuardObfuscation
+ #endif
case .wireGuardObfuscationUdpOverTcp, .wireGuardObfuscationShadowsocks:
- return .wireGuardObfuscationOption
+ .wireGuardObfuscationOption
case .wireGuardObfuscationPort:
- return .wireGuardObfuscationPort
+ .wireGuardObfuscationPort
case .quantumResistanceAutomatic, .quantumResistanceOn, .quantumResistanceOff:
- return .quantumResistance
+ .quantumResistance
}
}
}
@@ -205,6 +228,9 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
case .off: .wireGuardObfuscationOff
case .on, .udpOverTcp: .wireGuardObfuscationUdpOverTcp
case .shadowsocks: .wireGuardObfuscationShadowsocks
+ #if DEBUG
+ case .quic: .wireGuardObfuscationQuic
+ #endif
}
let quantumResistanceItem: Item = switch viewModel.quantumResistance {
@@ -340,6 +366,11 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
case .wireGuardObfuscationShadowsocks:
selectObfuscationState(.shadowsocks)
delegate?.didUpdateTunnelSettings(TunnelSettingsUpdate.obfuscation(obfuscationSettings))
+ #if DEBUG
+ case .wireGuardObfuscationQuic:
+ selectObfuscationState(.quic)
+ delegate?.didUpdateTunnelSettings(TunnelSettingsUpdate.obfuscation(obfuscationSettings))
+ #endif
case .wireGuardObfuscationOff:
selectObfuscationState(.off)
delegate?.didUpdateTunnelSettings(TunnelSettingsUpdate.obfuscation(obfuscationSettings))
diff --git a/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift b/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift
index 246da1b07b..b6afffd79f 100644
--- a/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift
+++ b/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift
@@ -48,6 +48,38 @@ final class TunnelSettingsUpdateTests: XCTestCase {
))
}
+ func testApplyShadowsocksObfuscation() {
+ // Given:
+ var settings = LatestTunnelSettings()
+
+ // When:
+ let update = TunnelSettingsUpdate.obfuscation(WireGuardObfuscationSettings(
+ state: .shadowsocks
+ ))
+ update.apply(to: &settings)
+
+ // Then:
+ XCTAssertEqual(settings.wireGuardObfuscation, WireGuardObfuscationSettings(
+ state: .shadowsocks
+ ))
+ }
+
+ func testApplyQuicObfuscation() {
+ // Given:
+ var settings = LatestTunnelSettings()
+
+ // When:
+ let update = TunnelSettingsUpdate.obfuscation(WireGuardObfuscationSettings(
+ state: .quic
+ ))
+ update.apply(to: &settings)
+
+ // Then:
+ XCTAssertEqual(settings.wireGuardObfuscation, WireGuardObfuscationSettings(
+ state: .quic
+ ))
+ }
+
func testApplyRelayConstraints() {
// Given:
var settings = LatestTunnelSettings()
diff --git a/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift b/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift
index 85854163b7..9a1039dfcc 100644
--- a/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift
+++ b/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift
@@ -133,6 +133,7 @@ class TunnelControlPage: Page {
@discardableResult func verifyConnectingOverTCPAfterUDPAttempts() -> Self {
let connectionAttempts = waitForConnectionAttempts(4, timeout: 30)
+ // TODO: Revisit this when QUIC obfuscation is added
// Should do four connection attempts but due to UI bug sometimes only two are displayed, sometimes all four
if connectionAttempts.count == 4 { // Expected retries flow
for (attemptIndex, attempt) in connectionAttempts.enumerated() {
diff --git a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift
index 696dab259b..6ed78d2ce0 100644
--- a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift
+++ b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift
@@ -128,6 +128,11 @@ class VPNSettingsPage: Page {
return self
}
+ @discardableResult func tapWireGuardObufscationQuicCell() -> Self {
+ app.cells[AccessibilityIdentifier.wireGuardObfuscationQuic].tap()
+ return self
+ }
+
@discardableResult func tapWireGuardObfuscationOffCell() -> Self {
app.cells[AccessibilityIdentifier.wireGuardObfuscationOff].tap()
diff --git a/ios/MullvadVPNUITests/RelayTests.swift b/ios/MullvadVPNUITests/RelayTests.swift
index 8c6aedeeed..17c0da2d2e 100644
--- a/ios/MullvadVPNUITests/RelayTests.swift
+++ b/ios/MullvadVPNUITests/RelayTests.swift
@@ -324,6 +324,47 @@ class RelayTests: LoggedInWithTimeUITestCase {
.tapDisconnectButton()
}
+ func testWireGuardOverQuicManually() throws {
+ addTeardownBlock {
+ HeaderBar(self.app)
+ .tapSettingsButton()
+
+ SettingsPage(self.app)
+ .tapVPNSettingsCell()
+
+ VPNSettingsPage(self.app)
+ .tapWireGuardObfuscationExpandButton()
+ .tapWireGuardObfuscationOffCell()
+ }
+
+ HeaderBar(app)
+ .tapSettingsButton()
+
+ SettingsPage(app)
+ .tapVPNSettingsCell()
+
+ VPNSettingsPage(app)
+ .tapWireGuardObfuscationExpandButton()
+ .tapWireGuardObufscationQuicCell()
+ .tapBackButton()
+
+ SettingsPage(app)
+ .tapDoneButton()
+
+ TunnelControlPage(app)
+ .tapConnectButton()
+
+ allowAddVPNConfigurationsIfAsked()
+
+ TunnelControlPage(app)
+ .waitForConnectedLabel()
+
+ try Networking.verifyCanAccessInternet()
+
+ TunnelControlPage(app)
+ .tapDisconnectButton()
+ }
+
/// Test automatic switching to TCP is functioning when UDP traffic to relay is blocked. This test first connects to a realy to get the IP address of it, in order to block UDP traffic to this relay.
func testWireGuardOverTCPAutomatically() throws {
FirewallClient().removeRules()
diff --git a/ios/PacketTunnelCore/Actor/ProtocolObfuscator.swift b/ios/PacketTunnelCore/Actor/ProtocolObfuscator.swift
index 2a0ed7bf06..51070accf8 100644
--- a/ios/PacketTunnelCore/Actor/ProtocolObfuscator.swift
+++ b/ios/PacketTunnelCore/Actor/ProtocolObfuscator.swift
@@ -60,12 +60,23 @@ public class ProtocolObfuscator<Obfuscator: TunnelObfuscation>: ProtocolObfuscat
return .init(endpoint: endpoint, method: .off)
}
+ #if DEBUG
+ // TODO: Revisit this when QUIC obfuscation is available to use, use shadowsocks over 443 for the time being
+ let obfuscator = Obfuscator(
+ remoteAddress: endpoint.ipv4Relay.ip,
+ tcpPort: remotePort,
+ obfuscationProtocol: (obfuscationMethod == .shadowsocks || obfuscationMethod == .quic)
+ ? .shadowsocks
+ : .udpOverTcp
+ )
+ #else
// At this point, the only possible obfuscation methods should be either `.udpOverTcp` or `.shadowsocks`
let obfuscator = Obfuscator(
remoteAddress: endpoint.ipv4Relay.ip,
tcpPort: remotePort,
obfuscationProtocol: obfuscationMethod == .shadowsocks ? .shadowsocks : .udpOverTcp
)
+ #endif
obfuscator.start()
tunnelObfuscator = obfuscator