Skip to content
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

Fix TunnelVision using enforceRoutes #3422

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14425,8 +14425,8 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 200.2.0;
kind = revision;
revision = a817b6e2c205f56b4b1e86c5db27a75a44029101;
};
};
9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "a7de5bc2fe128444495e6e8345026c8974076ad7",
"version" : "200.2.0"
"revision" : "a817b6e2c205f56b4b1e86c5db27a75a44029101"
}
},
{
Expand Down
9 changes: 9 additions & 0 deletions DuckDuckGo/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
private(set) var stateRestorationManager: AppStateRestorationManager!
private var grammarFeaturesManager = GrammarFeaturesManager()
let internalUserDecider: InternalUserDecider
private var isInternalUserSharingCancellable: AnyCancellable?
let featureFlagger: FeatureFlagger
private var appIconChanger: AppIconChanger!
private var autoClearHandler: AutoClearHandler!
Expand Down Expand Up @@ -375,6 +376,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {

subscribeToEmailProtectionStatusNotifications()
subscribeToDataImportCompleteNotification()
subscribeToInternalUserChanges()

fireFailedCompilationsPixelIfNeeded()

Expand Down Expand Up @@ -666,6 +668,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
NotificationCenter.default.addObserver(self, selector: #selector(dataImportCompleteNotification(_:)), name: .dataImportComplete, object: nil)
}

private func subscribeToInternalUserChanges() {
UserDefaults.appConfiguration.isInternalUser = internalUserDecider.isInternalUser

isInternalUserSharingCancellable = internalUserDecider.isInternalUserPublisher
.assign(to: \.isInternalUser, onWeaklyHeld: UserDefaults.appConfiguration)
}

private func emailDidSignInNotification(_ notification: Notification) {
PixelKit.fire(NonStandardEvent(NonStandardPixel.emailEnabled))
if AppDelegate.isNewUser {
Expand Down
5 changes: 5 additions & 0 deletions DuckDuckGo/FeatureFlagging/Model/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public enum FeatureFlag: String {

/// https://app.asana.com/0/72649045549333/1208231259093710/f
case networkProtectionUserTips

/// /// https://app.asana.com/0/72649045549333/1208617860225199/f
case networkProtectionEnforceRoutes
}

extension FeatureFlag: FeatureFlagSourceProviding {
Expand All @@ -66,6 +69,8 @@ extension FeatureFlag: FeatureFlagSourceProviding {
return .remoteReleasable(.subfeature(AutofillSubfeature.credentialsImportPromotionForExistingUsers))
case .networkProtectionUserTips:
return .remoteDevelopment(.subfeature(NetworkProtectionSubfeature.userTips))
case .networkProtectionEnforceRoutes:
return .remoteDevelopment(.subfeature(NetworkProtectionSubfeature.enforceRoutes))
}
}
}
Expand Down
60 changes: 42 additions & 18 deletions DuckDuckGo/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -38667,55 +38667,55 @@
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Du bist bereit! Du kannst mich jederzeit im Dock antreffen.\nMöchtest du sehen, wie ich dich beschütze? Versuche, eine deiner Lieblingsseiten zu besuchen 👆\n\nBehalte die Adressleiste im Auge. Ich werde Tracker blockieren und die Sicherheit deiner Verbindung verbessern, wenn möglichu{00A0}🔒"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "You’re all set! You can find me hanging out in the Dock anytime.\n\nWant to see how I protect you? Try visiting one of your favorite sites 👆\n\nKeep watching the address bar as you go. I’ll be blocking trackers and upgrading the security of your connection when possibleu{00A0}🔒"
"value" : "You’re all set! You can find me hanging out in the Dock anytime.\n\nWant to see how I protect you? Try visiting one of your favorite sites 👆\n\nKeep watching the address bar as you go. I’ll be blocking trackers and upgrading the security of your connection when possible 🔒"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "¡Ya está todo listo! Puedes encontrarme en el Dock en cualquier momento.\n¿Quieres ver cómo te protejo? Prueba a visitar uno de tus sitios favoritos 👆\n\nNo pierdas de vista la barra de direcciones al navegar. Bloquearé los rastreadores y mejoraré la seguridad de tu conexión cuando sea posible{00A0}🔒"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Tout est prêt ! Vous pouvez me trouver sur le Dock à tout moment.\nVous voulez voir comment je vous protège ? Essayez de visiter l'un de vos sites préférés 👆\n\nContinuez à regarder la barre d'adresse au fur et à mesure. Je bloquerai les traqueurs et mettrai à niveau la sécurité de votre connexion si possible 🔒"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Tutto pronto! Puoi trovarmi nel dock in qualsiasi momento.\nVuoi vedere come ti proteggo? Prova a visitare uno dei tuoi siti preferiti 👆\n\nContinua a controllare la barra degli indirizzi mentre esplori. Bloccherò i sistemi di tracciamento e aggiornerò la sicurezza della tua connessione quando possibile{00A0} 🔒"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Je bent helemaal klaar! Je kunt me altijd vinden in het Dock.\nWil je zien hoe ik je bescherm? Ga eens naar een van je favoriete websites 👆\n\nKijk tijdens het surfen goed naar de adresbalk. Ik blokkeer trackers en werk de beveiliging van je verbinding bij wanneer mogelijk 🔒"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Wszystko gotowe! W każdej chwili możesz mnie znaleźć w Docku.\nChcesz zobaczyć, jak Cię chronię? Spróbuj odwiedzić jedną z ulubionych stron 👆\n\nW międzyczasie obserwuj pasek adresu. Będę blokować mechanizmy śledzące i w miarę możliwości poprawiać bezpieczeństwo połączenia 🔒"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Está tudo pronto! Podes encontrar-me na Dock em qualquer altura.\nQueres ver como te protejo? Experimenta visitar um dos teus sites favoritos 👆\n\nContinua a observar a barra de endereço à medida que vais avançando. Vou bloquear os rastreadores e melhorar a segurança da tua ligação sempre que possível 🔒"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Готово! Теперь меня всегда можно найти на док-панели.\nВам интересно, как я защищаю вашу конфиденциальность? Зайдите на свой любимый сайт...👆\n\nИ следите за адресной строкой. По возможности я заблокирую все трекеры и сделаю соединение более безопасным {00A0}🔒"
}
}
Expand All @@ -38727,55 +38727,55 @@
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Du bist bereit!\n\nMöchtest du sehen, wie ich dich beschütze? Versuche, eine deiner Lieblingsseiten zu besuchen 👆\n\nBehalte die Adressleiste im Auge. Ich werde Tracker blockieren und die Sicherheit deiner Verbindung verbessern, wenn möglich 🔒"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "You’re all set!\n\nWant to see how I protect you? Try visiting one of your favorite sites 👆\n\nKeep watching the address bar as you go. I’ll be blocking trackers and upgrading the security of your connection when possibleu{00A0}🔒"
"value" : "You’re all set!\n\nWant to see how I protect you? Try visiting one of your favorite sites 👆\n\nKeep watching the address bar as you go. I’ll be blocking trackers and upgrading the security of your connection when possible 🔒"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "¡Ya está todo listo!\n\n¿Quieres ver cómo te protejo? Prueba a visitar uno de tus sitios favoritos 👆\n\nSigue viendo la barra de direcciones sobre la marcha. Bloquearé los rastreadores y mejoraré la seguridad de tu conexión cuando sea posible 🔒"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Tout est prêt !\n\nVous voulez voir comment je vous protège ? Essayez de visiter l'un de vos sites préférés 👆\n\n Continuez à regarder la barre d'adresse au fur et à mesure. Je bloquerai les traqueurs et mettrai à niveau la sécurité de votre connexion si possible 🔒"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Tutto pronto.\n\nVuoi vedere come ti proteggo? Prova a visitare uno dei tuoi siti preferiti 👆Continua a controllare la barra degli indirizzi mentre esplori. Bloccherò i sistemi di tracciamento e aggiornerò la sicurezza della tua connessione quando possibile 🔒"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Je bent helemaal klaar!\n\nWil je zien hoe ik je bescherm? Ga eens naar een van je favoriete websites 👆 \n\n Kijk tijdens het surfen goed naar de adresbalk. Ik blokkeer trackers en werk de beveiliging van je verbinding bij wanneer mogelijk 🔒"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Wszystko gotowe!\n\nChcesz zobaczyć, jak Cię chronię? Spróbuj odwiedzić jedną z ulubionych stron 👆\n\nW międzyczasie obserwuj pasek adresu. Będę blokować mechanizmy śledzące i w miarę możliwości poprawiać bezpieczeństwo połączenia 🔒"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Estás tudo pronto!\n\nQueres ver como te protejo? Experimenta visitar um dos teus sites favoritos 👆\n\nContinua a observar a barra de endereço à medida que vais avançando. Vou bloquear os rastreadores e melhorar a segurança da tua ligação sempre que possível 🔒"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "Все готово!\n\nХотите увидеть, как я вас защищаю? Зайдите на один из любимых сайтов 👆\n\nСледите за адресной строкой. Я по возможности буду блокировать трекеры и обеспечивать вам более безопасное соединение 🔒"
}
}
Expand Down Expand Up @@ -44086,6 +44086,18 @@
}
}
},
"pinning.hide-aichat-shortcut" : {
"comment" : "Menu item for hiding the AI Chat shortcut",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Hide AI Chat Shortcut"
}
}
}
},
"pinning.hide-autofill-shortcut" : {
"comment" : "Menu item for hiding the passwords shortcut",
"extractionState" : "extracted_with_value",
Expand Down Expand Up @@ -44326,6 +44338,18 @@
}
}
},
"pinning.show-aichat-shortcut" : {
"comment" : "Menu item for showing the AI Chat shortcut",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Show AI Chat Shortcut"
}
}
}
},
"pinning.show-autofill-shortcut" : {
"comment" : "Menu item for showing the passwords shortcut",
"extractionState" : "extracted_with_value",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,29 @@ final class NetworkProtectionDebugMenu: NSMenu {

@objc func toggleEnforceRoutesAction(_ sender: Any?) {
settings.enforceRoutes.toggle()

Task {
try await Task.sleep(interval: 0.1)
try await debugUtilities.restartAdapter()
}
}

@objc func toggleIncludeAllNetworks(_ sender: Any?) {
settings.includeAllNetworks.toggle()

Task {
try await Task.sleep(interval: 0.1)
try await debugUtilities.restartAdapter()
}
}

@objc func toggleShouldExcludeLocalRoutes(_ sender: Any?) {
settings.excludeLocalNetworks.toggle()

Task {
try await Task.sleep(interval: 0.1)
try await debugUtilities.restartAdapter()
}
}

@objc func openAppContainerInFinder(_ sender: Any?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,17 @@ import SystemExtensions
#endif

import Subscription
import BrowserServicesKit

typealias NetworkProtectionStatusChangeHandler = (NetworkProtection.ConnectionStatus) -> Void
typealias NetworkProtectionConfigChangeHandler = () -> Void

final class NetworkProtectionTunnelController: TunnelController, TunnelSessionProvider {

// MARK: - Settings
// MARK: - Configuration

private let internalUserDecider: InternalUserDecider
let settings: VPNSettings

// MARK: - Defaults

let defaults: UserDefaults

// MARK: - Combine Cancellables
Expand Down Expand Up @@ -154,11 +153,13 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr
///
init(networkExtensionBundleID: String,
networkExtensionController: NetworkExtensionController,
internalUserDecider: InternalUserDecider,
settings: VPNSettings,
defaults: UserDefaults,
notificationCenter: NotificationCenter = .default,
accessTokenStorage: SubscriptionTokenKeychainStorage) {

self.internalUserDecider = internalUserDecider
self.networkExtensionBundleID = networkExtensionBundleID
self.networkExtensionController = networkExtensionController
self.notificationCenter = notificationCenter
Expand Down Expand Up @@ -349,14 +350,13 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr
protocolConfiguration.providerBundleIdentifier = Bundle.tunnelExtensionBundleID
protocolConfiguration.providerConfiguration = [
NetworkProtectionOptionKey.defaultPixelHeaders: APIRequest.Headers().httpHeaders,
NetworkProtectionOptionKey.includedRoutes: includedRoutes().map(\.stringRepresentation) as NSArray
]

// always-on
protocolConfiguration.disconnectOnSleep = false

// kill switch
protocolConfiguration.enforceRoutes = settings.enforceRoutes
protocolConfiguration.enforceRoutes = enforceRoutes

// this setting breaks Connection Tester
protocolConfiguration.includeAllNetworks = settings.includeAllNetworks
Expand Down Expand Up @@ -732,6 +732,13 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr
try await tunnelManager.saveToPreferences()
}

// MARK: - Routing

private var enforceRoutes: Bool {
internalUserDecider.isInternalUser
&& settings.enforceRoutes
}

/* Temporarily disabled until we fix this menu: https://app.asana.com/0/0/1205766100762904/f
@MainActor
private func excludedRoutes() -> [NetworkProtection.IPAddressRange] {
Expand All @@ -753,7 +760,45 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr
/// extra Included Routes appended to 0.0.0.0, ::/0 (peers) and interface.addresses
@MainActor
private func includedRoutes() -> [NetworkProtection.IPAddressRange] {
[]
guard enforceRoutes else {
return []
}

return [
IPAddressRange(stringLiteral: "1.0.0.0/8"),
IPAddressRange(stringLiteral: "2.0.0.0/8"),
IPAddressRange(stringLiteral: "3.0.0.0/8"),
IPAddressRange(stringLiteral: "4.0.0.0/6"),
IPAddressRange(stringLiteral: "8.0.0.0/7"),
IPAddressRange(stringLiteral: "11.0.0.0/8"),
IPAddressRange(stringLiteral: "12.0.0.0/6"),
IPAddressRange(stringLiteral: "16.0.0.0/4"),
IPAddressRange(stringLiteral: "32.0.0.0/3"),
IPAddressRange(stringLiteral: "64.0.0.0/2"),
IPAddressRange(stringLiteral: "128.0.0.0/3"),
IPAddressRange(stringLiteral: "160.0.0.0/5"),
IPAddressRange(stringLiteral: "168.0.0.0/6"),
IPAddressRange(stringLiteral: "172.0.0.0/12"),
IPAddressRange(stringLiteral: "172.32.0.0/11"),
IPAddressRange(stringLiteral: "172.64.0.0/10"),
IPAddressRange(stringLiteral: "172.128.0.0/9"),
IPAddressRange(stringLiteral: "173.0.0.0/8"),
IPAddressRange(stringLiteral: "174.0.0.0/7"),
IPAddressRange(stringLiteral: "176.0.0.0/4"),
IPAddressRange(stringLiteral: "192.0.0.0/9"),
IPAddressRange(stringLiteral: "192.128.0.0/11"),
IPAddressRange(stringLiteral: "192.160.0.0/13"),
IPAddressRange(stringLiteral: "192.169.0.0/16"),
IPAddressRange(stringLiteral: "192.170.0.0/15"),
IPAddressRange(stringLiteral: "192.172.0.0/14"),
IPAddressRange(stringLiteral: "192.176.0.0/12"),
IPAddressRange(stringLiteral: "192.192.0.0/10"),
IPAddressRange(stringLiteral: "193.0.0.0/8"),
IPAddressRange(stringLiteral: "194.0.0.0/7"),
IPAddressRange(stringLiteral: "196.0.0.0/6"),
IPAddressRange(stringLiteral: "200.0.0.0/5"),
IPAddressRange(stringLiteral: "208.0.0.0/4")
]
}

/* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,13 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate {
return controller
}()

private let internalUserDecider = DefaultInternalUserDecider(store: UserDefaults.appConfiguration)

@MainActor
private lazy var tunnelController = NetworkProtectionTunnelController(
networkExtensionBundleID: tunnelExtensionBundleID,
networkExtensionController: networkExtensionController,
internalUserDecider: internalUserDecider,
settings: tunnelSettings,
defaults: userDefaults,
accessTokenStorage: accessTokenStorage)
Expand Down
Loading