diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-02-08 11:02:27 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-02-08 11:02:27 +0100 |
| commit | bd49170ce18b805299b00149de1804cbac52a19e (patch) | |
| tree | 3e93e482c087901008c1e7fcaab6755a6c6dd983 | |
| parent | 43c7e66870e96d252f9c8cf8256efdcd4f178f90 (diff) | |
| parent | 209983aadb85c65d9399a45c1e1ea3453aac1b49 (diff) | |
| download | mullvadvpn-bd49170ce18b805299b00149de1804cbac52a19e.tar.xz mullvadvpn-bd49170ce18b805299b00149de1804cbac52a19e.zip | |
Merge branch 'add-malware-blocking'
| -rw-r--r-- | ios/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | ios/MullvadVPN/PreferencesDataSource.swift | 34 | ||||
| -rw-r--r-- | ios/MullvadVPN/PreferencesViewModel.swift | 30 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelSettings.swift | 71 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/Preferences.strings | 3 | ||||
| -rw-r--r-- | ios/PacketTunnel/PacketTunnelProvider.swift | 11 |
6 files changed, 125 insertions, 25 deletions
diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index c7d3d9775b..e4d5550a11 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -25,6 +25,7 @@ Line wrap the file at 100 chars. Th ## [Unreleased] ### Added - Show privacy overlay when entering app switcher. +- Add option to block malware. ### Fixed - Fix crash occurring after completing in-app purchase. diff --git a/ios/MullvadVPN/PreferencesDataSource.swift b/ios/MullvadVPN/PreferencesDataSource.swift index 2ec34c1a6d..63482db47f 100644 --- a/ios/MullvadVPN/PreferencesDataSource.swift +++ b/ios/MullvadVPN/PreferencesDataSource.swift @@ -48,6 +48,7 @@ class PreferencesDataSource: NSObject, UITableViewDataSource, UITableViewDelegat private enum Item: Hashable { case blockAdvertising case blockTracking + case blockMalware case useCustomDNS case addDNSServer case dnsServer(_ uniqueID: UUID) @@ -308,7 +309,7 @@ class PreferencesDataSource: NSObject, UITableViewDataSource, UITableViewDelegat private func updateSnapshot() { var newSnapshot = DataSourceSnapshot<Section, Item>() newSnapshot.appendSections([.mullvadDNS, .customDNS]) - newSnapshot.appendItems([.blockAdvertising, .blockTracking], in: .mullvadDNS) + newSnapshot.appendItems([.blockAdvertising, .blockTracking, .blockMalware], in: .mullvadDNS) newSnapshot.appendItems([.useCustomDNS], in: .customDNS) let dnsServerItems = viewModel.customDNSDomains.map { entry in @@ -359,6 +360,23 @@ class PreferencesDataSource: NSObject, UITableViewDataSource, UITableViewDelegat return cell + case .blockMalware: + let cell = tableView.dequeueReusableCell(withIdentifier: CellReuseIdentifiers.settingSwitch.rawValue, for: indexPath) as! SettingsSwitchCell + + cell.titleLabel.text = NSLocalizedString( + "BLOCK_MALWARE_CELL_LABEL", + tableName: "Preferences", + value: "Block malware", + comment: "" + ) + cell.accessibilityHint = nil + cell.setOn(viewModel.blockMalware, animated: false) + cell.action = { [weak self] isOn in + self?.setBlockMalware(isOn) + } + + return cell + case .useCustomDNS: let cell = tableView.dequeueReusableCell(withIdentifier: CellReuseIdentifiers.settingSwitch.rawValue, for: indexPath) as! SettingsSwitchCell @@ -444,6 +462,20 @@ class PreferencesDataSource: NSObject, UITableViewDataSource, UITableViewDelegat } } + private func setBlockMalware(_ isEnabled: Bool) { + let oldViewModel = viewModel + + viewModel.setBlockMalware(isEnabled) + + if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { + reloadCustomDNSFooter() + } + + if !isEditing { + delegate?.preferencesDataSource(self, didChangeViewModel: viewModel) + } + } + private func setEnableCustomDNS(_ isEnabled: Bool) { viewModel.setEnableCustomDNS(isEnabled) diff --git a/ios/MullvadVPN/PreferencesViewModel.swift b/ios/MullvadVPN/PreferencesViewModel.swift index de4fdaba81..02107280b9 100644 --- a/ios/MullvadVPN/PreferencesViewModel.swift +++ b/ios/MullvadVPN/PreferencesViewModel.swift @@ -68,6 +68,7 @@ struct DNSServerEntry: Equatable, Hashable { struct PreferencesViewModel: Equatable { private(set) var blockAdvertising: Bool private(set) var blockTracking: Bool + private(set) var blockMalware: Bool private(set) var enableCustomDNS: Bool var customDNSDomains: [DNSServerEntry] @@ -81,6 +82,11 @@ struct PreferencesViewModel: Equatable { enableCustomDNS = false } + mutating func setBlockMalware(_ newValue: Bool) { + blockMalware = newValue + enableCustomDNS = false + } + mutating func setEnableCustomDNS(_ newValue: Bool) { blockTracking = false blockAdvertising = false @@ -89,7 +95,7 @@ struct PreferencesViewModel: Equatable { /// Precondition for enabling Custom DNS. var customDNSPrecondition: CustomDNSPrecondition { - if blockAdvertising || blockTracking { + if blockAdvertising || blockTracking || blockMalware { return .conflictsWithOtherSettings } else { let hasValidDNSDomains = customDNSDomains.contains { entry in @@ -110,8 +116,9 @@ struct PreferencesViewModel: Equatable { } init(from dnsSettings: DNSSettings = DNSSettings()) { - blockAdvertising = dnsSettings.blockAdvertising - blockTracking = dnsSettings.blockTracking + blockAdvertising = dnsSettings.blockingOptions.contains(.blockAdvertising) + blockTracking = dnsSettings.blockingOptions.contains(.blockTracking) + blockMalware = dnsSettings.blockingOptions.contains(.blockMalware) enableCustomDNS = dnsSettings.enableCustomDNS customDNSDomains = dnsSettings.customDNSDomains.map { ipAddress in return DNSServerEntry(identifier: UUID(), address: "\(ipAddress)") @@ -124,6 +131,7 @@ struct PreferencesViewModel: Equatable { mergedViewModel.blockAdvertising = other.blockAdvertising mergedViewModel.blockTracking = other.blockTracking + mergedViewModel.blockMalware = other.blockMalware mergedViewModel.enableCustomDNS = other.enableCustomDNS var oldDNSDomains = customDNSDomains @@ -188,9 +196,21 @@ struct PreferencesViewModel: Equatable { /// Converts view model into `DNSSettings`. func asDNSSettings() -> DNSSettings { + var blockingOptions = DNSBlockingOptions() + if blockAdvertising { + blockingOptions.insert(.blockAdvertising) + } + + if blockTracking { + blockingOptions.insert(.blockTracking) + } + + if blockMalware { + blockingOptions.insert(.blockMalware) + } + var dnsSettings = DNSSettings() - dnsSettings.blockAdvertising = blockAdvertising - dnsSettings.blockTracking = blockTracking + dnsSettings.blockingOptions = blockingOptions dnsSettings.enableCustomDNS = enableCustomDNS dnsSettings.customDNSDomains = customDNSDomains.compactMap { entry in return AnyIPAddress(entry.address) diff --git a/ios/MullvadVPN/TunnelSettings.swift b/ios/MullvadVPN/TunnelSettings.swift index c9a96fad80..aa0554d3c2 100644 --- a/ios/MullvadVPN/TunnelSettings.swift +++ b/ios/MullvadVPN/TunnelSettings.swift @@ -7,6 +7,7 @@ // import Foundation +import struct Network.IPv4Address import class WireGuardKit.PublicKey import struct WireGuardKit.IPAddressRange @@ -63,16 +64,49 @@ struct TunnelSettings: Codable, Equatable { var interface = InterfaceSettings() } +/// A struct describing Mullvad DNS blocking options. +struct DNSBlockingOptions: OptionSet, Codable { + typealias RawValue = UInt32 + + let rawValue: RawValue + + static let blockAdvertising = DNSBlockingOptions(rawValue: 1 << 0) + static let blockTracking = DNSBlockingOptions(rawValue: 1 << 1) + static let blockMalware = DNSBlockingOptions(rawValue: 1 << 2) + + var serverAddress: IPv4Address? { + if isEmpty { + return nil + } else { + return IPv4Address("100.64.0.\(rawValue)") + } + } + + init(rawValue: RawValue) { + self.rawValue = rawValue + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let rawValue = try container.decode(RawValue.self) + + self.init(rawValue: rawValue) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + try container.encode(rawValue) + } +} + /// A struct that holds DNS settings. struct DNSSettings: Codable, Equatable { /// Maximum number of allowed DNS domains. static let maxAllowedCustomDNSDomains = 3 - /// Block advertising. - var blockAdvertising: Bool = false - - /// Block tracking. - var blockTracking: Bool = false + /// DNS blocking options. + var blockingOptions: DNSBlockingOptions = [] /// Enable custom DNS. var enableCustomDNS: Bool = false @@ -82,11 +116,17 @@ struct DNSSettings: Codable, Equatable { /// Effective state of the custom DNS setting. var effectiveEnableCustomDNS: Bool { - return !blockAdvertising && !blockTracking && enableCustomDNS && !customDNSDomains.isEmpty + return blockingOptions.isEmpty && enableCustomDNS && !customDNSDomains.isEmpty } private enum CodingKeys: String, CodingKey { - case blockAdvertising, blockTracking, enableCustomDNS, customDNSDomains + // Removed in 2022.1 in favor of `blockingOptions` + case blockAdvertising, blockTracking + + // Added in 2022.1 + case blockingOptions + + case enableCustomDNS, customDNSDomains } init() {} @@ -94,8 +134,18 @@ struct DNSSettings: Codable, Equatable { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - blockAdvertising = try container.decode(Bool.self, forKey: .blockAdvertising) - blockTracking = try container.decode(Bool.self, forKey: .blockTracking) + // Added in 2022.1 + if let storedBlockingOptions = try container.decodeIfPresent(DNSBlockingOptions.self, forKey: .blockingOptions) { + blockingOptions = storedBlockingOptions + } + + if let storedBlockAdvertising = try container.decodeIfPresent(Bool.self, forKey: .blockAdvertising), storedBlockAdvertising { + blockingOptions.insert(.blockAdvertising) + } + + if let storedBlockTracking = try container.decodeIfPresent(Bool.self, forKey: .blockTracking), storedBlockTracking { + blockingOptions.insert(.blockTracking) + } if let storedEnableCustomDNS = try container.decodeIfPresent(Bool.self, forKey: .enableCustomDNS) { enableCustomDNS = storedEnableCustomDNS @@ -109,8 +159,7 @@ struct DNSSettings: Codable, Equatable { func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(blockAdvertising, forKey: .blockAdvertising) - try container.encode(blockTracking, forKey: .blockTracking) + try container.encode(blockingOptions, forKey: .blockingOptions) try container.encode(enableCustomDNS, forKey: .enableCustomDNS) try container.encode(customDNSDomains, forKey: .customDNSDomains) } diff --git a/ios/MullvadVPN/en.lproj/Preferences.strings b/ios/MullvadVPN/en.lproj/Preferences.strings index 30be83d034..1bbb0150a5 100644 --- a/ios/MullvadVPN/en.lproj/Preferences.strings +++ b/ios/MullvadVPN/en.lproj/Preferences.strings @@ -5,6 +5,9 @@ "BLOCK_ADS_CELL_LABEL" = "Block ads"; /* No comment provided by engineer. */ +"BLOCK_MALWARE_CELL_LABEL" = "Block malware"; + +/* No comment provided by engineer. */ "BLOCK_TRACKERS_CELL_LABEL" = "Block trackers"; /* No comment provided by engineer. */ diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift index 59250d9345..b9f645eb9d 100644 --- a/ios/PacketTunnel/PacketTunnelProvider.swift +++ b/ios/PacketTunnel/PacketTunnelProvider.swift @@ -327,14 +327,9 @@ extension PacketTunnelConfiguration { .prefix(DNSSettings.maxAllowedCustomDNSDomains) return Array(dnsServers) } else { - switch (dnsSettings.blockAdvertising, dnsSettings.blockTracking) { - case (true, false): - return [IPv4Address("100.64.0.1")!] - case (false, true): - return [IPv4Address("100.64.0.2")!] - case (true, true): - return [IPv4Address("100.64.0.3")!] - case (false, false): + if let serverAddress = dnsSettings.blockingOptions.serverAddress { + return [serverAddress] + } else { return [mullvadEndpoint.ipv4Gateway, mullvadEndpoint.ipv6Gateway] } } |
