Hello,
For several versions, we have had a NetworkExtension registered to "FilterDataProvider" for content filtering reasons, with no issues about performance in 10Gigabit networks.
In our latest version, we added registration to "FilterPacketProvider" for packet filtering purposes, and from that moment, we have observed that outgoing bandwidth dramatically decreases by 90% (from 883 MB/s to 140MB/s), simply due to being registered to "FilterPacketProvider," without any processing by us, just only registering and returning ALLOW:
class FilterPacketProvider: {
override func startFilter(completionHandler: @escaping (Error?) -> Void) {
self.packetHandler = {(_pContext: NEFilterPacketContext, _pIface: OS_nw_interface, _pDirection: NETrafficDirection, _pRawData: UnsafeRawPointer, _pRawDataLength: Int) -> NEFilterPacketProvider.Verdict in
return self.handleNewPacket(context: _pContext, interface: _pIface, direction: _pDirection, rawData: _pRawData, rawDataLength: _pRawDataLength)
}
}}
func handleNewPacket(context: NEFilterPacketContext, interface: OS_nw_interface, direction: NETrafficDirection, rawData: UnsafeRawPointer, rawDataLength: Int) -> NEFilterPacketProvider.Verdict
{
return .allow
}
The most curious thing is that this behaviour only happens with outgoing traffic, while incoming traffic does not experience any performance penalty.
Reviewing similar cases, we found a similar post here: https://developer.apple.com/forums/thread/741965
So, our questions are:
1. Could we be doing something wrong when registering to NEFilterPacketProvider?
2. Is there still any known performance bug with outgoing traffic in NEFilterPacketProvider as I read in the post I found and attached?
3. If this bug is confirmed, is there any estimated date for its correction?
Best regards,
Asier Gil.
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
This doesn't particularly surprise me, but I am curious about it, and whether we can change it: our TPP won't start if the only IP address available is in 169.254.0.0/16. I can see (from our logs) that the preferences are loaded & saved, and the extension is loaded, but until it gets a real address, the startProxy method is not invoked.
I'm working with content filters on OS X and encountered an issue where the handleNewFlow function is not called unless I explicitly invoke completionHandler(nil) in the startFilter method. This is perplexing because I expected handleNewFlow to be called automatically when new traffic flows are detected.
Here's an example of my startFilter function without the completionHandler:
override func startFilter(completionHandler: @escaping (Error?) -> Void) {
os_log("Start filter called")
// Create a network rule that matches all traffic
let allTrafficNetworkRule = NENetworkRule(remoteNetwork: nil,
remotePrefix: 0,
localNetwork: nil,
localPrefix: 0,
protocol: .any,
direction: .outbound)
// Create a filter rule that allows all traffic
let allowAllFilterRule = NEFilterRule(networkRule: allTrafficNetworkRule, action: .allow)
// Set filter settings with the default action to allow all traffic
let filterSettings = NEFilterSettings(rules: [allowAllFilterRule], defaultAction: .allow)
// If I include this it will work fine, but TCP sessions will be reset:
//completionHandler(nil)
}
Question:
Why, when I include completionHandler(nil) in the startFilter method, do all TCP sessions on my computer get reset? Is there a way to around this? My ideal state would be to get handleNewFlow to execute, but not without resetting sessions on my machine.
When I turn on the PAC proxy configuration on my computer, the URL request part in the developed app will overflow the memory, but it will not happen if I turn off PAC
We are working on an app which includes a packet tunnel provider extension. The packet tunnel provider works by relaying traffic from a device on the same Wi-Fi network to a remote server via the iPhone's cell socket.
As such, it is important for the VPN (and the Wi-Fi connection) to remain running while the phone is locked. We have however noticed that when we lock the phone, the VPN stops running a few seconds later and will remain inactive until the phone's screen wakes up. We have set disconnectOnSleep to false but the issue still remains.
Is there a way to keep the VPN alive while the phone is locked?
Hello, I recently encountered a tricky problem:
+ (BOOL)registerWithOptions:(nullable NSDictionary<NSString *,NSObject *> *)options
queue:(dispatch_queue_t)queue
handler:(NEHotspotHelperHandler)handler
NEHotspotHelper handler make our app live in the background for a long time. And the running time of the app in the background far exceeds the running time of the foreground.
Our application reported the content of the metric payload, and the statistics data of some users are as follows:
ForegroundTime is 0 ,BackgroundTime: almost 3 hours, audiotime is 0 LocationTime is 0
I would like to ask about NEHotspotHelper details: How NEHotspotHelper make the app live in the background. How to limit the App background live time triggered by hotspot.
I have a VPN configuration that starts a PacketTunnelProvider extension. In there I set the DoH server url and start / stop everything pretty straight forward.
I want to exclude certain domains, such as e.g. "google.com" or "apple-dns.net" to lower my traffic on the DoH server.
I tried a couple of variations of onDemand rules yet they all don't work for me. Is there a way how I can only route DNS requests towards my DoH server for all domains except custom defined domains?
Examples I've tried thus far
I spare the boilerplate code for creating the NETunnelProviderManager before and setting the rules + isOnDemandEnabled flag for the following examples except the first one:
1
// create the NETunnelProviderManager
let evaluationRule = NEOnDemandRuleEvaluateConnection()
let ignoreDomainRule = NEEvaluateConnectionRule(matchDomains: ["apple.com"], andAction: neverConnect)
evaluationRule.connectionRules = [ignoreDomainRule]
manager.onDemandRules = evaluationRule
manager.isOnDemandEnabled = true
2
let ignoreDomainRule = NEEvaluateConnectionRule(matchDomains: ["apple.com"], andAction: neverConnect)
[ignoreDomainRule, NEOnDemandRuleConnect()]
3
let ignoreDomainRule = NEEvaluateConnectionRule(matchDomains: ["apple.com"], andAction: connectIfNeeded)
ignoreDomainRule.useDNSServers = ["8.8.8.8"]
[ignoreDomainRule, NEOnDemandRuleConnect()]
// or [ignoreDomainRule]
4
let disconnectRule = NEOnDemandRuleDisconnect()
disconnectRule.dnsSearchDomainMatch = ["apple.com"]
[disconnectRule, NEOnDemandRuleConnect()]
5
let evaluationRule = NEOnDemandRuleEvaluateConnection()
let ignoreDomainRule = NEEvaluateConnectionRule(matchDomains: ["apple.com"], andAction: neverConnect)
let connectRule = NEEvaluateConnectionRule(matchDomains: [""], andAction: connectIfNeeded)
evaluationRule.connectionRules = [connectRule]
We are using an NEPacketTunnel provider for our custom VPN solution, and doing so we are setting NEPacketTunnelNetworkSettings with setting IPv4 and IPv6 default routes. We are then setting DNS
networkSettings.dnsSettings?.matchDomains = [""]
However, apps like FaceTime still go around the VPN.
Once you set setTunnelNetworkSettings is there no way to ask the system to return what the current saved configuration?
Testing, Ive also tried turning off IPv6 on my home network and cell data to force all traffic to my IPv4 default routes.
Ive seen FaceTime work on one session, relaunch the app and never again.
Note: IncludeAllNetworks does work, but comes with a lot of downsides too. Our goal is to securely and redundantly help with video calls , streaming apps etc.
I have implemented a NEPacketTunnelProvider in my app, which sends local notifications to the user when the server is down. While the notifications are displayed successfully, I encountered an issue when changing the system locale settings on iOS. Specifically, the notifications still display in the previous locale, even after the system locale has been changed. The locale of the notifications only updates if I restart the device.
I am currently using Locale.current for setting the locale in my notifications. I have also tried using Locale.preferredLanguages, but it seems that the locale does not properly update in real-time.
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 !
Currently, I've been able to completely block requests using a Content Filter Network extension.
Right now, I'm looking to build a Network Link Conditioner that applies to an individual app only.
The Network Link Conditioner allows selecting profiles with specific settings:
Downlink
Packages Dropped
Bandwidth
Delay
Uplink
Bandwidth
Packets dropped
Delay
My question
Is it possible to reproduce this behavior using a Network Extension and if so, which type of network extension should I use?
Since we've had a lot of problems with XPC (bad design on my part, I'm sure), I tried changing the data communications between the TPP and the userland proxy to use sockets -- in this case (I've so many, many cases), I am trying to do an http proxy (so the TPP connects to, say, port 12345, sends
CONNECT ${host}:${port} HTTP/1.0
X-Proxy-Host: ${host}:${port}
It then reads a response, looking for a 200.
So that part works -- once I added the networking client entitlement, I could connect and write that and read the response. Now we are cooking with gas, right?
The application doing the connection (eg, curl) then sends the normal HTTP request, the TPP gets it, it writes it to the socket it created, the write succeeds (that is, returns the number of bytes in the request), and...
it doesn't show up on the interface. (Using tcpdump -i lo0 -s 0 -vvvvvvvvvvvvvvvvvvv -A port 12345.) Since it doesn't show up on the interface, the user-land proxy doesn't get it, and things are very confused for everyone.
If the connect() failed, I'd say, ah yes, sandboxed to heck and back, even with the entitlement can't do it. Or if the first write() or read() failed. But they don't fail, and the first round works. If the second write() failed, I could see that.
But it both succeeds and doesn't succeed, and quantum confuses the heck out of me.
I use NETransparentProxyProvider transparent proxy the outbound data ports 80 and 443, at the same time using CocoaAsyncSocket third party open source libraries for data forwarding
At first, handleNewFlow will be called normally, but after running for a period of time, handleNewFlow will not be called again, and the system will not be able to access the Internet unless the vpn is disabled
By checking the terminal app log, I found that handleNewFlow will not be called again when the following information is displayed.
# Domain=NEAppProxyFlowErrorDomain Code=1 "The operation could not be completed because the flow is not connected" UserInfo={NSLocalizedDescription=The operation could not be completed because the flow is not connected" #
Hello,
I am working on a macOS VPN app using Network Extension's packet tunnel capability.
When the container app (referred to as "App" below) and the network extension plugin (referred to as "NE" below) are signed with my development certificate, everything works perfectly.
However, when they are signed with a Developer ID certificate, the network extension refuses to activate.
Here are the details:
The App has sandbox set to off, but the NE has sandbox set to on.
I managed to archive and notarize both Developer ID signed App and NE.
The Debug version and Release version don't use the same App ID or App Group ID to make sure there is no interference.
I am aware that the NE entitlement value changes if signed by Developer ID. I followed the instructions and used packet-tunnel-provider-systemextension instead of packet-tunnel-provider.
I tested adding System Extension capability into the App, but it made no difference.
The activate tunnel function returns NEVPNError.Code.configurationInvalid, but I don't think the configuration is invalid. The same configuration works with a development profile.
In the system console, I observed the following log messages:
Looking for an extension with identifier {NE_BUNDLE_ID} and extension point com.apple.networkextension.packet-tunnel
Found 1 extension(s) with identifier {NE_BUNDLE_ID} and extension point com.apple.networkextension.packet-tunnel
Beginning extension request with extension {NE_BUNDLE_ID}
Assertion 395-24105-185921 (target:[xpcservice<{NE_BUNDLE_ID}([osservice<com.apple.neagent(512863558)>:24105:24105])(512863558)>:42188]) will be created as active
[0x12be187f0] activating connection: mach=false listener=false peer=false name={NE_BUNDLE_ID}.apple-extension-service
Entitlement com.apple.application-identifier={APP_GROUP_ID} is ignored because of invalid application signature or incorrect provisioning profile
Entitlement com.apple.security.application-groups=(
{APP_GROUP_ID}
) is ignored because of invalid application signature or incorrect provisioning profile
{APP NAME}[42130]/1#5 LF=0 copy_matching Error Domain=NSOSStatusErrorDomain Code=-34018 "Client has neither com.apple.application-identifier nor com.apple.security.application-groups nor keychain-access-groups entitlements" UserInfo={numberOfErrorsDeep=0, NSDescription=Client has neither com.apple.application-identifier nor com.apple.security.application-groups nor keychain-access-groups entitlements}
Any guidance or suggestions would be greatly appreciated.
Thank you!
I work on an app that includes a network extension. The app is essentially just to activate the extension, and the extension typically has long-running background sessions. Analyzing/monitoring metrics for the network extension is very important for us. However, in the Xcode Organizer screen, only the app itself is shown in the drop down menu - the associated network extension is not an option.
For Xcode Organizer screens like Termination metrics and Battery Usage metrics, does the app's background metrics include the network extension, or just the app itself? If just the app, is there any way to get these metrics for the network extension?
Hello,
We are facing what we believe is a compatibility issue with two networking APIs.
If the Network extension VPN configuration has includeAllNetworks flag enabled and the NEHotspotHelper is registered.
The user has internet connection but it is blocked, and there user will get internet back only after restarting the device.
VPN Configuration is as below while connecting to VPN,
{
localizedDescription = WLVPN WireGuard Configuration
enabled = YES
protocolConfiguration = {
serverAddress = <18-char-str>
passwordReference = {length = 20, bytes = 0x67656e70ed0d05c06b1b4896bf4fef2031e1a92d}
disconnectOnSleep = NO
includeAllNetworks = YES
excludeLocalNetworks = YES
excludeCellularServices = YES
excludeAPNs = YES
excludeDeviceCommunication = YES
enforceRoutes = NO
providerBundleIdentifier = com.wlvpn.ios.consumervpn.network-extension
}
onDemandEnabled = NO
onDemandRules = ()
}
After running the code shown below. Regardless if the VPN is connected or not, the user needs to restart his device to regain internet access.
private let neHelperQueue = DispatchQueue(label: "com.wlvpn.ios.consumervpn.hotspot",
attributes: DispatchQueue.Attributes.concurrent)
let options: [String: NSObject] = [kNEHotspotHelperOptionDisplayName : "" as NSObject]
let status = NEHotspotHelper.register(options: nil, queue: neHelperQueue) { cmd in
NSLog("Received command: \(cmd.commandType.rawValue)")
}
We need to use the includeAllNetworks flag to prevent the novel "Tunnel vision" vulnerability.
Can we please have some help getting confirmation if both functionalities are compatible or if there's a way to enable them at the same time?
2024-06-04 15:17:59.618853+0100 ProxyAgent[20233:29237510] [xpc.exceptions] <NSXPCConnection: 0x60000331cb40> connection from pid 20227 on anonymousListener or serviceListener: Exception caught during decoding of received selector newFlowWithIdentifier:to:type:metadata:socket:, dropping incoming message.
Exception: Exception while decoding argument 4 (#6 of invocation):
<NSInvocation: 0x600001778780>
return value: {v} void
target: {@} 0x0
selector: {:} null
argument 2: {@} 0x6000017787c0
argument 3: {@} 0x60000002d170
argument 4: {q} 1
argument 5: {@} 0x600001746600
argument 6: {@} 0x0
Exception: decodeObjectForKey: Object of class "NSFileHandle" returned nil from -initWithCoder: while being decoded for key <no key>
The extension is in Swift; the recipient is in ObjC (wheeeeee).
Based on the extension's logging, the FileHandle is not nil.
I am trying to pass a FileHandle based on a socketpair up to the user-land code. The sockets are created happily.
Any ideas what's going wrong here?
Hello, my goal is that when a request comes in with a specified ip using vpn, it sents to a localhost 8080 web server I created using gcdwebserver so I created NEPacketTunnelProvider and set some proxy server by using NEPacketTunnelProvider.
However, when I configure it as below, and connect to the ip in the browser, it shows web server result I want but I can't access the other site like apple.com.
let settings: NEPacketTunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "77.77.77.77")
settings.dnsSettings = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4"])
let proxySettings: NEProxySettings = NEProxySettings()
proxySettings.httpServer = NEProxyServer(
address: proxyHost,
port: proxyPort
)
proxySettings.httpsServer = NEProxyServer(
address: proxyHost,
port: proxyPort
)
proxySettings.autoProxyConfigurationEnabled = false
proxySettings.httpEnabled = true
proxySettings.httpsEnabled = true
proxySettings.excludeSimpleHostnames = true
settings.proxySettings = proxySettings
let ipv4Settings: NEIPv4Settings = NEIPv4Settings(
addresses: [settings.tunnelRemoteAddress],
subnetMasks: ["255.255.255.255"]
)
ipv4Settings.includedRoutes = [NEIPv4Route.default()]
settings.ipv4Settings = ipv4Settings
So, I set includeRoutes to only allow specified ip (77.77.77.77) as below, and the internet works fine, but access to the the ip is failed. It shows "connection failed" in the browser. Am I trying something wrong?
ipv4Settings.includedRoutes = [
NEIPv4Route(destinationAddress: "77.77.77.77", subnetMask: "255.255.255.255")
]
Hello
I am developing a react native VPN app. Also I'm new to Native Modules and Swift.
Depending on the related documents, I've tried to create IPSEC VPN and connect automatically from my application.
I've used the code below to create and connect IPSEC VPN but it is returning "No VPN Shared Secret was provided" error.
If I try to add VPN configuration from my Iphone with same parameters it's connecting successfully.
Feedback Ticket: FB13812251
Problem Statement: We are currently facing internet connectivity issue with our VPN application where we try to disconnect the VPN from the Packet Tunnel Network Extension using - (void)cancelTunnelWithError:(nullable NSError *)error. Which API to use to disconnect the VPN from Packet Tunnel as VPN app is not running such that device retains its internet connectivity as soon as VPN disconnects.
Configuration: We have configured PacketTunnelProvider with the following settings:
(NETunnelProviderManager *)tunnelProvider.protocolConfiguration.includeAllNetworks = YES;
(NETunnelProviderManager *)tunnelProvider.protocolConfiguration.excludeLocalNetworks = NO;
(NETunnelProviderManager *)tunnelProvider.protocolConfiguration.enforceRoutes = NO;
These settings are applied from the VPN app and allow us to successfully establish a VPN connection, with all traffic being routed through the tunnel as expected.We are setting above properties to address local net attack.
Issue we are facing:
However, we encounter a problem when we attempt to disconnect the VPN from. When we call the following method from PacketTunnel network extension:
(void)cancelTunnelWithError:(nullable NSError *)error
Upon calling this method, the VPN disconnects as expected, but the device loses all internet connectivity and is unable to access any resources. This is not the desired behavior.
Observation : Interestingly, when we call the following method from the app side. The VPN disconnects and the device retains its internet connectivity.
[enabledConfig.connection stopVPNTunnel];
We would like to achieve the same behavior when disconnecting the VPN from the Network Extension. So we are looking for an API that could be called from NE without causing any internet connectivity issue.
Any guidance on how to resolve this issue would be greatly appreciated.