-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remediate TunnelVision, TunnelCrack and fix "Exclude Local Networks" #1039
Conversation
import Combine | ||
import Foundation | ||
|
||
extension UserDefaults: InternalUserStoring { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UserDefaults
can now be used to store the internal user state so that agents and extensions can access said state.
@@ -19,7 +19,7 @@ | |||
import Foundation | |||
import Network | |||
|
|||
public enum AnyIPAddress: IPAddress, Hashable, CustomDebugStringConvertible, @unchecked Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was causing issues because some IP addresses contained by this were converting to empty strings. I'm removing the IPAddress
protocol and consumers will instead need to call ipAddress
on an instance of this class.
@@ -65,10 +65,8 @@ public protocol NetworkProtectionDeviceManagement { | |||
typealias GenerateTunnelConfigurationResult = (tunnelConfiguration: TunnelConfiguration, server: NetworkProtectionServer) | |||
|
|||
func generateTunnelConfiguration(resolvedSelectionMethod: NetworkProtectionServerSelectionMethod, | |||
includedRoutes: [IPAddressRange], | |||
excludedRoutes: [IPAddressRange], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Included and excluded routes will no longer by passed by the client or by settings. They'll be calculated by the extension based on settings.
If we ever need to add support for custom IP ranges, we'll just add the appropriate overrides in settings but still calculate all the routing here.
includedRoutes: includedRoutes, | ||
excludedRoutes: excludedRoutes, | ||
dnsSettings: dnsSettings, | ||
isKillSwitchEnabled: isKillSwitchEnabled) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bool is not necessary and not really useful. Enforce routes is sort of our kill switch now.
|
||
return TunnelConfiguration(name: "DuckDuckGo VPN", interface: interface, peers: [peerConfiguration]) | ||
Logger.networkProtection.log("Routing table information:\nL Included Routes: \(routingTableResolver.includedRoutes, privacy: .public)\nL Excluded Routes: \(routingTableResolver.excludedRoutes, privacy: .public)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this can contain PII - it'll mostly be mostly static IP ranges and DNS ip for inclusions, then static IP ranges and server IP for exclusions.
excludedRoutes: excludedRoutes, | ||
dns: dns, | ||
isKillSwitchEnabled: isKillSwitchEnabled) | ||
let routingTableResolver = VPNRoutingTableResolver( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class takes care of calculating the appropriate routes. Makes it really easy to write unit tests as well.
I'll try to get some in before we merge this.
Logger.networkProtection.log("Generating tunnel config") | ||
Logger.networkProtection.log("Excluded ranges are: \(String(describing: self.settings.excludedRanges), privacy: .public)") | ||
Logger.networkProtection.log("Server selection method: \(self.currentServerSelectionMethod.debugDescription, privacy: .public)") | ||
Logger.networkProtection.log("DNS server: \(String(describing: self.settings.dnsSettings), privacy: .public)") | ||
let tunnelConfiguration = try await generateTunnelConfiguration(serverSelectionMethod: currentServerSelectionMethod, | ||
includedRoutes: includedRoutes ?? [], | ||
excludedRoutes: settings.excludedRanges, | ||
dnsSettings: settings.dnsSettings, | ||
regenerateKey: true) | ||
let tunnelConfiguration = try await generateTunnelConfiguration( | ||
serverSelectionMethod: currentServerSelectionMethod, | ||
dnsSettings: settings.dnsSettings, | ||
regenerateKey: true) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Routes are no longer passed into the PacketTunnelProvider
.
case .setExcludeLocalNetworks: | ||
if case .connected = connectionStatus { | ||
try await updateTunnelConfiguration( | ||
updateMethod: .selectServer(currentServerSelectionMethod), | ||
reassert: false) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if the extension or main app should decide when to restart the adapter. Maybe I should just do it here?
But doing it here prevents us from doing batch changes - although to be honest we don't do them in the main app either as settings are individual :)
private func handleRestartAdapter() async throws { | ||
let tunnelConfiguration = try await generateTunnelConfiguration( | ||
serverSelectionMethod: currentServerSelectionMethod, | ||
dnsSettings: settings.dnsSettings, | ||
regenerateKey: false) | ||
|
||
try await updateTunnelConfiguration(updateMethod: .useConfiguration(tunnelConfiguration), | ||
reassert: false, | ||
regenerateKey: false) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convenience method for restarting the adapter very quickly and without going through server re-registration.
|
||
import Foundation | ||
|
||
public enum RoutingRange { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole doesn't make sense anymore. We don't need to offer to the user this level of granularity and if we ever do, it's likely to be using a different mechanism.
...NetworkProtection/Status/ConnectionErrorObserver/ConnectionErrorObserverThroughSession.swift
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just some open questions on the 10.0.0.0 IP range and a nit with left-in commented-out code.
Not a blocker, but open question: do you think there is a way to test the routing table in isolation? I don't see an obvious way that doesn't involve quite a bit of work, but you know more than me :)
] | ||
|
||
public static let localNetworkRange: [NetworkProtection.IPAddressRange] = [ | ||
// "10.0.0.0/8", /* 255.0.0.0 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this commented out because it clashes with our VPN tunnel IP range? Should we add ranges surrounding the tunnel range?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm matching Android here, where they exclude the 10.x.x.x range because it's used for DNS and generally reserved for out VPN.
I do think we should included everything but the DNS but since Android is doing this, I'm assuming it's good enough for us, for now.
Tests/NetworkProtectionTests/Mocks/NetworkProtectionServerMocks.swift
Outdated
Show resolved
Hide resolved
I think we should add tests to make sure the ranges are fine, but I also don't want to be blocking this PR for that now. I promise I'll push something soon to cover this. Testing what the system does with the ranges is, IMO, a loosing battle - but we can test that our system is behaving well and delivering the correct routes to the OS. |
…3422) Task/Issue URL: https://app.asana.com/0/1206580121312550/1208686409805161/f Tech Design URL: https://app.asana.com/0/481882893211075/1208643192597095/f iOS PR: iOS PR: duckduckgo/iOS#3460 BSK PR: duckduckgo/BrowserServicesKit#1039 ## Description Remediate TunnelVision, TunnelCrack and fix "Exclude Local Networks".
…3460) Task/Issue URL: https://app.asana.com/0/1206580121312550/1208686409805161/f Tech Design URL: https://app.asana.com/0/481882893211075/1208643192597095/f macOS PR: duckduckgo/macos-browser#3422 BSK PR: duckduckgo/BrowserServicesKit#1039 ## Description Remediate TunnelVision, TunnelCrack and fix "Exclude Local Networks".
Task/Issue URL: https://app.asana.com/0/1206580121312550/1208686409805161/f
Tech Design URL: https://app.asana.com/0/481882893211075/1208643192597095/f
iOS PR: duckduckgo/iOS#3460
macOS PR: duckduckgo/macos-browser#3422
What kind of version bump will this require?: Major
Description
Remediate TunnelVision, TunnelCrack and fix "Exclude Local Networks".
Testing
Please refer to the platform-specific PRs for testing instructions.
Internal references:
Software Engineering Expectations
Technical Design Template