From e85c91ed79f661f1be0ac0e6ed164d4bfd6ee678 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Thu, 25 Apr 2019 14:53:26 +0200 Subject: [PATCH 1/4] Upgrade TunnelKit for redirect-gateway --- Podfile | 4 ++-- Podfile.lock | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Podfile b/Podfile index 1d64e1f8..d4898787 100644 --- a/Podfile +++ b/Podfile @@ -5,8 +5,8 @@ use_frameworks! def shared_pods #pod 'TunnelKit', '~> 1.6.2' #pod 'TunnelKit/LZO', '~> 1.6.2' - pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => 'ef5180a' - pod 'TunnelKit/LZO', :git => 'https://github.com/keeshux/tunnelkit', :commit => 'ef5180a' + pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => '7382616' + pod 'TunnelKit/LZO', :git => 'https://github.com/keeshux/tunnelkit', :commit => '7382616' #pod 'TunnelKit', :path => '../../personal/tunnelkit' #pod 'TunnelKit/LZO', :path => '../../personal/tunnelkit' pod 'SSZipArchive' diff --git a/Podfile.lock b/Podfile.lock index 8acecd93..102f302a 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -17,8 +17,8 @@ PODS: DEPENDENCIES: - MBProgressHUD - SSZipArchive - - TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `ef5180a`) - - TunnelKit/LZO (from `https://github.com/keeshux/tunnelkit`, commit `ef5180a`) + - TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `7382616`) + - TunnelKit/LZO (from `https://github.com/keeshux/tunnelkit`, commit `7382616`) SPEC REPOS: https://github.com/cocoapods/specs.git: @@ -29,12 +29,12 @@ SPEC REPOS: EXTERNAL SOURCES: TunnelKit: - :commit: ef5180a + :commit: '7382616' :git: https://github.com/keeshux/tunnelkit CHECKOUT OPTIONS: TunnelKit: - :commit: ef5180a + :commit: '7382616' :git: https://github.com/keeshux/tunnelkit SPEC CHECKSUMS: @@ -44,6 +44,6 @@ SPEC CHECKSUMS: SwiftyBeaver: 4cc0080d2e23f980652e28978db11a5c9da39165 TunnelKit: a0b7eb151ae6d30788623df94d682ed90706940a -PODFILE CHECKSUM: 15e1a3ee168932349294032eeddea0f0713873a4 +PODFILE CHECKSUM: 15a7ba649b5eafa958016880cee196b53e08bf1f COCOAPODS: 1.6.1 From b3a509fbea2f75869a66a3c2c162ce405a89930b Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Thu, 25 Apr 2019 14:53:50 +0200 Subject: [PATCH 2/4] Show default gateway policy in configuration UI --- .../Scenes/ConfigurationViewController.swift | 15 ++++++++++++++- .../Resources/en.lproj/Localizable.strings | 1 + Passepartout/Sources/SwiftGen+Strings.swift | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Passepartout-iOS/Scenes/ConfigurationViewController.swift b/Passepartout-iOS/Scenes/ConfigurationViewController.swift index dad0cff9..580850c6 100644 --- a/Passepartout-iOS/Scenes/ConfigurationViewController.swift +++ b/Passepartout-iOS/Scenes/ConfigurationViewController.swift @@ -87,6 +87,7 @@ class ConfigurationViewController: UIViewController, TableModelHost { } else { networkRows = [] } + networkRows.insert(.defaultGateway, at: 0) networkRows.append(.dnsDomain) networkRows.append(.httpProxy) networkRows.append(.httpsProxy) @@ -197,6 +198,8 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat case compressionAlgorithm + case defaultGateway + case dnsServer case dnsDomain @@ -304,12 +307,22 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat cell.accessoryType = .none cell.isTappable = false + case .defaultGateway: + cell.leftText = L10n.Configuration.Cells.DefaultGateway.caption + if let policies = configuration.routingPolicies { + cell.rightText = policies.map { $0.rawValue }.joined(separator: " / ") + } else { + cell.rightText = V.All.Value.none + } + cell.accessoryType = .none + cell.isTappable = false + case .dnsServer: guard let dnsServers = configuration.dnsServers else { fatalError("Showing DNS section without any custom server") } cell.leftText = L10n.Configuration.Cells.DnsServer.caption - cell.rightText = dnsServers[indexPath.row] + cell.rightText = dnsServers[indexPath.row - 1] cell.accessoryType = .none cell.isTappable = false diff --git a/Passepartout/Resources/en.lproj/Localizable.strings b/Passepartout/Resources/en.lproj/Localizable.strings index 2876518a..bda34dac 100644 --- a/Passepartout/Resources/en.lproj/Localizable.strings +++ b/Passepartout/Resources/en.lproj/Localizable.strings @@ -181,6 +181,7 @@ "configuration.cells.tls_wrapping.value.auth" = "Authentication"; "configuration.cells.tls_wrapping.value.crypt" = "Encryption"; "configuration.cells.eku.caption" = "Extended verification"; +"configuration.cells.default_gateway.caption" = "Default gateway"; "configuration.cells.dns_server.caption" = "DNS"; "configuration.cells.dns_domain.caption" = "Domain"; "configuration.cells.proxy_http.caption" = "Proxy"; diff --git a/Passepartout/Sources/SwiftGen+Strings.swift b/Passepartout/Sources/SwiftGen+Strings.swift index bb60cafc..49fb2e55 100644 --- a/Passepartout/Sources/SwiftGen+Strings.swift +++ b/Passepartout/Sources/SwiftGen+Strings.swift @@ -168,6 +168,10 @@ public enum L10n { public static let lzo = L10n.tr("Localizable", "configuration.cells.compression_framing.value.lzo") } } + public enum DefaultGateway { + /// Default gateway + public static let caption = L10n.tr("Localizable", "configuration.cells.default_gateway.caption") + } public enum Digest { /// Authentication public static let caption = L10n.tr("Localizable", "configuration.cells.digest.caption") From 04c2191e83a2093c04ca9f6aa763728873234083 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Thu, 25 Apr 2019 14:54:09 +0200 Subject: [PATCH 3/4] Migrate profiles routing policies - Providers: enforce all (IPv4 + IPv6) - Hosts: re-read .ovpn on app update, fall back to all (safer) Reload hosts in order to re-interpret "redirect-gateway". --- .../Sources/Model/ConnectionService.swift | 41 +++++++++++++++++-- .../Sources/Model/TransientStore.swift | 23 ++++++++++- .../Services/InfrastructurePreset.swift | 3 ++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Passepartout/Sources/Model/ConnectionService.swift b/Passepartout/Sources/Model/ConnectionService.swift index 3d687e53..8e6ca9a9 100644 --- a/Passepartout/Sources/Model/ConnectionService.swift +++ b/Passepartout/Sources/Model/ConnectionService.swift @@ -265,22 +265,22 @@ public class ConnectionService: Codable { case .provider: let providerProfile = try decoder.decode(ProviderConnectionProfile.self, from: data) - // fix renamed presets, fall back to default + // XXX: fix renamed presets, fall back to default if providerProfile.preset == nil { providerProfile.presetId = providerProfile.infrastructure.defaults.preset } - // fix renamed pool, fall back to default + // XXX: fix renamed pool, fall back to default if providerProfile.pool == nil, let fallbackPool = providerProfile.infrastructure.defaultPool() { providerProfile.poolId = fallbackPool.id } - + profile = providerProfile case .host: let hostProfile = try decoder.decode(HostConnectionProfile.self, from: data) - // migrate old endpointProtocols + // XXX: migrate old endpointProtocols if hostProfile.parameters.sessionConfiguration.endpointProtocols == nil { var sessionBuilder = hostProfile.parameters.sessionConfiguration.builder() sessionBuilder.endpointProtocols = hostProfile.parameters.endpointProtocols @@ -288,6 +288,8 @@ public class ConnectionService: Codable { parametersBuilder.sessionConfiguration = sessionBuilder.build() hostProfile.parameters = parametersBuilder.build() } + + // XXX: re-read routing policies for profile = hostProfile } @@ -329,6 +331,37 @@ public class ConnectionService: Codable { return url.deletingPathExtension().lastPathComponent } + func reloadHostProfilesFromConfigurationFiles() -> Bool { + var anyReloaded = false + for entry in cache { + guard entry.value.context == .host else { + continue + } + guard let host = profile(withKey: entry.key) as? HostConnectionProfile else { + log.warning("Host context but not a HostConnectionProfile?") + continue + } + guard let url = configurationURL(for: entry.key) else { + continue + } + + // can fail due to passphrase (migration is non-interactive) + if let result = try? ConfigurationParser.parsed(fromURL: url) { + host.parameters = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: result.configuration).build() + } else { + + // fall back to the safer option + var builder = host.parameters.builder() + builder.sessionConfiguration.routingPolicies = [.IPv4, .IPv6] + host.parameters = builder.build() + } + cache[entry.key] = host + + anyReloaded = true + } + return anyReloaded + } + // MARK: Profiles public func hasProfiles() -> Bool { diff --git a/Passepartout/Sources/Model/TransientStore.swift b/Passepartout/Sources/Model/TransientStore.swift index 0f284a19..35aace91 100644 --- a/Passepartout/Sources/Model/TransientStore.swift +++ b/Passepartout/Sources/Model/TransientStore.swift @@ -34,6 +34,10 @@ public class TransientStore { static let didHandleSubreddit = "DidHandleSubreddit" static let masksPrivateData = "MasksPrivateData" + + // migrations + + static let didMigrateHostsRoutingPolicies = "DidMigrateHostsRoutingPolicies" } public static let shared = TransientStore() @@ -62,6 +66,15 @@ public class TransientStore { } } + public static var didMigrateHostsRoutingPolicies: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.didMigrateHostsRoutingPolicies) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.didMigrateHostsRoutingPolicies) + } + } + public static var baseVPNConfiguration: TunnelKitProvider.ConfigurationBuilder { let sessionBuilder = SessionProxy.ConfigurationBuilder() var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) @@ -84,7 +97,7 @@ public class TransientStore { // this must be graceful ConnectionService.migrateJSON(from: TransientStore.serviceURL, to: TransientStore.serviceURL) - + let cfg = TransientStore.baseVPNConfiguration.build() do { let data = try Data(contentsOf: TransientStore.serviceURL) @@ -95,6 +108,14 @@ public class TransientStore { service = try JSONDecoder().decode(ConnectionService.self, from: data) service.baseConfiguration = cfg service.loadProfiles() + + // do migrations + if !TransientStore.didMigrateHostsRoutingPolicies { + if service.reloadHostProfilesFromConfigurationFiles() { + service.saveProfiles() + } + TransientStore.didMigrateHostsRoutingPolicies = true + } } catch let e { log.error("Could not decode service: \(e)") service = ConnectionService( diff --git a/Passepartout/Sources/Services/InfrastructurePreset.swift b/Passepartout/Sources/Services/InfrastructurePreset.swift index d37d581d..87baad20 100644 --- a/Passepartout/Sources/Services/InfrastructurePreset.swift +++ b/Passepartout/Sources/Services/InfrastructurePreset.swift @@ -162,6 +162,9 @@ public struct InfrastructurePreset: Codable { sessionBuilder.randomizeEndpoint = try cfgContainer.decodeIfPresent(Bool.self, forKey: .randomizeEndpoint) ?? false sessionBuilder.usesPIAPatches = try cfgContainer.decodeIfPresent(Bool.self, forKey: .usesPIAPatches) ?? false + // XXX: redirect everything through the VPN for providers + sessionBuilder.routingPolicies = [.IPv4, .IPv6] + let builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) configuration = builder.build() } From 5451139c8e2b0af0197022e0fd86cde0d0fc4c3d Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Thu, 25 Apr 2019 15:54:09 +0200 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 396444c9..d509bdc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Do not redirect all traffic to VPN unless `--redirect-gateway` specified. [#71](https://github.com/passepartoutvpn/passepartout-ios/pull/71) + ## 1.6.0 Beta 1750 (2019-04-23) ### Added