I realized that using 1 target per network extension (so 2 targets in total) is a non starter, because the main app can only have one NEFIlterManager, so couldn’t control both.
So I focused on the solution of having 1 system extension that cumulates the two Filter%Provider, with this Info.plist:
NEProviderClasses
com.apple.networkextension.filter-packet
$(PRODUCT_MODULE_NAME).FilterPacketProvider
com.apple.networkextension.filter-data
$(PRODUCT_MODULE_NAME).FilterDataProvider
The extension loads fine, the problem is that only 1 FilterProvider receives the startFilter callback when I do this:
func loadFilterConfiguration(completionHandler: @escaping (Bool) -> Void) {
NEFilterManager.shared().loadFromPreferences { loadError in
DispatchQueue.main.async {
var success = true
if let error = loadError {
print("Failed to load the filter configuration: %@", error.localizedDescription)
success = false
}
completionHandler(success)
}
}
}
loadFilterConfiguration { success in
guard success else {
print("Errrrror !")
return
}
if (true) {
let providerConfiguration = NEFilterProviderConfiguration()
providerConfiguration.filterSockets = true
providerConfiguration.filterPackets = true
filterManager.providerConfiguration = providerConfiguration
if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
filterManager.localizedDescription = appName
}
}
filterManager.isEnabled = true
filterManager.saveToPreferences { saveError in
DispatchQueue.main.async {
if let error = saveError {
os_log("%@", error.localizedDescription)
return
}
os_log("%{public}s %{public}s", NEFilterManager.shared().providerConfiguration!.filterDataProviderBundleIdentifier!, NEFilterManager.shared().providerConfiguration!.filterPacketProviderBundleIdentifier! )
}
}
}
Unless there is something I am doing wrong in the code above, this starts feeling like a bug in macOS. Both the filters should receive the startFilter callback, after this.
Note that when I keep only 1 FIlter%Provider (either one) in my extension, it works fine, indicating there is no issue in the Filter%Provider code themselves.