diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2021-10-05 11:59:33 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-11-03 13:30:51 +0100 |
| commit | cbf7d656ab49144ebd0bfddc7667ecf144316f54 (patch) | |
| tree | 589eff1aec97c64a902300f209de2cf5e7db13b3 | |
| parent | 7f54468f674e991038bf676113dba61e46a60353 (diff) | |
| download | mullvadvpn-cbf7d656ab49144ebd0bfddc7667ecf144316f54.tar.xz mullvadvpn-cbf7d656ab49144ebd0bfddc7667ecf144316f54.zip | |
DNSSettings: add custom DNS configuration
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 6 | ||||
| -rw-r--r-- | ios/MullvadVPN/AnyIPAddress.swift | 101 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelSettings.swift | 39 |
3 files changed, 146 insertions, 0 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 4417fd14e9..5d9c205ec8 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -98,6 +98,8 @@ 584789BE264D4A2A000E45FB /* le_root_cert.cer in Resources */ = {isa = PBXBuildFile; fileRef = 584789B7264D4A2A000E45FB /* le_root_cert.cer */; }; 584789E026529D72000E45FB /* SSLPinningURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584789DF26529D72000E45FB /* SSLPinningURLSessionDelegate.swift */; }; 584789EC2652A1A2000E45FB /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 584789EB2652A1A2000E45FB /* Logging */; }; + 584D26BF270C550B004EA533 /* AnyIPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26BE270C550B004EA533 /* AnyIPAddress.swift */; }; + 584D26C0270C550E004EA533 /* AnyIPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26BE270C550B004EA533 /* AnyIPAddress.swift */; }; 584E96BC240FD4DA00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; }; 584E96BD240FD4DA00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; }; 584E96BE240FD4DB00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; }; @@ -394,6 +396,7 @@ 584789B7264D4A2A000E45FB /* le_root_cert.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = le_root_cert.cer; sourceTree = "<group>"; }; 584789DF26529D72000E45FB /* SSLPinningURLSessionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSLPinningURLSessionDelegate.swift; sourceTree = "<group>"; }; 584B26F3237434D00073B10E /* RelaySelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorTests.swift; sourceTree = "<group>"; }; + 584D26BE270C550B004EA533 /* AnyIPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddress.swift; sourceTree = "<group>"; }; 5850366725A47AC700A43E93 /* IPAddressRange+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IPAddressRange+Codable.swift"; sourceTree = "<group>"; }; 58561C98239A5D1500BD6B5E /* IPEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPEndpoint.swift; sourceTree = "<group>"; }; 5857F24224C8662600CF6F47 /* SelectLocationHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationHeaderView.swift; sourceTree = "<group>"; }; @@ -786,6 +789,7 @@ 582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */, 58CCA01722426713004F3011 /* AccountViewController.swift */, 58B9EB122488ED2100095626 /* AlertPresenter.swift */, + 584D26BE270C550B004EA533 /* AnyIPAddress.swift */, 5868585424054096000B8131 /* AppButton.swift */, 58CE5E63224146200008646E /* AppDelegate.swift */, 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */, @@ -1337,6 +1341,7 @@ 5820674926E63EC900655B05 /* Promise+BackgroundTask.swift in Sources */, 58B9EB132488ED2100095626 /* AlertPresenter.swift in Sources */, 587A01FC23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift in Sources */, + 584D26BF270C550B004EA533 /* AnyIPAddress.swift in Sources */, 5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */, 580EE20624B3222200F9D8A1 /* ExclusivityController.swift in Sources */, 5888AD83227B11080051EB06 /* SelectLocationCell.swift in Sources */, @@ -1421,6 +1426,7 @@ 58BFA5CD22A7CE1F00A6173D /* ApplicationConfiguration.swift in Sources */, 5850368D25A49E2200A43E93 /* PrivateKeyWithMetadata.swift in Sources */, 5820675826E652AF00655B05 /* RelayCacheIO.swift in Sources */, + 584D26C0270C550E004EA533 /* AnyIPAddress.swift in Sources */, 5820675726E652A600655B05 /* REST.swift in Sources */, 585DA88F26B031E200B8C587 /* TunnelIPCCoding.swift in Sources */, 5806767C27048E9B00C858CB /* PacketTunnelProvider.swift in Sources */, diff --git a/ios/MullvadVPN/AnyIPAddress.swift b/ios/MullvadVPN/AnyIPAddress.swift new file mode 100644 index 0000000000..1898754a69 --- /dev/null +++ b/ios/MullvadVPN/AnyIPAddress.swift @@ -0,0 +1,101 @@ +// +// AnyIPAddress.swift +// MullvadVPN +// +// Created by pronebird on 05/10/2021. +// Copyright © 2021 Mullvad VPN AB. All rights reserved. +// + +import Foundation +import Network + +/// Container type that holds either `IPv4Address` or `IPv6Address`. +enum AnyIPAddress: IPAddress, Codable, Equatable, CustomDebugStringConvertible { + case ipv4(IPv4Address) + case ipv6(IPv6Address) + + private enum CodingKeys: String, CodingKey { + case ipv4, ipv6 + } + + private var innerAddress: IPAddress { + switch self { + case .ipv4(let ipv4Address): + return ipv4Address + case .ipv6(let ipv6Address): + return ipv6Address + } + } + + var rawValue: Data { + return innerAddress.rawValue + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + if container.contains(.ipv4) { + self = .ipv4(try container.decode(IPv4Address.self, forKey: .ipv4)) + } else if container.contains(.ipv6) { + self = .ipv6(try container.decode(IPv6Address.self, forKey: .ipv6)) + } else { + throw DecodingError.dataCorruptedError(forKey: .ipv4, in: container, debugDescription: "Invalid AnyIPAddress representation") + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + switch self { + case .ipv4(let ipv4Address): + try container.encode(ipv4Address, forKey: .ipv4) + case .ipv6(let ipv6Address): + try container.encode(ipv6Address, forKey: .ipv6) + } + } + + init?(_ rawValue: Data, _ interface: NWInterface?) { + if let ipv4Address = IPv4Address(rawValue, interface) { + self = .ipv4(ipv4Address) + } else if let ipv6Address = IPv6Address(rawValue, interface) { + self = .ipv6(ipv6Address) + } else { + return nil + } + } + + init?(_ string: String) { + if let ipv4Address = IPv4Address(string) { + self = .ipv4(ipv4Address) + } else if let ipv6Address = IPv6Address(string) { + self = .ipv6(ipv6Address) + } else { + return nil + } + } + + var interface: NWInterface? { + return innerAddress.interface + } + + var isLoopback: Bool { + return innerAddress.isLoopback + } + + var isLinkLocal: Bool { + return innerAddress.isLinkLocal + } + + var isMulticast: Bool { + return innerAddress.isMulticast + } + + var debugDescription: String { + switch self { + case .ipv4(let ipv4Address): + return "\(ipv4Address)" + case .ipv6(let ipv6Address): + return "\(ipv6Address)" + } + } +} diff --git a/ios/MullvadVPN/TunnelSettings.swift b/ios/MullvadVPN/TunnelSettings.swift index c8503c894d..9f3b47162d 100644 --- a/ios/MullvadVPN/TunnelSettings.swift +++ b/ios/MullvadVPN/TunnelSettings.swift @@ -58,9 +58,48 @@ struct TunnelSettings: Codable, Equatable { /// 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 + + /// Enable custom DNS. + var enableCustomDNS: Bool = false + + /// Custom DNS domains. + var customDNSDomains: [AnyIPAddress] = [] + + private enum CodingKeys: String, CodingKey { + case blockAdvertising, blockTracking, enableCustomDNS, customDNSDomains + } + + init() {} + + 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) + + if let storedEnableCustomDNS = try container.decodeIfPresent(Bool.self, forKey: .enableCustomDNS) { + enableCustomDNS = storedEnableCustomDNS + } + + if let storedCustomDNSDomains = try container.decodeIfPresent([AnyIPAddress].self, forKey: .customDNSDomains) { + customDNSDomains = storedCustomDNSDomains + } + } + + 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(enableCustomDNS, forKey: .enableCustomDNS) + try container.encode(customDNSDomains, forKey: .customDNSDomains) + } } |
