In another post a while back, I found that if you hover the mouse over the spinning wheel in App Store while it is installing, you can see % installed...a great help to letting you know that the cpu being used by installd is making progress. It took almost 2 hrs to upgrade xcode 13.4.1 on a 2019 Macbook Pro with 32 gb.
Post
Replies
Boosts
Views
Activity
Thanks for responding Eskimo, but it turns out that they must not have allowed the app to save VPN configs. Without answering my question, they put the app back into review and approved it...so I guess they did answer it.
Anyway, thanks again for responding.
I should add that I have a pending question to App Review asking them if they allowed the app to save a VPN config since iOS asks for permission to do this when the app first does this after being installed. Denying this permission results in a "permission denied" error.
It sounds like you are using the NEPacketTunnelProvider classes, but I did just want to confirm that you are setting up your tunnel with the standard infrastructure for NEPacketTunnelNetworkSettings and NEPacketTunnelFlow etc, correct?
Correct. Stuff works in every other situation.
Also, one option I forgot to mention is the in-provider networking class that is similar to nw_connection_t, NWTCPConnection and NWUDPSession.
What is that option? Would it lead to me being able to get a socket descriptor?
And why doesn't connect() work in this single situation? I still say this is either a bug/regression, or there has to be some official statement in documentation somewhere that says that BSD sockets no longer work in network extensions running iOS 14+ when the device has a public ip address.
No, the tunnel is not failing. As I said when I started this thread:
The above chunk of C code is used to open TCP sockets on public and private servers on many platforms including Android and Mac OS. On iOS, it works if the device, an XR running 14.4.2, has an internal IP address when connecting to a public server. However, if the XR has a public IP address as it does when not connected to wifi, it fails with this in the log calling the same public server (or any public server) and errno = 1, Operation not permitted.
When the extension is started, the vpn becomes ready, and the above chunk of code sets up encryption with a server by first making a tcp connection to it and sending an encrypted packet through that connection that identifies the client and then sets up OpenSSL. Then control information and output from the vpn goes through that interface.
The problem is when the device is running iOS 14+ and has a public ip address, meaning either wifi is disabled or it's not connected to wifi, the connect() for the tcp connection fails with:
Sandbox: extension name(process #) deny(1) network-outbound*:port no
The deny(1) means errno == 1.
I know that this is not a problem with extensions on iOS 12.5.2, and I also made sure that connect() worked from the app. So the situation is that a basic connect() fails in network extensions on iOS 14+, but works outside of extensions on 14+ and works inside and outside of extensions on 12.5.2 (and I'll assume earlier versions).
I see no other reason for connect() to fail in this single situation unless it is a bug/regression or a lack of documentation that says that BSD sockets are no longer supported in network extensions running iOS 14+ on devices with public ip addresses, which makes C next to useless. Saying that NWConnection is "better equipped" doesn't explain why the industry standard connect() fails after working on earlier releases. And without an OpenSSL implementation for it, it is only "better equipped" for relatively simple stuff.
It would be acceptable if I could get a socket descriptor out of a NWConnection, but that is not possible. Since connect() works in the app, I might be able to make it work if the app can do background processing, but this is not an acceptable use of background processing from what I can tell.
I'll bet a case of beer that the above comments, especially the VPN one, are related to connect() failing in network extensions on ios 14.4. See https://developer.apple.com/forums/thread/678959.
Hi Matt,
Please excuse me for being blunt and not accepting "I do not think this is a case where there is a version that this functionality started/stopped working" as a legitimate answer. This is code. Of course there is a reason it doesn't work in network extensions, but does work properly in the app outside of the network extension. Code in the kernel spits out
Sandbox: extension name(5616) deny(1) network-outbound*:port no
and doesn't do that when the code runs in the app.
I have a rather large body of C code interfacing with OpenSSL, which uses sockets, that runs on most every Linux platform except network extensions on iOS versions = 14.0 because connect() fails. I want to confirm that you are telling me that because Linux C connect fails on PacketTunnelProvider extensions on = 14.0, and NWConnection (or nw_connection_t) appears to be the only way to open a TCP connection in this environment, and you can't get a socket descriptor out of a NWConnection, the whole body of C code has to be rewritten in Objective-C or Swift because NWConnection is "better equipped".
Considering most of Secure Transport is deprecated, what Apple frameworks can be used with NWConnection to do the heavy lifting OpenSSL does in this situation?
Or, what legitimate excuse could I use for an entitlement to allow background processing in the app: the code doesn't work as it should in the network extension?
Any possibility of finding out the version of iOS that this stopped working? As I said, I have a 5s maxed at 12.5.2 and an XR at 14.4.2. Since network extensions can't run on simulators, I don't have a way find the breaking point myself on iOS 13.
Hi Matt,
Since you popped the sim card into the phone and it worked is your connection going over cellular and outside of tunnel?
Yes it is. This is with wifi disabled and the phones having a public ip address. Same thing happens if wifi is enabled, but not connected to a network and the phones having a public ip address. The phone with 12.5.2 can make a TCP connection from the extension with the public ip address, and the phone with 14.4 fails with the above mentioned sandbox message, which comes from the kernel process.
Have you also tried this with NWConnection, or nw_connection_t to see if it makes a difference?
The app has to run on devices running ios 12. That said, I tried it on the XR with the sim and wifi disabled, and the NWConnection did get a 'ready' state update. So it looks like NWConnections can get out.
This leads me to ask if you can find out or what I have to do to find out:
1) When did this stop working? I have an XR running 14.4.2, and 5s maxed out at 12.5.2. Since I can't figure this out on the simulator, being a network extension, I have no way to find out the ios version to put in ifdefs.
2) Is this by design? It seems rather arbitrary to allow outside tcp connections on 14.4 only using NWConnection when the device has a public ip address.
Update.
I popped the sim card from the XR into a 5s running 12.5.2, and it worked like expected - the packet tunnel provider can open a tcp socket when it only has a public ip address.
Did something happen between 12.5.2 and 14.4.2 to break this or is it no longer permitted to open tcp sockets from packet tunnel providers from devices with public addresses?
I made request 765462285 for this.
Here is my provider startTunnel code
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) - Void) {
let newTunnel = ClientVpnTunnel()
newTunnel.delegate = self
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1")
settings.ipv4Settings = NEIPv4Settings(addresses: ["10.0.0.8"], subnetMasks: ["255.255.255.255"])
settings.ipv4Settings?.includedRoutes = [NEIPv4Route(destinationAddress: "10.0.0.1", subnetMask: "255.255.255.0")]
settings.ipv4Settings?.excludedRoutes = []
settings.dnsSettings = NEDNSSettings(servers: ["208.67.222.222", "208.67.220.220"])
settings.dnsSettings?.matchDomains = [""]
self.setTunnelNetworkSettings(settings) { error in
if let e = error {
NSLog("Settings error %@", e.localizedDescription)
} else {
simpleTunnelLog("Before newTunnel.startTunnel")
if let error = newTunnel.startTunnel(self) {
completionHandler(error as NSError)
}
else {
simpleTunnelLog("setTunnelNetworkSettings successful")
// Save the completion handler for when the tunnel is fully established.
self.pendingStartCompletion = completionHandler
self.tunnel = newTunnel
}
}
}
}
I see "setTunnelNetworkSettings successful" on the console, and using ios 14.4.1, I can see traffic like I said above from and to 10.0.0.8 and 10.0.0.1 in Wireshark on the server (10.0.0.1). I also have logging statements to the console at the top of the read and write handlers that match the hex I see going in and out of Wireshark on the server.
Yet I see nothing on ios 12.5.1.
Hi Matt,
As I said in my first post, I am using NWUDPSessionState.ready as a status to let the provider know when to read / write data on the connection:
I can see the NWUDPSession of the extension go from preparing to ready. When it gets to ready, I set the NWUDPSession read handler and have it start handling packets. However, in settings, the VPN is still connecting, and NWUDPSession.isViable is false.
And I wasn't asking if NEProxySettings should be able to handle either HTTP or HTTPS traffic, I was asking if it is *required* to handle http traffic. Also, there are no inconsistencies with isViable - it is always false.
Seeing that there are no answers for what I thought were direct questions, I'll post back here when I figure it out.
Still more to add...the above was running on an XR with 14.4.1. On a 5s with 12.5.1, the favicon request never makes it to the read handler, which is leading me to the NEProxySettings being required for http/https, at least for a NWUDPSession. If so, is there any way with a PacketTunnelProvider that all ip and tcp packets can be grabbed out of the tunnel without writing a proxy server for http traffic?
Also, do the settings require NEProxySettings to handle http/https traffic? I can see when I used NEProxySettings with a dummy endpoint, 127.0.0.1:54321, that browsers say the server can't be reached rather than saying there is no internet, which tells me that http/https requests go straight to the proxy server because I can see they never come through the NWUDPSession read handler. At this point, I would ask if there is a way to get the http packets as they come out of the VPN using a NWUDPSession read handler.
If a proxy is required, then why does the http request for the favicon make it to the read handler without the proxy setting?