summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-02-08 11:02:27 +0100
committerAndrej Mihajlov <and@mullvad.net>2022-02-08 11:02:27 +0100
commitbd49170ce18b805299b00149de1804cbac52a19e (patch)
tree3e93e482c087901008c1e7fcaab6755a6c6dd983
parent43c7e66870e96d252f9c8cf8256efdcd4f178f90 (diff)
parent209983aadb85c65d9399a45c1e1ea3453aac1b49 (diff)
downloadmullvadvpn-bd49170ce18b805299b00149de1804cbac52a19e.tar.xz
mullvadvpn-bd49170ce18b805299b00149de1804cbac52a19e.zip
Merge branch 'add-malware-blocking'
-rw-r--r--ios/CHANGELOG.md1
-rw-r--r--ios/MullvadVPN/PreferencesDataSource.swift34
-rw-r--r--ios/MullvadVPN/PreferencesViewModel.swift30
-rw-r--r--ios/MullvadVPN/TunnelSettings.swift71
-rw-r--r--ios/MullvadVPN/en.lproj/Preferences.strings3
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift11
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]
}
}