Post

Replies

Boosts

Views

Activity

Filtering DNS packets via Network Extension
Hello, we are working on a feature that sometimes needs to drop/postpone DNS requests except for requests for allowed domains or originating from allowed executables. In this product we already have a network extension Socket Filter present. We were looking for correct technology to use for this purpose. 1), socket filter can not be used, as it is not possible to selectively drop only some UDP packets. If we block one flow, the socket can no longer be used to communicate with the specific remote IP and fails with EPIPE. This leads to DNS resolving issues as not every software can cope with UDP not working for part of the remote servers (AFAIK including Apple's own mDNSresponder). 2), loading socket filter drops all active connections. This is understandable for firewall type API, but it is an extremely inconvenient behavior if we do not want to actually implement a firewall. There is currently no option to configure this behavior of socket filter. 3), using DNS proxy is not really feasible, as it is not a transparent proxy and only a single DNS proxy can run at any given time. In case of multiple registered DNS proxies only the last one stays running. It is also a pretty heavyweight solution for what we want to accomplish. We tried using BSD pf packet filter with user specific rules: "pass out quick from any to any keep state user nameofuser" but 4) this breaks if DNS proxy is present. Attribution of proxied flows is not visible to BSD pf packet filter which sees all traffic as attributed to the DNS proxy instead of the original process. This has been reported as working as intended by Apple. The only other solution seems to be a packet level filter. But here we hit other issues: 5), since order of processing is Socket Filter —> DNS proxy -> VPN -> packet filter, we can not guarantee all traffic will be filtered (packet filter does not see at least some VPN traffic on MacOS, did not test this with all VPN types though...) 6). the NEFilterPacketProvider does not seem to have a way how to attribute the packet to a process. While the NEPacket obtained via delayCurrentPacket() has a metadata member, it seems to be never present on MacOS (at least on Monterey). This prevents per app/process/binary filtering and leaves only packet content inspection as an option. While it may in theory be possible to use Socket Filter to attribute packet level addresses to processes, it seems pretty cumbersome and potentially fragile in case DNS proxy is used. 7), there is an issue with coexistence of Packet and Socket filter. It seems that any change of NEFilterManager’s configuration concerning packet filter causes brief stop and start of socket filter as well. This is extremely inconvenient because a socket filter reload subsequently leads to the drop of all connections on the system. Please note that the packet filter does not cause such drop of connections on loading, so it would be ideal for our purpose. The only workaround is to have multiple system extensions, which is actually a correct engineering approach, but that leads to a horrible user experience. Allowing multiple system extensions is far from streamlined for the average user, and he would need to also allow one filter after each other separately. If we were to use socket filter, DNS proxy, VPN and packet filter in a single product, which ideally should each reside in standalone system extensions for resilience, the user would need to allow 8 separate dialogs!! And adding feature during lifetime of the product should not lead to repeated requests to allow system extensions; this is a nightmare from administration point of view. It should really be a once per app action (at least the load of system extension). But we are getting sidetracked. Coexistence seems like the most feasible user centric solution, but it is not really possible with the combination of Socket and Packet filters. Am I missing something or is the only possible solution to use Packet Filter extension (a second one, to not interfere with the Socket Filter one) and filtering based on packet content, which only works for wifi/ethernet interfaces?
3
0
995
Jun ’22
Big Sur and later: when user interaction is required to modify trust settings of certificates as root?
On Big Sur, user interaction is sometimes necessary to modify trust settings of a certificate (see https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-release-notes#Security). This means that sometimes, app calling SecTrustSettingsSetTrustSettings blocks until user enters password even if it is running as root (or fails with "The authorization was denied since no user interaction was possible" if it is run from a context where user session is not available). But it seems that for vast majority of machines, entering the password is not necessary (for other voice confirming this, please see https://developer.apple.com/forums/thread/671582). Please is there any way how to check whether user interaction will be required for this operation on the machine in advance? Be it via api or some characteristics of the system? This would lead to better user experience of our app...
1
0
918
Jul ’21
Adding EndpointSecurity client entitlement to an app
I am trying to write non-system extension EndpointSecurity client. As recommended by “eskimo”, I have made an app in xcode, gutting it so that main runs the ES client.However I do not know how to add EndpointSecurity entitlement. In December we have received a mail from Apple notifying us that we can now use this entitlement. In the attached email, there was a description how to add the entitlement to provisioning profile: “When you create a Development or Distribution provisioning profile for your Bundle ID, you'll be prompted to select additional entitlements. Click Profiles on the sidebar, then click the Add button in the upper-left corner. Choose a provisioning profile type and follow the prompts until you see ‘Additional Entitlements.’ Select the Endpoint entitlement from the dropdown to include the Endpoint Security entitlements in your new profile. Click Continue to finish the process.” This seems out of date; there does not seem to be a way how to add entitlements when generating provisioning profile. I can see System Extension and Network Extension entitlements when setting up app id, however even there the EndpointSecurity entitlement is not present.Surprisingly, I am able to sign the app with a provisioning profile that does not contain ES client entitlement (I have thought it would fail, as the profile is supposed to be a whitelist of entitlements), and the app itself seems to have the entitlement:$ codesign -d --entitlements :- com.whatever.test.app/contains key com.apple.developer.endpoint-security.client set as truehowever trying to run this unsurprisingly fails (i guess now the profile is applied?):taskgated-helper: com.whatever.test: Unsatisfied entitlements: com.apple.developer.endpoint-security.clienttaskgated-helper: Disallowing: com.whatever.testamfid: /path/to/com.whatever.test.app/Contents/MacOS/com.whatever.test signature not valid: -67671kernel: proc 73552: load code signature error 4 for file "com.whatever.test"Please anyone knows what should be done to add the Endpoint Security client entitlement to an app?
5
0
3.3k
Feb ’20
Network.framework: Receiving UDP response from other UDP port
Some network protocols allow response to UDP request to arrive from other server's port than the one request is sent to. However these responses are ignored (ICPM message is sent back) if Network.framework is used. Is there a way how to actually receive such packets? I have tried to create a listener for the connection, or to start a listener with the ip+port of the local address of the connection used to send the original request, in a hope that I would get these via new connection objects, but these did not work...
1
0
479
Aug ’20
EndpointSecurity: es_new_client freezes all operations until other clients decide pending messages?
I have 2 EndpointSecurity apps. App1 is doing the heavy lifting and processes multiple events(ES_EVENT_TYPE_AUTH_EXEC, ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_RENAME, ES_EVENT_TYPE_AUTH_UNLINK, ES_EVENT_TYPE_NOTIFY_CLOSE, ES_EVENT_TYPE_NOTIFY_CREATE ). App2 is responsible for checking whether Full Disk Access is granted or not: int main(int argc, char * argv[]) { 		es_client_t *client; auto res = es_new_client(&client, ^(es_client_t *clt, const es_message_t *msg) { }); 		_exit(res == ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED ? 0 : 1); } (please note that none of the apps is a System Extension). Sometimes when App1 is runing and App2 executes, the system hangs. After few days of investigation, it seems that starting a new es client (even without registering any messages) causes the system to block all operations until all the currently pending auth requests from other clients are answered. This makes it very hard to reason about the application. It also requires to basically offload everything to background threads and do every FileSystem related operation with a timer (even operations on NON_BLOCKING filedescriptors) so we can guarantee to answer in time; not doing so leads to endpointsecurityd eventually killing all endpoint security apps when it detects a stuck app. I want to note that typically for me it is necessary to run the hepler app in a loop to induce this; there may be some other race condition happening at the same time. But originally a single execution of this seemed to be enough to cause the hang in rare circumstances. Please is this an intended feature? And if yes, is there a way how to detect such an event ("you have to answer all pending requests immediately while basically not being able to do anything") from the main app? Because right now it seems that starting a new endpoint security client may lead to temporary hang of the system…
0
0
395
Jul ’20
Transparent Proxy and issues when NEHostEndpoint is hostname
Greetings, I have encountered issues with Safari and transparent proxy (NEAppProxyTCPFlow). Safari and other apps like to invoke NEAppProxyProvider's handleNewFlow with flow's requested endpoint being hostname rather than ipv4/6 ip address. The issue is that I have not been able to find a way how to set the actual remote IP address for the flow; it only seems that networkInterface can be used to set the actual network interface. And when this is not done, stuff starts breaking. First, lsof shows the remote address as Safari		89690					username	 25u		 IPv4 0x143206f1f81963c1				0t0								 TCP 1.2.3.4:61127->*:https (CLOSED) please note the wrong state(closed) and star instead of remote address. From syslog it seems that Safari considers the remote ip address as 0.0.0.0:443. The problem is that this seems to break safari internally; if http2 protocol is used, it likes to use random connections to send subsequent requests (eg. the connection to youtube.com is used to send also requests for youtube videos to servers like r6---sn-2gb7sn7z.googlevideo.com). This leads to a lot of 421 HTTP responses and broken youtube etc. Please can I somehow set the remote ip address of the flow?
4
0
1.5k
Jul ’20
Changing text of allow dialog triggered by NETransparentProxyManager
When trying to do transparent proxying via NETransparentProxyManager, the dialog asking to allow/deny the functionality has following text:"My Network Extension" Would Like to Add VPN Configurationand small text:All network activity on this Mac may be filtered or monitored when using VPNThis text is missleading and confusing, as it has nothing to do with VPN, and most of the people do not even know what VPN is. I guess this is the relic of the relevant mechanism originally being developed for VPN? Is it possible to change this text to something more sane? Either allow us to customize this (I was not able to find if it is possible in the documentation but I may have missed it) or change it to something more suited for transparent proxying, eg. "My Nework Extension" Would Like to View And/Or Modify Network Trafficand small text:All network activity on this Mac may be filtered or monitored.
2
0
590
Jun ’20
Stopping TransparentProxy Network Extension
Hello, we need a system extension which will provide both AppProxy and DnsProxy functionality on demand for daemons started by launchd.We have written a fake application that has application structure for signing purposes but behaves as a command line tool with commands: load sext, unload sext, enable/disable App proxy, enable/disable DNS proxy. It looks like it works. We have verified that even when the sext process is killed, in case DNS proxy is enabled, after sext gets restarted, the dns proxy functionality is restarted. Also enabling and disabling DNS Proxy via NEDNSProxyManager.shared().isEnabled correctly triggers NEDNSProxyProvider’s startProxy/stopProxy methods.But App Proxy does not behave well. It seems that change of NETransparentProxyManager’s isEnabled to false does not stop running AppProxyProviders (stopProxy method is never called). Even worse, next enabling of NETransparentProxyManager followed by connection.startVPNTunnel() creates another instance of AppProxyProvider (even when it does not intercept any traffic at the moment of disabling it). Calling stopVpnTunnel() fails, probably since we use the command app as a command, so it exits after starting the tunnel and as such does not have the context to stop it in next execution.What is the correct way how to stop a running Transparent Proxy sext? Or how should the case of sext having multiple running AppProxyProvider instances be handled?
0
0
416
Jun ’20
Uninstallation of System Extension always requires password?
Hello, our application can not be uninstalled by dragging it into trash, so we have a script that uninstalls it. But either systemextensionsctl and the OSSystemExtensionRequest.deactivationRequest api require this to be run as a user and triggers a dialog for user to enter his password. This is unfortunate, as it will mean the user will have to enter password twice during unregistration flow (once to remove system extension, once for our script to gain root to remove everything else). Is it possible to somehow work around this? Eg. add some entitlement to the app that sends the deactivation request for it to be able to remove it without a dialog in case it is already being run as root?
1
0
622
Jun ’20