Post

Replies

Boosts

Views

Activity

Infinite crashes caused by on-demand
Hi There, If some code in the packet tunnel provider caused a crash, it seems like on-demand will bring back the tunnel and then the tunnel crashes again. This is an infinite loop and on iOS, it's not very obvious for the users to understand what's going on there. Is there a way to programmatically disable on-demand feature within packet tunnel provide?
3
0
708
Dec ’22
NEPacketTunnelProvider Cannot Be Started
Hi There, I am using NETunnelProviderManager to configure and start a NEPacketTunnelProvider on macOS. Most of time, it works just fine, however, under some edge cases, NEPacketTunnelProvider will not start and NEVPNConnectionStatus changes directly from NEVPNStatusConnecting to NEVPNStatusDisconnected from the NEVPNStatusDidChangeNotification I received. What is the best way to handle this edge case? It seems like normally retry the startVPNTunnelWithOptions:andReturnError: shortly after would just fix the issue somehow. Core logic to start the NEPacketTunnelProvider ... [manager loadFromPreferencesWithCompletionHandler:^(NSError *loadError) { [self observeConnection:manager.connection]; NSError *error; BOOL success = [manager.connection startVPNTunnelWithOptions:options andReturnError:&error]; NSLog(@"start tunnel succeeded: %d error: %@", success, error); }]; ... - (void)vpnConnectionDidChange:(NSNotification *)notification { NEVPNConnection *connection = (NEVPNConnection *)notification.object; NSLog(@"connection.status: %ld", (long)connection.status); } NEPacketTunnelProvider code to verify the provider is started @implementation MyMacPacketTunnelProvider { - (instancetype)init { NSLog(@"tunnel init"); ... } - (void)startTunnelWithOptions:(NSDictionary<NSString *, id> *)options completionHandler:(void (^)(NSError *_Nullable error))completionHandler { NSLog(@"startTunnelWithOptions called"); Logs when hitting edge case: start tunnel succeeded: 1, andReturnError: (null) connection.status: 2 connection.status: 2 connection.status: 1 connection.status: 1 connection.status: 1 Logs happy path: start tunnel succeeded: 1, andReturnError: (null) connection.status: 2 connection.status: 2 tunnel init startTunnelWithOptions called connection.status: 3 connection.status: 3
10
0
1.5k
Sep ’22
SKPayment.applicationUsername is nil even if we assign a UUID string to it
According to the documentation and WWDC sessions, as long as we create a SKPayment with applicationUsername to be a UUID string. This value should be persistent when the transactions are updated. However, when we tested it with XCode 14 and iOS 15 device, when we receive the SKPaymentTransaction for the auto renewals. The SKPaymentTransaction.payment.applicationUsername is nil. Is this expected? Or it's a feature that will come in the future Xcode releases?
3
0
1.7k
Jun ’22
What's the best way to launch containing app on macOS from the Network Extension
Hi There, We have a VPN application built on top of the Packet Tunnel Provider. We are seeing an issue that once our containing application crashed, the packet tunnel provider keeps running. We could detect the crash from the tunnel, but there is no way for us to stop the VPN because on-demand will bring back VPN all the time. Since there is no way to disable on-demand rule within the packet tunnel provider, is it possible that we can programmatically launch the crash application from the packet tunnel provider? Something like iOS's silent push notification could work too since all we need is to disable on-demand rule from the application and stop VPN.
3
0
696
May ’22
Unable to launch Network Extension On Mac
Hi There, I have read every previous post in the forum and I still cannot figure out why my network extension cannot be launch with error: Error Domain=OSSystemExtensionErrorDomain Code=4 "Extension not found in App bundle: perhaps App is not validly structured" UserInfo={NSLocalizedDescription=Extension not found in App bundle: perhaps App is not validly structured} Things I have tried: I verified the network extension is indeed bundled into the final packet by unzip the the project and look into the package contents: I did tried multiple versions of different entitlements and Info.plist for both the app and extension and none of them worked. I did disable SIP on my Mac. Here is my entitlements for the extension: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>keychain-access-groups</key> <array> <string>${TEAM_ID}.group.com.test.vpn</string> </array> <key>com.apple.security.application-groups</key> <array> <string>${TEAM_ID}.group.com.test.vpn</string> </array> <key>com.apple.developer.networking.networkextension</key> <array> <string>packet-tunnel-provider-systemextension</string> </array> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.files.user-selected.read-write</key> <true/> <key>com.apple.security.network.client</key> <true/> <key>com.apple.security.network.server</key> <true/> <key>com.apple.application-identifier</key> <string>${TEAM_ID}.com.test.vpn.NetworkExtension</string> </dict> </plist> Here is the info.plist for the extension: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>${CF_BUNDLE_NAME}</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>${VERSIONINFO_SHORT}</string> <key>CFBundleVersion</key> <string>${VERSIONINFO_LONG}</string> <key>CFBundleDisplayName</key> <string>${PRODUCT_NAME}</string> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>${AUTHENTICATION_SCHEME}</string> </array> </dict> </array> <key>APPClientId</key> <string>${APP_CLIENT_ID}</string> <key>NetworkExtension</key> <dict> <key>NEMachServiceName</key> <string>${TEAM_ID}.com.test.vpn.NetworkExtension</string> <key>NEProviderClasses</key> <dict> <key>com.apple.networkextension.packet-tunnel</key> <string>VPNPacketTunnelProvider</string> </dict> <key>NSSystemExtensionUsageDescription</key> <string></string> </dict> </dict> </plist> Here is the entitlements for the app: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.files.user-selected.read-write</key> <true/> <key>com.apple.security.network.client</key> <true/> <key>com.apple.security.network.server</key> <true/> <key>com.apple.developer.networking.networkextension</key> <array> <string>packet-tunnel-provider-systemextension</string> </array> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.application-groups</key> <array> <string>${TEAM_ID}.group.com.test.vpn</string> </array> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.application-identifier</key> <string>${TEAM_ID}.com.test.vpn</string> </dict> </plist> Any thing did I misconfigure or any steps did I miss?
8
0
3.8k
Feb ’22
How do I use initWithUpgradeForSession safely?
It's a little bit unclear to be how to use initWithUpgradeForSession safely. Imagine we have a class like this: @implementation PPNUDPSessionPipeWrapper { NWUDPSession *_session; NWUDPSession *_upgradedSession; } - (void) startReadingPackets() { [_session setReadHandler:^(NSArray<NSData *> *datagrams, NSError *error) { // process datagrams [_session writeMultipleDatagrams:datagrams completionHandler:^(NSError *error) { // Handle error }]; }]; -(void)didHaveBetterPath { _upgradedSession = [[NWUDPSession alloc] initWithUpgradeForSession:_session]; [self waitForSessionToBeReady: _upgradedSession]; // How can I swap `_session` with the // `_upgradedSession` safely? Will iOS guarantee the // readHandler on `_session` will not be called any // more? }
1
0
503
Nov ’21
Disable on-demand VPN
Hi There, We want to disable on-demand feature when the packet tunnel provider is stopped, so we implemented the logic like this: - (void)stopTunnelWithReason:(NEProviderStopReason)reason completionHandler:(void (^)(void))completionHandler { [NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^( NSArray *managers, NSError *error) { NETunnelProviderManager *manager = managers.firstObject; [manager setOnDemandEnabled:NO]; [manager saveToPreferencesWithCompletionHandler: ^(NSError *saveError) { completionHandler(); }]; }]; } However, when the user turns off VPN from the Settings app, the completion handler in the loadAllFromPreferencesWithCompletionHandler is not executed. Do you have an idea why is that?
3
0
742
Aug ’21
NWUDPSessionState Stuck at Preparing After Cancelling Session.
Hi There, We found an issue that caused NWUDPSession stuck at NWUDPSessionStatePreparing forever: When the user switches from Wifi to cellular network, we will reconnect them using: [self.session cancel]; NEPacketTunnelNetworkSettings* networkSettings = // new settings [self updateTunnelNetworkSettings:networkSettings]; self.session = [self createUDPSessionToEndpoint:hostEndpoint fromEndpoint:nil]; [self waitForSessionToBeReadyUsingKVO]; // This line never executed while self.session.state stuck // at NWUDPSessionStatePreparing Any ideas on this issue?
3
0
882
Aug ’21
NWUDPSession only works when there is a sim card installed
Hi There, I built a VPN using NEPacketTunnelProvider - https://developer.apple.com/documentation/networkextension/nepackettunnelprovider?language=objc and created the UDP session using createUDPSessionToEndpoint:fromEndpoint:(https://developer.apple.com/documentation/networkextension/neprovider/1406004-createudpsessiontoendpoint?language=objc). When I tested on an iPhone with sim card installed, everything works fine with or without a wifi connected. However, when I removed the sim card from the iPhone, even if my wifi is still connected, I can no longer connect to the backend. And the session above falls into the failed state every time. I disabled the VPN, my phone can open any website as normal. I tried to reboot my iPhone multiple times, delete the app and reinstall multiple times, no luck. As soon as I inserted my sim card into the device, the app starts working fine again.
3
0
737
May ’21
How can I pause reading packets from NEUDPSession
Hi There, NWUDPSession has a setReadHandler:maxDatagrams: method to register a callback for reading packets. I am wondering how can I pause this handler not to be called for a short period(pause it for a while)? I can think of few options, but all of them seem to be bad. Cancel the session when paused, and create a new one when resumed. (void)stopReadingPackets { [self.session cancel]; } (void)resume { self.session = ... [self.session setReadHandler:^(NSArrayNSData** datagrams, NSError* error) { // Handle packets here. } maxDatagrams:1]; } 2. Block the handler to be executed. For example: [self.session setReadHandler:^(NSArrayNSData** datagrams, NSError* error) { while (self.paused) {} // Handle datagrams here. } maxDatagrams:1]; Thanks.
3
0
726
Mar ’21
NEPacketTunnelFlow.readPackets not working
Hi There, I have setup a PacketTunnelProvider as this: class PacketTunnelProvider: NEPacketTunnelProvider {   override func startTunnel(    options: [String: NSObject]?, completionHandler: @escaping (Error?) - Void   ) {    NSLog("Tunnel started")    remoteEndpoint = NWHostEndpoint(hostname: "192.168.0.27", port: "62165")    readPackets()  }   override func stopTunnel(    with reason: NEProviderStopReason, completionHandler: @escaping () - Void   ) {    NSLog("Tunnel Stopped")   completionHandler()  } } extension PacketTunnelProvider {  private func readPackets() {    NSLog("readPackets called")     self?.packetFlow.readPackets { (_, _) in      NSLog("Did read packets")     }   } } After running the extension on a device using XCode, I can see completion handler in the NEPacketTunnelFlow.readPackets is never being called according to logs: default 16:00:07.447406-0800 VPNTestAppExtension Tunnel started default 16:00:07.466064-0800 VPNTestAppExtension Did finish setting network: nil default 16:00:07.466629-0800 VPNTestAppExtension readPackets called Did I miss anything here? To test, I have an app keep sending a UDP packet to a UDP server, I am expecting readPackets method should capture these UDP packets after the tunnel is started.
5
0
1.8k
Feb ’21