Hi, I am working on the app for some basic concept, I would like to intercept both DNS and IP connections. I succeeded in intercepting DNS using NEDNSProxyProvider
, however I seem to have some troubles with IPConnections using NEFilterDataProvider
.
First thing, I have three targets in my app. For some reason, when I run DNS Proxy Extension target it doesn't ask me to choose the app for target run, and after the application if launched, it correctly intercepts DNS traffic and inits NEDNSProxyManager
ps: all logs are correctly displayed for NEFilterDataProvider
However, when I try to run Filter Data Extension target with Content Filter capability, it asks me to choose the app for run. Even tho I checked the Build Settings and those are identical to DNS Proxy Extension target.
And finally, when I run main target it still inits NEDNSProxyManager
properly and the NEFilterManager
returns this warning
-[NEFilterManager saveToPreferencesWithCompletionHandler:]_block_invoke_3: failed to save the new configuration: (null)
I tried to log the configuration and compared to some code samples, but I can't identify the problem.
I'd very grateful if somebody could suggest where the problems might be (targets builds difference & NEFilterManager
config)
I will attach a sample of code where I add configuration to my NEFilterManager
// MARK: - FilterDataManager
final class FilterDataManager: NSObject, ObservableObject {
// MARK: - Properties
private let manager = NEFilterManager.shared()
private let filterName = "Data Filter"
@Published
private(set) var isEnabled: Bool? = nil
// MARK: - Singleton
static let shared = FilterDataManager()
// Cancellables set
private var subs: Set<AnyCancellable> = []
private override init() {
super.init()
enable()
manager.isEnabledPublisher()
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] isEnabled in
self?.setIsEnabled(isEnabled)
})
.store(in: &subs)
}
// MARK: - Filter Configurations
func enable() {
manager.updateConfiguration { [unowned self] manager in
manager.localizedDescription = filterName
manager.providerConfiguration = createFilterProviderConfiguration()
manager.isEnabled = true
} completion: { result in
guard case let .failure(error) = result else { return }
Log("Filter enable failed: \(error)", prefix: "[Filter]")
}
}
private func createFilterProviderConfiguration() -> NEFilterProviderConfiguration {
let configuration = NEFilterProviderConfiguration()
configuration.organization = "***"
configuration.filterBrowsers = true
configuration.filterSockets = true
return configuration
}
func disable() {
Log("Will disable filter", prefix: "[Filter]")
manager.updateConfiguration { manager in
manager.isEnabled = false
} completion: { result in
guard case let .failure(error) = result else { return }
Log("Filter enable failed: \(error)")
}
}
private func setIsEnabled(_ isEnabled: Bool) {
guard self.isEnabled != isEnabled else { return }
self.isEnabled = isEnabled
Log("Filter \(isEnabled ? "enabled" : "disabled")", prefix: "[Filter]")
}
}
```Swift
extension NEFilterManager {
// MARK: - NEFilterManager config update
func updateConfiguration(_ body: @escaping (NEFilterManager) -> Void, completion: @escaping (Result<Void, Error>) -> Void) {
loadFromPreferences { [unowned self] error in
if let error,
let filterError = FilterError(error) {
completion(.failure(filterError))
return
}
body(self)
saveToPreferences { (error) in
if let error,
let filterError = FilterError(error) {
completion(.failure(filterError))
return
}
completion(.success(()))
}
}
}
// MARK: - Publisher enabling
func isEnabledPublisher() -> AnyPublisher<Bool, Never> {
NotificationCenter.default
.publisher(for: NSNotification.Name.NEFilterConfigurationDidChange)
.compactMap { [weak self] notification in
guard let self else { return nil }
return self.isEnabled
}
.eraseToAnyPublisher()
}
}
// MARK: - FilterError
@available(iOS 8.0, *)
enum FilterError: Error {
/// The Filter configuration is invalid
case configurationInvalid
/// The Filter configuration is not enabled.
case configurationDisabled
/// The Filter configuration needs to be loaded.
case configurationStale
/// The Filter configuration cannot be removed.
case configurationCannotBeRemoved
/// Permission denied to modify the configuration
case configurationPermissionDenied
/// Internal error occurred while managing the configuration
case configurationInternalError
case unknown
init?(_ error: Error) {
switch error {
case let error as NSError:
switch NEFilterManagerError(rawValue: error.code) {
case .configurationInvalid:
self = .configurationInvalid
return
case .configurationDisabled:
self = .configurationDisabled
return
case .configurationStale:
self = .configurationStale
return
case .configurationCannotBeRemoved:
self = .configurationCannotBeRemoved
return
case .some(.configurationPermissionDenied):
self = .configurationPermissionDenied
return
case .some(.configurationInternalError):
self = .configurationInternalError
return
case .none:
return nil
@unknown default:
break
}
default:
break
}
assertionFailure("Invalid error \(error)")
return nil
}
}