Posts

Post not yet marked as solved
10 Replies
We also have had hundreds of customer complaints about total loss of networking while on our VPN - only for iOS 14. We use BSD Sockets in the packet tunnel provider for UDP - as a DNS proxy of sorts. Prior to iOS 14, everything works fine. As soon as users updated to 14, many have no networking whatsoever. We're finding that recv is never called. I've tried adding the local privacy permission to no avail. Do we need the multicast entitlement?
Post marked as solved
7 Replies
Replied In iOS 14 UDP
We also have this issue exclusive to iOS 14. Our app uses a PacketTunnelProvider VPN extension. It essentially acts as a "local tunnel" to listen for DNS queries on the interface, block adult content, and write back the packets to the interface via UDP packets. Our app has worked fantastically until users updated to iOS 14. We are totally unable to find a solution to this issue and are starting to believe the issue may not with us but rather with iOS.
Post not yet marked as solved
1 Replies
I second this problem. To obtain default browser entitlement, we need to only use "NSPhotoLibraryAddUsageDescription" to increase privacy. However, when saving an image, the app crashes.
Post not yet marked as solved
3 Replies
To clarify,if we use the new https://developer.apple.com/documentation/networkextension/nednssettingsmanager , does it enforce such DoH or DoT across the entire device? If so, that means WebKit processes would have such enforced DNS. Thanks, Logan
Post marked as solved
18 Replies
Makes sense.Swift should be autoreleasing the packet on its own then.Thank you!
Post marked as solved
18 Replies
Thank you Quinn!Yes; that was a simple mistake on my part...Ah ok, metadata is probably expected to be nil for us, then.Now that the former is working, I'm having trobule with delayCurrentPacket.The docs indicate we should return a .delay verdict after calling delayCurrentPacket. Once delayed, we can call allow( <packet> ) with the previousy delayed packet or choose to drop the packet by releasing it.What does "releasing" mean in this context? Because we've already returned the .delay verdict, we cannot subsequently return a followup verdict of .drop from our handler any longer because it has already returned. It seems we should have a function called drop(<packet>) similarly to our allow(<packet>) function, where we can drop the packet after we've returned the .delay verdict.While it is possible we can simply never call allow(<packet>) and the connection may eventually time out and drop on its own, this is not ideal for a great UX.Is it possible my async nature on this code is incorrect? Should I instead be making these decisions sync to avoid the need to use delay at all?I'm worried that if the blocking operation is holding up other packets waiting to enter the handler, we may slow other traffic until the completion of the blocking operation before it. Though if the extension is running each packet through the packet handler on its own private thread/queue, this blocking may not be a problem.Do you have suggestions on either of these options? override func startFilter(completionHandler: @escaping (Error?) -> Void) { os_log( #function ) packetHandler = { context, interface, direction, packetBytes, packetLength in guard direction == .outbound else { return .allow } let data = Data( bytes: packetBytes, count: packetLength ) var hostname: String var `protocol` = Protocol.ssl // Assume it's HTTPS // hostname = packetUtilWrapper.getHostForPossibleHTTPSRequest( data ) if hostname.isEmpty // Maybe HTTP? { hostname = packetUtilWrapper.getHostForPossibleHTTPRequest( data ) `protocol` = .http } // Don't spam logs with anything but HTTP/HTTPS // if !hostname.isEmpty { let packet = self.delayCurrentPacket( context ) let urlString = `protocol`.rawValue.appending( "://" ).appending( hostname ) let postData = Data( "{\"url\":\"\( urlString )\"}".utf8 ) var request = URLRequest( url: URL( string: "http://myLocalAPI.json")! ) request.httpMethod = "POST" request.httpBody = postData FilterPacketProvider.queue.async { URLSession.shared.dataTask( with: request ) { data, response, error in guard let data = data, let json = try? JSONSerialization.jsonObject( with: data, options: [] ) as? [String: Any] else { self.allow( packet ) FilterPacketProvider.log( (`protocol`, "Bad response: ".appending( hostname ) ) ) return } let results = json["result"] as! [String: Any] let records = results["records"] as! [String: Any] let action = records["action"] as! String if action == "allow" { self.allow( packet ) } else { // TODO: How we do drop the packet now? // } FilterPacketProvider.log( (`protocol`, "\( action ): ".appending( hostname ) ) ) }.resume() } return .delay } return .allow }Thanks again!
Post marked as solved
18 Replies
Additionally, the NEPacket metadata property is nil...any documentation on metadata?
Post marked as solved
18 Replies
Hey,I'm having trouble using the context in my app as well.I'm trying to delay a packet with `delayCurrentPacket` but Xcode is having trouble with this compilation, acting as if the context in my closure does not exist. Here's my code: private var _packetHandler: NEFilterPacketHandler? = { context, interface, direction, packetBytes, packetLength in let data = Data( bytes: packetBytes, count: packetLength ) var hostname: String var `protocol` = Protocol.ssl // Assume it's HTTPS // hostname = packetUtilWrapper.getHostForPossibleHTTPSRequest( data ) if hostname.isEmpty // Maybe HTTP? { hostname = packetUtilWrapper.getHostForPossibleHTTPRequest( data ) `protocol` = .http } // Don't spam logs with anything but HTTP/HTTPS // if !hostname.isEmpty { log( (`protocol`, hostname) ) let packet = delayCurrentPacket( context ) return .delay } return .allow }The error is: 'NEFilterPacketContext' is not convertible to 'FilterPacketProvider'
Post marked as solved
8 Replies
Hi Quinn,Thanks for the helpful info here. We also need the PID from the NEFilterFlow.Unfortuantely the above solution is giving us problems:audit_token_to_pidHere is our full code using Swift.extension NEFilterFlow { func pid() -> pid_t { let array8 = Array( self.sourceAppAuditToken! ) let array32 = array8.map { UInt32($0) } let audit_token = audit_token_t(val: (array32[0], array32[1], array32[2], array32[3], array32[4], array32[5], array32[6], array32[7])) return audit_token_to_pid( audit_token ) } }I'm wondering if our conversion from Data to audit_token_t is the culprit.The resulting PID is a 0 or 1, regardless of input.Anything stand out?Thanks!