I've come to the conclusion that TPP and UDP are just utterly wonky together.
This is my relevant code:
let host = NWHostEndpoint(hostname: "", port: "0")
let udpRule = NENetworkRule(destinationNetwork: host, prefix: 0, protocol: .UDP)
let tcpRule = NENetworkRule(destinationNetwork: host, prefix: 0, protocol: .TCP)
let settings = NETransparentProxyNetworkSettings(tunnelRemoteAddress:"127.0.0.1")
/*
* These three lines are a hack and experiment
*/
let quicHost_1 = NWHostEndpoint(hostname: "", port: "80")
let quicHost_2 = NWHostEndpoint(hostname: "", port: "443")
let quicRule_1 = NENetworkRule(destinationNetwork: quicHost_1, prefix: 0, protocol: .UDP)
let quicRule_2 = NENetworkRule(destinationNetwork: quicHost_2, prefix: 0, protocol: .UDP)
settings.includedNetworkRules = [quicRule_1, quicRule_2, tcpRule]
settings.excludedNetworkRules = nil
Directing UDP through a TPP breaks FaceTime, AirDrop, and a bunch of VPNs
Despite the documentation implication that you can't do DNS control with a TPP ("A port string of 53 is not allowed. Use Destination Domain-based rules to match DNS traffic."), if I opt into UDP (settings.includedNetworkRules = [udpRule, tcpRule]), then I see traffic to port 53, and can do things with it.
If I use a wild-card network rule (the code above), then the TPP does not seem to get any UDP flows at all.
If I use a wild-card exclusion rule (using NWHostEndpoint(hostname: "", port: "53")), then everything starts breaking.
If I use NENetworkRule(destinationHost: host, protocol: .UDP), it complains because the prefix must be 32 or less.
I've filed feedbacks, and engaged with eskimo (really, thank you), and looked at previous threads, so mostly this is begging: has anyone gotten this to work as expected? I no longer think I'm being obviously wrong with my code, but I would be super delighted to find out I've missed some tricks or angles.
Network Extension
RSS for tagCustomize and extend the core networking features of iOS, iPad OS, and macOS using Network Extension.
Posts under Network Extension tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi all,
I'm working on a small PoC to get Content Filtering (FilterDataProvider) working on macOS without any user interaction.
So far, I've pushed two payloads to my machine using user-approved MDM enrollment:
com.apple.system-extension-policy
com.apple.webcontent-filter
The application containing the network extension is present in /Applications.
The installation of the profiles both succeed and I can see a Content Filter is created in the Network section of System Settings. Even the status says "Enabled", but the dot remains orange.
Inspecing the system logs (specifically: filtering on process:neagent) shows me the following error:
1. Failed to find a com.apple.networkextension.filter-data extension inside of app com.my.app.containing.the.ext
Only when I submit an activation request using OSSystemExtensionRequest.activationRequest, the network extension starts (without prompts, as expected) and everything works.
Is this expected behaviour? Do I need to submit an activation request through code regardless of the fact that MDM pre-approved the System Extension prompts and created the Content Filter in the System Settings?
Because it may be quicker to ask: with a TPP, readData() gets a data size of 0 if the process has finished writing to the network. However, there seems to be no way to find out if it has finished reading from the network, other than to do a .write() and see if you get an error. (I filed a FB about this, for whatever that's worth.)
Since the API is flow-based, not socket, it's not possible to tell if the app has set its own timeout. Or exited. So one question I have is: if I do flow.write(Data(count:0)) -- is that a possible way to determine if it's still around? Or will it be interpreted as read(2) returning 0?
(Putting this in for testing is difficult, but not impossible -- as I said, this might be the quickest way to find out.)
xcode15.3, ios 17.4SDK VPN NEPacketTunnelProvider, After successful socket listen local ip 0.0.0.0, data packets cannot be received in release mode, but can be received in debug mode.This bug has been bothering me for a few days. Please help me. Thank you very much.
In networkExtension code:
... let ip4Set = ...
ip4Set.includedRoutes = [NEIPv4Route.default()]
...
func readDevicePackets(){
...
packetFlow.readPacketObjects { (packetList) in
... let sendPacketList: [NEPacket] = changePacket(packetList)
... packetFlow.writePacketObjects(sendPacketList)
readDevicePackets()
}
Issue:
Our app is currently experiencing an unexpected behavior related to VPN functionality on iOS devices. Despite having the "OnDemandUserOverrideDisabled" parameter set to 1 in our VPN profile, users have reported that they can create a shortcut to disable the "Connect On Demand" feature. However, upon doing so, toggling off the VPN does not re-enable the feature as anticipated. This oversight results in unfiltered browsing, potentially compromising user security and privacy.
Explanation:
The presence of "OnDemandUserOverrideDisabled" set to 1 in our VPN profile should theoretically prevent users from toggling the "Connect On Demand" feature via any means. However, users have found a workaround using shortcuts to bypass this safeguard. Consequently, the VPN does not automatically re-engage after being disabled, leading to unintended consequences for users.
Impact:
The inability to reliably control VPN settings, despite profile configurations, poses a significant risk to user data privacy and security. Unintended unfiltered browsing can expose users to malicious actors and compromise sensitive information.
OS Version: macOS 13.6.3 (22G436)
Code Type: ARM64
We recently observed that the system extension process CPU based on networkextension (data-filter firewall) has been 99% busy for a period of time.
We try to deauthorize data-filter so that the firewall stops working and the NEFilterDataProvider object is released. However, the system extension process CPU usage is always 99% busy.
Then I used Instruments-CPU Counters to observe that a thread (thread id: 0x2abf9b) has been busy, but no useful backtrace information was captured. Through the sample command, I caught the backtrace and found that the busy process (thread id: 2801563 == 0x2abf9b) is in this state.
35 Thread_1336407 DispatchQueue_442: NEFilterExtensionProviderContext queue (serial)
+ 35 start_wqthread (in libsystem_pthread.dylib) + 8 [0x1a1afad94]
+ 35 _pthread_wqthread (in libsystem_pthread.dylib) + 288 [0x1a1afc074]
+ 35 _dispatch_workloop_worker_thread (in libdispatch.dylib) + 648 [0x1a1963244]
+ 35 _dispatch_lane_invoke (in libdispatch.dylib) + 384 [0x1a19585f8]
+ 35 _dispatch_lane_serial_drain (in libdispatch.dylib) + 372 [0x1a1957960]
+ 35 _dispatch_source_invoke (in libdispatch.dylib) + 1176 [0x1a1966ce0]
+ 35 _dispatch_source_cancel_callout (in libdispatch.dylib) + 204 [0x1a1967890]
+ 35 _dispatch_continuation_pop (in libdispatch.dylib) + 504 [0x1a1953884]
+ 35 _dispatch_client_callout (in libdispatch.dylib) + 20 [0x1a1950400]
+ 35 _dispatch_call_block_and_release (in libdispatch.dylib) + 32 [0x1a194e874]
+ 35 __75-[NEFilterDataExtensionProviderContext setupSocketSourceWithControlSocket:]_block_invoke (in NetworkExtension) + 112 [0x1b1e0dd74]
+ 35 close (in libsystem_kernel.dylib) + 8 [0x1a1ac0ac0]
note: the picture screenshot and the text description backtrace are from different machines, but the problem is the same.
This seems to be a newly introduced bug in the network extension? This problem did not occur for a long time between 10.15 and 10.12.
We're looking at mitigation options for the TunnelVisioning attack that exploits DHCP option 121 to set routes. It looks like Per-App VPN doesn't have the problem, but in standard mode we aren't able to touch potentially malicious host routes, so while we can mitigate it we can't eliminate the security problem completely.
Is there any way to tell iOS and macOS to ignore DHCP option 121? Or even better, does Apple have a fix in the works?
Hi, we are a Carrier company (Utility provider) and working on a feature to display real-time Wifi Signal strength of customer devices (connected to Router Gateway) to help customers identify low and high signal areas, and possibly install extenders to improve signal strength at weak points. This feature requires NEHotspotHelper entitlement approval to access signalStrength property. We went through this Apple documentation too and we're open to other recommendations from Apple https://developer.apple.com/forums/thread/721067 .
Since we currently don't have direct point of contact with Apple to discuss this requirement, hence wanted to check it here. Kindly advise. Thanks !
After I upgraded xcode to 15.3 , Then VPN NetworkExtension NEPacketTunnelProvider cannot send TCP packets in release mode, but can send TCP packets in debug mode, please help me!!!
Hello!
I'm trying to capture socket state changes for an endpoint security product and have tried the Endpoint Security APIs as well as a Network Extension but there doesn't seem to be a way to detect listening sockets in real time. I've so far been able to capture all process, file and network flow/packet information in real-time but I'm also interested in getting an event when a server socket is opened for listening for incoming connections. Is there a way to do this? If yes, can someone please point me to the documentation or any other information on how to go about it? Thanks!
Hi everyone,
I'm working on an iOS app where I need to implement content filtering functionality.
I've successfully implemented a network extension target in my iOS app to filter data locally. However, I'm now aiming to extend this functionality to filter content over HTTPS. Currently, I'm utilizing a local data source for filtering, but I want to explore options for filtering content directly over HTTPS connections, like this URL: https://dns.nextdns.io/46d65d.
I've reviewed the available Apple APIs and documentation but haven't found a straightforward solution for HTTPS content filtering. Can anyone provide guidance or suggest any relevant resources for implementing HTTPS content filtering within a network extension target on iOS?
Any help or insights would be greatly appreciated!
Thank you in advance!
Hi, in my Extension FilterDataProvider class that is inherited from NEFilterDataProvider i am trying to insert logs into my CoreData entity, but when i insert it gives me error
"NSCocoaErrorDomain: -513
"reason": Unable to write to file opened Readonly
Any suggestions please to update the read write permission
i already have tried this way but no luck
let description = NSPersistentStoreDescription(url: storeURL) description.shouldInferMappingModelAutomatically = true description.shouldMigrateStoreAutomatically = true description.setOption(false as NSNumber, forKey: NSReadOnlyPersistentStoreOption)
?
I have an installation workflow that works by a user double clicking on the mpkg and going through the prompts to install some software. Within the postinstall of the mpkg, /usr/sbin/installer -pkg "path_to_pkg" -target / is done to install additional software.
The software contained in the mpkg contains system extensions and installs without issue.
The software contained in the pkg file also contains system extensions and a prompt with this message displayed.
"XSoftware" is damaged and can't be opened. You should move it to the Trash
This file was downloaded on an unknown date.
This is causing issues with the system extension being installed from XSoftware.
Curiously enough, when I run /usr/sbin/installer -pkg "path_to_pkg" -target / manually in a terminal window it works successfully and XSoftware is able to install the System Extensions and run properly.
I've used the pkgutil --check-signature to check the notarization and signing and it looks correct.
This is my dmg structure:
dmg
|
mpkg
data_folder
|
pkg
Any suggestions or help would be greatly appreciated. I can provide more details if neccessary.
Hello, i am trying to record logs in my network extension class, and then i want to read it in my application class, i.e. viewModel. However, i am unable to read the data. I have tried different ways like UserDefaults, Keychain, FileManager, NotificationCenter and CoreData. I have also used Appgroups but still there is blocker for reading data outside the scope of Extension class.
This one is sorta behaving similar to the FaceTime / AirDrop issue, but it does depend on order, which makes me wonder if it's a programming choice. Specifically, using FortiNet's VPN client, using IPSec, if I have a TPP installed and then try to connect it, it fails. If, however, I connect and then start the TPP, it succeeds, which at least makes it better than FaceTime and AirDrop.
So my question here is... hm, not as well-articulated as I would like. I'm curious if a VPN can check to see if other VPNs are installed and configured, and if so say "nope." Hm, saying that more clearly: I think it's possible for a network extension to check the interface that a packet/flow is going to, and cause a failure of some sort if it's a VPN, correct? Does anyone do that? Or am I seeing lions in the waterhole weeds?
I'm also curious if Apple's networking code has issues with multiple VPNs. (Although, I will note, our TPP works just fine with Tailscale, so it's not an inherent conflict. Also Cisco AnyConnect. So maybe it's just IPSec?)
ETA: to make it clear, my test case involves using a ****** TPP, where handleNewUDPFlow and handleNewFlow both immediately return false, meaning that the system should behave as if it's not there, and yet... doesn't.
I appreciate any comments/assistance/guffaws.
Hi, I have been working on some kind of network filtering app for iOS using Content Filter Provider. And I have stored rules for each domain.
As of right now, I use UserDefaults with my app's bundle suite to store and observe rules. I have also read this documentation page for UserDefaults link.
Is it okay to use UserDefaults in my case, if I have rules added/modified dynamically as the flow is intercepted, or should I pick some other approach like Core Data, SwiftData, etc.?
Thank you!
Hello,
I have some question about the usage of the function:
func update(NEFilterSocketFlow, using: NEFilterDataVerdict, for: NETrafficDirection)
(https://developer.apple.com/documentation/networkextension/nefilterdataprovider/3543400-update)
provided by the NEFilterDataProvider class of the content filter network extension.
If I understand correctly, this function can be used on an instance of NEFilterDataProvider to update an already issued verdict for a network flow. By "issuing verdict" I mean returning any of .allow()/.drop()/.init(pass: peek:) in handleNewFlow/handleInboundData/handleOutboundData
However, I am having difficulty with it. My workflow involves maintaining an array of currently active flows. Flows are inserted in handleNewFlow() and they are deleted when handleReport(report: NEFilterReport) with event flowClosed is called (flow identification is based on their UUID). Then, at some point in future, based on our business logic, I iterate through the container of "active flows" and attempt to call func update(NEFilterSocketFlow, using: NEFilterDataVerdict, for: NETrafficDirection) on all of them, with intention of changing the already issued verdict.
However, calling that function seems to have no effect. Am I using it the wrong way? What is the intended usage? Is it even possible to update verdict of already allowed or postponed by .init(peek:pass:) flows?
The issue I'm trying to solve is that we evaluate flows based on our business logic and return either .drop() or .init(pass: peek:) verdicts for them. Sometimes, we want to reevaluate the .init(pass: peek:) verdict immediately, which is when we attempt to call the update() function and provide a new .init(pass:peek) or .drop() verdict.
The main objective is to promptly drop certain flows, particularly those awaiting further data evaluation due to .init(pass: peek), immediately on demand.
Thanks.
I am working on a VPN app featuring Wireguard. The app was working fine. I planned to make a Framework for the Wireguard Target, Network Extension Target and the Code managing VPN, Now after removing all errors, resolving Bundle IDs and making all the targets compatible to iOS 16.0, I am getting this error in the Settings app as shown in the following
In short, same code is not working when moved into the framework.
I have read the similar thread talking about lowering the minimum deployments. All of my minimum deployments are set to iOS 16.0.
Any suggestions would be appreciated.
Thanking you in anticipation.
Ali.
On the [documentation page](Implement a completely custom DNS proxying protocol) it says
For example, a DNS proxy provider might:
Implement a completely custom DNS proxying protocol
I would like to add some filtering logic to the NEDNSProxyProvider (for example, return nxdomain if the flow is not passing the filtering process). Is it possible to implement with NEDNSProxyProvider? It also says that
func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool
from NEDNSProxyProvider returns a Boolean value set to true if the proxy implementation decides to handle the flow, or false if it instead decides to terminate the flow link. Does it mean that the filtering logic could be added here by just returning false for the flows that are not matching the rules?
Because I first tried to handle UDP flows like this in handleNewFlow(_ flow: NEAppProxyUDPFlow) function and form my own packets in connection.transferData, by first passing empty Data object and then by setting RCODE to 3, which is supposedly a nxdomain response code. However, both implementations didn't work: even though I was getting logs about handling failure, the flow was still able to go through.
try await flow.open(withLocalEndpoint: flow.localEndpoint as? NWHostEndpoint)
let datagrams = try await flow.readDatagrams()
let results = try await datagrams.parallelMap {
let connection = try DatagramConnection($0)
return try await connection.transferData()
}
try await flow.writeDatagrams(results)
flow.closeReadWithError(nil)
flow.closeWriteWithError(nil)
I am new to NEDNSProxyProvider and my networking knowledge is on a pretty basic level, so I would be very grateful to hear any suggestions. Thank you!
I want to use Network Extension Relay to implement a system-wide proxy. First, I will setup a local http2 proxy and forward to a local http proxy. The problem is
How to implement this http2relayurl link to? Is it a regular http2 proxy protocol?
What should I pass to raw public keys? Is it a bytes like rsa public key, or is .pem, .pub like plain text string? And I will use self signed certificate, will it be a problem?