mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-13 11:22:06 +00:00
Optionally resort to CloudFlare when no DNS settings are provided (#1165)
Fixes #1152
This commit is contained in:
parent
cc8a500dab
commit
c2a8db1cdb
81
Packages/App/Sources/CommonLibrary/CommonLibrary.swift
Normal file
81
Packages/App/Sources/CommonLibrary/CommonLibrary.swift
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// CommonLibrary.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 2/11/25.
|
||||
// Copyright (c) 2025 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutKit
|
||||
|
||||
public final class CommonLibrary {
|
||||
public enum Target {
|
||||
case app
|
||||
|
||||
case tunnel
|
||||
}
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func configure(_ target: Target) {
|
||||
switch target {
|
||||
case .app:
|
||||
configureApp()
|
||||
case .tunnel:
|
||||
configureTunnel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension CommonLibrary {
|
||||
func configureApp() {
|
||||
configureShared()
|
||||
|
||||
PassepartoutConfiguration.shared.configureLogging(
|
||||
to: BundleConfiguration.urlForAppLog,
|
||||
parameters: Constants.shared.log,
|
||||
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
||||
)
|
||||
}
|
||||
|
||||
func configureTunnel() {
|
||||
configureShared()
|
||||
|
||||
PassepartoutConfiguration.shared.configureLogging(
|
||||
to: BundleConfiguration.urlForTunnelLog,
|
||||
parameters: Constants.shared.log,
|
||||
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
||||
)
|
||||
if UserDefaults.appGroup.bool(forKey: AppPreference.dnsFallsBack.key) {
|
||||
let servers = Constants.shared.tunnel.dnsFallbackServers
|
||||
PassepartoutConfiguration.shared.dnsFallbackServers = servers
|
||||
pp_log(.app, .info, "Enable DNS fallback servers: \(servers)")
|
||||
}
|
||||
}
|
||||
|
||||
func configureShared() {
|
||||
UserDefaults.appGroup.register(defaults: [
|
||||
AppPreference.logsPrivateData.key: false,
|
||||
AppPreference.dnsFallsBack.key: true
|
||||
])
|
||||
}
|
||||
}
|
@ -26,6 +26,9 @@
|
||||
import Foundation
|
||||
|
||||
public enum AppPreference: String, PreferenceProtocol {
|
||||
case dnsFallsBack
|
||||
// case dnsFallbackServers
|
||||
|
||||
case lastUsedProfileId
|
||||
|
||||
case logsPrivateData
|
||||
|
@ -114,6 +114,8 @@ public struct Constants: Decodable, Sendable {
|
||||
|
||||
public let refreshInterval: TimeInterval
|
||||
|
||||
public let dnsFallbackServers: [String]
|
||||
|
||||
public let verification: Verification
|
||||
|
||||
public func verificationDelayMinutes(isBeta: Bool) -> Int {
|
||||
|
@ -27,6 +27,10 @@
|
||||
"tunnel": {
|
||||
"profileTitleFormat": "Passepartout: %@",
|
||||
"refreshInterval": 3.0,
|
||||
"dnsFallbackServers": [
|
||||
"1.1.1.1",
|
||||
"1.0.0.1"
|
||||
],
|
||||
"verification": {
|
||||
"production": {
|
||||
"delay": 120.0,
|
||||
|
@ -828,6 +828,8 @@ public enum Strings {
|
||||
}
|
||||
}
|
||||
public enum Preferences {
|
||||
/// DNS fallback
|
||||
public static let dnsFallsBack = Strings.tr("Localizable", "views.preferences.dns_falls_back", fallback: "DNS fallback")
|
||||
/// Erase profiles from iCloud
|
||||
public static let eraseIcloud = Strings.tr("Localizable", "views.preferences.erase_icloud", fallback: "Erase profiles from iCloud")
|
||||
/// Keep in menu bar
|
||||
@ -838,6 +840,10 @@ public enum Strings {
|
||||
public static let locksInBackground = Strings.tr("Localizable", "views.preferences.locks_in_background", fallback: "Lock in background")
|
||||
/// Pin active profile
|
||||
public static let pinsActiveProfile = Strings.tr("Localizable", "views.preferences.pins_active_profile", fallback: "Pin active profile")
|
||||
public enum DnsFallsBack {
|
||||
/// Fall back to CloudFlare servers when the VPN does not provide DNS settings.
|
||||
public static let footer = Strings.tr("Localizable", "views.preferences.dns_falls_back.footer", fallback: "Fall back to CloudFlare servers when the VPN does not provide DNS settings.")
|
||||
}
|
||||
public enum EraseIcloud {
|
||||
/// To erase all profiles from the iCloud store securely, do so on all your synced devices. This will not affect local profiles.
|
||||
public static let footer = Strings.tr("Localizable", "views.preferences.erase_icloud.footer", fallback: "To erase all profiles from the iCloud store securely, do so on all your synced devices. This will not affect local profiles.")
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Wenn du diese App oder Funktion in der Vergangenheit gekauft hast, kannst du deine Käufe wiederherstellen.";
|
||||
"views.paywall.sections.restore.header" = "Wiederherstellen";
|
||||
"views.paywall.sections.suggested_product.header" = "Einmaliger Kauf";
|
||||
"views.preferences.dns_falls_back" = "DNS-Fallback";
|
||||
"views.preferences.dns_falls_back.footer" = "Fällt auf CloudFlare-Server zurück, wenn das VPN keine DNS-Einstellungen bereitstellt.";
|
||||
"views.preferences.erase_icloud" = "Profile aus iCloud löschen";
|
||||
"views.preferences.erase_icloud.footer" = "Um alle Profile sicher aus dem iCloud-Speicher zu löschen, führen Sie diese Aktion auf allen synchronisierten Geräten aus. Lokale Profile werden nicht betroffen.";
|
||||
"views.preferences.keeps_in_menu" = "In der Menüleiste behalten";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Εάν αγοράσατε αυτήν την εφαρμογή ή λειτουργία στο παρελθόν, μπορείτε να επαναφέρετε τις αγορές σας.";
|
||||
"views.paywall.sections.restore.header" = "Επαναφορά";
|
||||
"views.paywall.sections.suggested_product.header" = "Εφάπαξ αγορά";
|
||||
"views.preferences.dns_falls_back" = "Εναλλακτικό DNS";
|
||||
"views.preferences.dns_falls_back.footer" = "Χρησιμοποιεί τους διακομιστές CloudFlare όταν το VPN δεν παρέχει ρυθμίσεις DNS.";
|
||||
"views.preferences.erase_icloud" = "Διαγραφή προφίλ από το iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Για να διαγράψετε όλα τα προφίλ από το iCloud με ασφάλεια, κάντε το σε όλες τις συγχρονισμένες συσκευές σας. Αυτό δεν θα επηρεάσει τα τοπικά προφίλ.";
|
||||
"views.preferences.keeps_in_menu" = "Διατήρηση στη γραμμή μενού";
|
||||
|
@ -105,6 +105,8 @@
|
||||
"views.preferences.pins_active_profile.footer" = "Also show the active profile on top for quick access.";
|
||||
"views.preferences.locks_in_background" = "Lock in background";
|
||||
"views.preferences.locks_in_background.footer" = "Lock the app with FaceID when sent to the background.";
|
||||
"views.preferences.dns_falls_back" = "DNS fallback";
|
||||
"views.preferences.dns_falls_back.footer" = "Fall back to CloudFlare servers when the VPN does not provide DNS settings.";
|
||||
"views.preferences.erase_icloud" = "Erase profiles from iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "To erase all profiles from the iCloud store securely, do so on all your synced devices. This will not affect local profiles.";
|
||||
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Si compraste esta app o característica en el pasado, puedes restaurar tus compras.";
|
||||
"views.paywall.sections.restore.header" = "Restaurar";
|
||||
"views.paywall.sections.suggested_product.header" = "Compra única";
|
||||
"views.preferences.dns_falls_back" = "DNS de respaldo";
|
||||
"views.preferences.dns_falls_back.footer" = "Usa los servidores de CloudFlare cuando el VPN no proporciona configuraciones de DNS.";
|
||||
"views.preferences.erase_icloud" = "Eliminar perfiles de iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Para eliminar de forma segura todos los perfiles del almacenamiento de iCloud, hágalo en todos sus dispositivos sincronizados. Esto no afectará los perfiles locales.";
|
||||
"views.preferences.keeps_in_menu" = "Mantener en la barra de menús";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Si vous avez acheté cette application ou cette fonctionnalité dans le passé, vous pouvez restaurer vos achats.";
|
||||
"views.paywall.sections.restore.header" = "Restaurer";
|
||||
"views.paywall.sections.suggested_product.header" = "Achat unique";
|
||||
"views.preferences.dns_falls_back" = "Basculement DNS";
|
||||
"views.preferences.dns_falls_back.footer" = "Bascule vers les serveurs CloudFlare lorsque le VPN ne fournit pas de paramètres DNS.";
|
||||
"views.preferences.erase_icloud" = "Supprimer les profils d'iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Pour supprimer tous les profils du stockage iCloud de manière sécurisée, faites-le sur tous vos appareils synchronisés. Cela n'affectera pas les profils locaux.";
|
||||
"views.preferences.keeps_in_menu" = "Conserver dans la barre de menu";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Se hai acquistato questa app o funzionalità in passato, puoi ripristinare i tuoi acquisti.";
|
||||
"views.paywall.sections.restore.header" = "Ripristina";
|
||||
"views.paywall.sections.suggested_product.header" = "Acquisto una tantum";
|
||||
"views.preferences.dns_falls_back" = "DNS di fallback";
|
||||
"views.preferences.dns_falls_back.footer" = "Ripiega sui server CloudFlare quando il VPN non fornisce impostazioni DNS.";
|
||||
"views.preferences.erase_icloud" = "Elimina i profili da iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Per eliminare in modo sicuro tutti i profili dall'archivio iCloud, fallo su tutti i tuoi dispositivi sincronizzati. Questo non influirà sui profili locali.";
|
||||
"views.preferences.keeps_in_menu" = "Mantieni nella barra dei menu";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Als je deze app of functie eerder hebt gekocht, kun je je aankopen herstellen.";
|
||||
"views.paywall.sections.restore.header" = "Herstellen";
|
||||
"views.paywall.sections.suggested_product.header" = "Eenmalige aankoop";
|
||||
"views.preferences.dns_falls_back" = "DNS-terugval";
|
||||
"views.preferences.dns_falls_back.footer" = "Valt terug op CloudFlare-servers wanneer het VPN geen DNS-instellingen biedt.";
|
||||
"views.preferences.erase_icloud" = "Verwijder profielen van iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Om alle profielen veilig van de iCloud-opslag te verwijderen, doe dit op al uw gesynchroniseerde apparaten. Dit heeft geen invloed op lokale profielen.";
|
||||
"views.preferences.keeps_in_menu" = "In menubalk houden";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Jeśli wcześniej kupiłeś tę aplikację lub funkcję, możesz przywrócić swoje zakupy.";
|
||||
"views.paywall.sections.restore.header" = "Przywróć";
|
||||
"views.paywall.sections.suggested_product.header" = "Jednorazowy zakup";
|
||||
"views.preferences.dns_falls_back" = "Awaryjny DNS";
|
||||
"views.preferences.dns_falls_back.footer" = "Przełącza się na serwery CloudFlare, gdy VPN nie zapewnia ustawień DNS.";
|
||||
"views.preferences.erase_icloud" = "Usuń profile z iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Aby bezpiecznie usunąć wszystkie profile z iCloud, wykonaj to na wszystkich synchronizowanych urządzeniach. Nie wpłynie to na profile lokalne.";
|
||||
"views.preferences.keeps_in_menu" = "Trzymaj w pasku menu";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Se você comprou este app ou recurso no passado, pode restaurar suas compras.";
|
||||
"views.paywall.sections.restore.header" = "Restaurar";
|
||||
"views.paywall.sections.suggested_product.header" = "Compra única";
|
||||
"views.preferences.dns_falls_back" = "Fallback de DNS";
|
||||
"views.preferences.dns_falls_back.footer" = "Reverte para os servidores CloudFlare quando o VPN não fornece configurações de DNS.";
|
||||
"views.preferences.erase_icloud" = "Apagar perfis do iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Para apagar com segurança todos os perfis do armazenamento do iCloud, faça isso em todos os seus dispositivos sincronizados. Isso não afetará os perfis locais.";
|
||||
"views.preferences.keeps_in_menu" = "Manter na barra de menu";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Если вы уже купили это приложение или функцию в прошлом, вы можете восстановить свои покупки.";
|
||||
"views.paywall.sections.restore.header" = "Восстановить";
|
||||
"views.paywall.sections.suggested_product.header" = "Единоразовая покупка";
|
||||
"views.preferences.dns_falls_back" = "Резервный DNS";
|
||||
"views.preferences.dns_falls_back.footer" = "Переключается на серверы CloudFlare, если VPN не предоставляет настройки DNS.";
|
||||
"views.preferences.erase_icloud" = "Удалить профили из iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Чтобы безопасно удалить все профили из iCloud, выполните это действие на всех ваших синхронизированных устройствах. Это не затронет локальные профили.";
|
||||
"views.preferences.keeps_in_menu" = "Оставить в строке меню";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Om du har köpt denna app eller funktion tidigare kan du återställa dina köp.";
|
||||
"views.paywall.sections.restore.header" = "Återställ";
|
||||
"views.paywall.sections.suggested_product.header" = "Engångsköp";
|
||||
"views.preferences.dns_falls_back" = "DNS-backup";
|
||||
"views.preferences.dns_falls_back.footer" = "Återgår till CloudFlare-servrar när VPN inte tillhandahåller DNS-inställningar.";
|
||||
"views.preferences.erase_icloud" = "Radera profiler från iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "För att säkert radera alla profiler från iCloud-lagringen, gör det på alla dina synkroniserade enheter. Detta påverkar inte lokala profiler.";
|
||||
"views.preferences.keeps_in_menu" = "Behåll i menyraden";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "Якщо ви раніше купували цей додаток або функцію, ви можете відновити свої покупки.";
|
||||
"views.paywall.sections.restore.header" = "Відновлення";
|
||||
"views.paywall.sections.suggested_product.header" = "Одноразова покупка";
|
||||
"views.preferences.dns_falls_back" = "Резервний DNS";
|
||||
"views.preferences.dns_falls_back.footer" = "Перемикається на сервери CloudFlare, коли VPN не надає налаштування DNS.";
|
||||
"views.preferences.erase_icloud" = "Видалити профілі з iCloud";
|
||||
"views.preferences.erase_icloud.footer" = "Щоб безпечно видалити всі профілі з iCloud, виконайте цю дію на всіх ваших синхронізованих пристроях. Це не вплине на локальні профілі.";
|
||||
"views.preferences.keeps_in_menu" = "Залишати в рядку меню";
|
||||
|
@ -274,6 +274,8 @@
|
||||
"views.paywall.sections.restore.footer" = "如果您过去购买过此应用或功能,可以恢复您的购买记录。";
|
||||
"views.paywall.sections.restore.header" = "恢复";
|
||||
"views.paywall.sections.suggested_product.header" = "一次性购买";
|
||||
"views.preferences.dns_falls_back" = "DNS 备用";
|
||||
"views.preferences.dns_falls_back.footer" = "当 VPN 不提供 DNS 设置时,回退到 CloudFlare 服务器。";
|
||||
"views.preferences.erase_icloud" = "从 iCloud 中删除配置文件";
|
||||
"views.preferences.erase_icloud.footer" = "要安全地从 iCloud 存储中删除所有配置文件,请在所有已同步的设备上执行此操作。这不会影响本地配置文件。";
|
||||
"views.preferences.keeps_in_menu" = "保持在菜单栏";
|
||||
|
@ -41,11 +41,8 @@ public final class UILibrary: UILibraryConfiguring {
|
||||
}
|
||||
|
||||
public func configure(with context: AppContext) {
|
||||
PassepartoutConfiguration.shared.configureLogging(
|
||||
to: BundleConfiguration.urlForAppLog,
|
||||
parameters: Constants.shared.log,
|
||||
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
||||
)
|
||||
CommonLibrary().configure(.app)
|
||||
|
||||
assertMissingImplementations(with: context.registry)
|
||||
uiConfiguring?.configure(with: context)
|
||||
}
|
||||
|
@ -40,6 +40,9 @@ public struct PreferencesGroup: View {
|
||||
private var settings: MacSettingsModel
|
||||
#endif
|
||||
|
||||
@AppStorage(AppPreference.dnsFallsBack.key, store: .appGroup)
|
||||
private var dnsFallsBack = true
|
||||
|
||||
private let profileManager: ProfileManager
|
||||
|
||||
@State
|
||||
@ -60,6 +63,7 @@ public struct PreferencesGroup: View {
|
||||
keepsInMenuToggle
|
||||
#endif
|
||||
pinActiveProfileToggle
|
||||
dnsFallsBackToggle
|
||||
eraseCloudKitButton
|
||||
}
|
||||
}
|
||||
@ -87,6 +91,11 @@ private extension PreferencesGroup {
|
||||
.themeSectionWithSingleRow(footer: Strings.Views.Preferences.PinsActiveProfile.footer)
|
||||
}
|
||||
|
||||
var dnsFallsBackToggle: some View {
|
||||
Toggle(Strings.Views.Preferences.dnsFallsBack, isOn: $dnsFallsBack)
|
||||
.themeSectionWithSingleRow(footer: Strings.Views.Preferences.DnsFallsBack.footer)
|
||||
}
|
||||
|
||||
var eraseCloudKitButton: some View {
|
||||
Button(Strings.Views.Preferences.eraseIcloud, role: .destructive) {
|
||||
isConfirmingEraseiCloud = true
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 191369cb4a9a34acac747f2fffd19ea470f8f79e
|
||||
Subproject commit 595ebe59c71151d0661a018cd61d3af77114cd79
|
@ -38,11 +38,8 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
|
||||
private var fwd: NEPTPForwarder?
|
||||
|
||||
override func startTunnel(options: [String: NSObject]? = nil) async throws {
|
||||
PassepartoutConfiguration.shared.configureLogging(
|
||||
to: BundleConfiguration.urlForTunnelLog,
|
||||
parameters: Constants.shared.log,
|
||||
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
||||
)
|
||||
CommonLibrary().configure(.tunnel)
|
||||
|
||||
pp_log(.app, .info, "Tunnel started with options: \(options?.description ?? "nil")")
|
||||
|
||||
let environment = await dependencies.tunnelEnvironment()
|
||||
|
Loading…
Reference in New Issue
Block a user