Skip to content

Commit a9a0189

Browse files
committed
Enable custom Shadowsocks port selection on entry servers in multihop
1 parent 862b958 commit a9a0189

12 files changed

+48
-41
lines changed

ios/MullvadREST/Relay/ObfuscatorPortSelector.swift

+22-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ import MullvadSettings
1010
import MullvadTypes
1111

1212
struct ObfuscatorPortSelection {
13-
let relays: REST.ServerRelaysResponse
13+
let entryRelays: REST.ServerRelaysResponse
14+
let exitRelays: REST.ServerRelaysResponse
1415
let port: RelayConstraint<UInt16>
1516
let method: WireGuardObfuscationState
17+
18+
var wireguard: REST.ServerWireguardTunnels {
19+
exitRelays.wireguard
20+
}
1621
}
1722

1823
struct ObfuscatorPortSelector {
@@ -22,7 +27,9 @@ struct ObfuscatorPortSelector {
2227
tunnelSettings: LatestTunnelSettings,
2328
connectionAttemptCount: UInt
2429
) throws -> ObfuscatorPortSelection {
25-
var relays = relays
30+
var entryRelays = relays
31+
var exitRelays = relays
32+
2633
var port = tunnelSettings.relayConstraints.port
2734
let obfuscationMethod = ObfuscationMethodSelector.obfuscationMethodBy(
2835
connectionAttemptCount: connectionAttemptCount,
@@ -36,7 +43,13 @@ struct ObfuscatorPortSelector {
3643
connectionAttemptCount: connectionAttemptCount
3744
)
3845
case .shadowsocks:
39-
relays = obfuscateShadowsocksRelays(tunnelSettings: tunnelSettings)
46+
let filteredRelays = obfuscateShadowsocksRelays(tunnelSettings: tunnelSettings)
47+
if tunnelSettings.tunnelMultihopState.isEnabled {
48+
entryRelays = filteredRelays
49+
} else {
50+
exitRelays = filteredRelays
51+
}
52+
4053
port = obfuscateShadowsocksPort(
4154
tunnelSettings: tunnelSettings,
4255
shadowsocksPortRanges: relays.wireguard.shadowsocksPortRanges
@@ -45,7 +58,12 @@ struct ObfuscatorPortSelector {
4558
break
4659
}
4760

48-
return ObfuscatorPortSelection(relays: relays, port: port, method: obfuscationMethod)
61+
return ObfuscatorPortSelection(
62+
entryRelays: entryRelays,
63+
exitRelays: exitRelays,
64+
port: port,
65+
method: obfuscationMethod
66+
)
4967
}
5068

5169
private func obfuscateShadowsocksRelays(tunnelSettings: LatestTunnelSettings) -> REST.ServerRelaysResponse {

ios/MullvadREST/Relay/RelayPicking.swift

+5-14
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import Network
1212

1313
protocol RelayPicking {
1414
var obfuscation: ObfuscatorPortSelection { get }
15-
var relays: REST.ServerRelaysResponse { get }
1615
var constraints: RelayConstraints { get }
1716
var connectionAttemptCount: UInt { get }
1817
var daitaSettings: DAITASettings { get }
@@ -27,7 +26,7 @@ extension RelayPicking {
2726
) throws -> SelectedRelay {
2827
var match = try RelaySelector.WireGuard.pickCandidate(
2928
from: candidates,
30-
relays: relays,
29+
wireguard: obfuscation.wireguard,
3130
portConstraint: useObfuscatedPortIfAvailable ? obfuscation.port : constraints.port,
3231
numberOfFailedAttempts: connectionAttemptCount,
3332
closeTo: location
@@ -46,7 +45,7 @@ extension RelayPicking {
4645

4746
private func applyShadowsocksIpAddress(in match: RelaySelectorMatch) -> RelaySelectorMatch {
4847
let port = match.endpoint.ipv4Relay.port
49-
let portRanges = RelaySelector.parseRawPortRanges(relays.wireguard.shadowsocksPortRanges)
48+
let portRanges = RelaySelector.parseRawPortRanges(obfuscation.wireguard.shadowsocksPortRanges)
5049
let portIsWithinRange = portRanges.contains(where: { $0.contains(port) })
5150

5251
var endpoint = match.endpoint
@@ -76,15 +75,11 @@ struct SinglehopPicker: RelayPicking {
7675
let connectionAttemptCount: UInt
7776
let daitaSettings: DAITASettings
7877

79-
var relays: REST.ServerRelaysResponse {
80-
obfuscation.relays
81-
}
82-
8378
func pick() throws -> SelectedRelays {
8479
do {
8580
let exitCandidates = try RelaySelector.WireGuard.findCandidates(
8681
by: constraints.exitLocations,
87-
in: relays,
82+
in: obfuscation.exitRelays,
8883
filterConstraint: constraints.filter,
8984
daitaEnabled: daitaSettings.daitaState.isEnabled
9085
)
@@ -114,14 +109,10 @@ struct MultihopPicker: RelayPicking {
114109
let connectionAttemptCount: UInt
115110
let daitaSettings: DAITASettings
116111

117-
var relays: REST.ServerRelaysResponse {
118-
obfuscation.relays
119-
}
120-
121112
func pick() throws -> SelectedRelays {
122113
let exitCandidates = try RelaySelector.WireGuard.findCandidates(
123114
by: constraints.exitLocations,
124-
in: relays,
115+
in: obfuscation.exitRelays,
125116
filterConstraint: constraints.filter,
126117
daitaEnabled: false
127118
)
@@ -153,7 +144,7 @@ struct MultihopPicker: RelayPicking {
153144
do {
154145
let entryCandidates = try RelaySelector.WireGuard.findCandidates(
155146
by: daitaSettings.isAutomaticRouting ? .any : constraints.entryLocations,
156-
in: relays,
147+
in: obfuscation.entryRelays,
157148
filterConstraint: constraints.filter,
158149
daitaEnabled: daitaSettings.daitaState.isEnabled
159150
)

ios/MullvadREST/Relay/RelaySelector+Wireguard.swift

+8-8
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ extension RelaySelector {
3131
/// Picks a random relay from a list.
3232
public static func pickCandidate(
3333
from relayWithLocations: [RelayWithLocation<REST.ServerRelay>],
34-
relays: REST.ServerRelaysResponse,
34+
wireguard: REST.ServerWireguardTunnels,
3535
portConstraint: RelayConstraint<UInt16>,
3636
numberOfFailedAttempts: UInt,
3737
closeTo referenceLocation: Location? = nil
3838
) throws -> RelaySelectorMatch {
3939
let port = try evaluatePort(
40-
relays: relays,
4140
portConstraint: portConstraint,
41+
rawPortRanges: wireguard.portRanges,
4242
numberOfFailedAttempts: numberOfFailedAttempts
4343
)
4444

@@ -54,7 +54,7 @@ extension RelaySelector {
5454
throw NoRelaysSatisfyingConstraintsError(.relayConstraintNotMatching)
5555
}
5656

57-
return createMatch(for: relayWithLocation, port: port, relays: relays)
57+
return createMatch(for: relayWithLocation, port: port, wireguard: wireguard)
5858
}
5959

6060
public static func closestRelay(
@@ -96,13 +96,13 @@ extension RelaySelector {
9696
}
9797

9898
private static func evaluatePort(
99-
relays: REST.ServerRelaysResponse,
10099
portConstraint: RelayConstraint<UInt16>,
100+
rawPortRanges: [[UInt16]],
101101
numberOfFailedAttempts: UInt
102102
) throws -> UInt16 {
103103
let port = applyPortConstraint(
104104
portConstraint,
105-
rawPortRanges: relays.wireguard.portRanges,
105+
rawPortRanges: rawPortRanges,
106106
numberOfFailedAttempts: numberOfFailedAttempts
107107
)
108108

@@ -116,16 +116,16 @@ extension RelaySelector {
116116
private static func createMatch(
117117
for relayWithLocation: RelayWithLocation<REST.ServerRelay>,
118118
port: UInt16,
119-
relays: REST.ServerRelaysResponse
119+
wireguard: REST.ServerWireguardTunnels
120120
) -> RelaySelectorMatch {
121121
let endpoint = MullvadEndpoint(
122122
ipv4Relay: IPv4Endpoint(
123123
ip: relayWithLocation.relay.ipv4AddrIn,
124124
port: port
125125
),
126126
ipv6Relay: nil,
127-
ipv4Gateway: relays.wireguard.ipv4Gateway,
128-
ipv6Gateway: relays.wireguard.ipv6Gateway,
127+
ipv4Gateway: wireguard.ipv4Gateway,
128+
ipv6Gateway: wireguard.ipv6Gateway,
129129
publicKey: relayWithLocation.relay.publicKey
130130
)
131131

ios/MullvadVPN.xcodeproj/project.pbxproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -4251,12 +4251,12 @@
42514251
7ACE19102C1C349200260BB6 /* MultihopDecisionFlow.swift */,
42524252
F0F3161A2BF358590078DBCF /* NoRelaysSatisfyingConstraintsError.swift */,
42534253
7AD63A3A2CD5278900445268 /* ObfuscationMethodSelector.swift */,
4254+
7AD63A382CD520FD00445268 /* ObfuscatorPortSelector.swift */,
42544255
5820675A26E6576800655B05 /* RelayCache.swift */,
42554256
7A3AD5002C1068A800E9AD90 /* RelayPicking.swift */,
42564257
F0DDE4282B220A15006B57A7 /* RelaySelector.swift */,
42574258
F0B894F42BF7528700817A42 /* RelaySelector+Shadowsocks.swift */,
42584259
F0B894F22BF7526700817A42 /* RelaySelector+Wireguard.swift */,
4259-
7AD63A382CD520FD00445268 /* ObfuscatorPortSelector.swift */,
42604260
5824037F2A827DF300163DE8 /* RelaySelectorProtocol.swift */,
42614261
F0F316182BF3572B0078DBCF /* RelaySelectorResult.swift */,
42624262
7AEBA5292C2179F20018BEC5 /* RelaySelectorWrapper.swift */,

ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift

+1-3
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,12 @@ final class VPNSettingsDataSource: UITableViewDiffableDataSource<
9292
}
9393

9494
static var wireGuardObfuscation: [Item] {
95-
var items: [Item] = [
95+
[
9696
.wireGuardObfuscationAutomatic,
9797
.wireGuardObfuscationShadowsocks,
9898
.wireGuardObfuscationUdpOverTcp,
9999
.wireGuardObfuscationOff,
100100
]
101-
102-
return items
103101
}
104102

105103
static var wireGuardObfuscationPort: [Item] {

ios/MullvadVPNTests/MullvadREST/Relay/ObfuscatorPortSelectorTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ final class ObfuscatorPortSelectorTests: XCTestCase {
153153
!relay.shadowsocksExtraAddrIn.isNil
154154
}
155155

156-
XCTAssertEqual(obfuscationResult.relays.wireguard.relays.count, relaysWithExtraAddresses.count)
156+
XCTAssertEqual(obfuscationResult.wireguard.relays.count, relaysWithExtraAddresses.count)
157157
}
158158

159159
func testObfuscateShadowsocksRelayFilteringWithPortInsideDefaultRanges() throws {
@@ -172,6 +172,6 @@ final class ObfuscatorPortSelectorTests: XCTestCase {
172172
connectionAttemptCount: 0
173173
)
174174

175-
XCTAssertEqual(obfuscationResult.relays.wireguard.relays.count, sampleRelays.wireguard.relays.count)
175+
XCTAssertEqual(obfuscationResult.wireguard.relays.count, sampleRelays.wireguard.relays.count)
176176
}
177177
}

ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ extension RelaySelectorTests {
304304

305305
return try RelaySelector.WireGuard.pickCandidate(
306306
from: candidates,
307-
relays: relays,
307+
wireguard: relays.wireguard,
308308
portConstraint: constraints.port,
309309
numberOfFailedAttempts: failedAttemptCount
310310
)

ios/PacketTunnelCoreTests/AppMessageHandlerTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ final class AppMessageHandlerTests: XCTestCase {
9191

9292
let match = try RelaySelector.WireGuard.pickCandidate(
9393
from: candidates,
94-
relays: ServerRelaysResponseStubs.sampleRelays,
94+
wireguard: ServerRelaysResponseStubs.sampleRelays.wireguard,
9595
portConstraint: relayConstraints.port,
9696
numberOfFailedAttempts: 0
9797
)

ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
3131
filterConstraint: relayConstraints.filter,
3232
daitaEnabled: false
3333
),
34-
relays: ServerRelaysResponseStubs.sampleRelays,
34+
wireguard: ServerRelaysResponseStubs.sampleRelays.wireguard,
3535
portConstraint: relayConstraints.port,
3636
numberOfFailedAttempts: 0
3737
)
@@ -43,7 +43,7 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
4343
filterConstraint: relayConstraints.filter,
4444
daitaEnabled: false
4545
),
46-
relays: ServerRelaysResponseStubs.sampleRelays,
46+
wireguard: ServerRelaysResponseStubs.sampleRelays.wireguard,
4747
portConstraint: relayConstraints.port,
4848
numberOfFailedAttempts: 0
4949
)

ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
3030
filterConstraint: relayConstraints.filter,
3131
daitaEnabled: false
3232
),
33-
relays: ServerRelaysResponseStubs.sampleRelays,
33+
wireguard: ServerRelaysResponseStubs.sampleRelays.wireguard,
3434
portConstraint: relayConstraints.port,
3535
numberOfFailedAttempts: 0
3636
)
@@ -42,7 +42,7 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
4242
filterConstraint: relayConstraints.filter,
4343
daitaEnabled: false
4444
),
45-
relays: ServerRelaysResponseStubs.sampleRelays,
45+
wireguard: ServerRelaysResponseStubs.sampleRelays.wireguard,
4646
portConstraint: relayConstraints.port,
4747
numberOfFailedAttempts: 0
4848
)

ios/PacketTunnelCoreTests/ProtocolObfuscatorTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ final class ProtocolObfuscatorTests: XCTestCase {
5858
let settings = settings(.automatic, obfuscationPort: .automatic)
5959

6060
try (UInt(0) ... 3).forEach { attempt in
61-
var obfuscatedEndpoint = obfuscator.obfuscate(endpoint, settings: settings, retryAttempts: attempt)
61+
let obfuscatedEndpoint = obfuscator.obfuscate(endpoint, settings: settings, retryAttempts: attempt)
6262

6363
switch attempt {
6464
case 0, 1:
6565
XCTAssertEqual(endpoint, obfuscatedEndpoint)
6666
case 2, 3:
67-
var obfuscationProtocol = try XCTUnwrap(obfuscator.tunnelObfuscator as? TunnelObfuscationStub)
67+
let obfuscationProtocol = try XCTUnwrap(obfuscator.tunnelObfuscator as? TunnelObfuscationStub)
6868
validate(obfuscatedEndpoint, against: obfuscationProtocol)
6969
default:
7070
XCTExpectFailure("Should not end up here, test setup is wrong")

ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class SingleHopEphemeralPeerExchangerTests: XCTestCase {
3030

3131
let match = try RelaySelector.WireGuard.pickCandidate(
3232
from: candidates,
33-
relays: ServerRelaysResponseStubs.sampleRelays,
33+
wireguard: ServerRelaysResponseStubs.sampleRelays.wireguard,
3434
portConstraint: relayConstraints.port,
3535
numberOfFailedAttempts: 0
3636
)

0 commit comments

Comments
 (0)