Post

Replies

Boosts

Views

Activity

IKEv2 Personal VPN: Child SA torn down after 120s idle (NEIKEv2ErrorDomain Code=15) with DisconnectOnIdle already NO
We ship a consumer VPN app on iOS, iPadOS and tvOS using a Personal VPN configuration: NEVPNManager with NEVPNProtocolIKEv2, EAP-MSCHAPv2, no MDM profile installed. After exactly 120 seconds with no traffic, iOS destroys the Child SA and disconnects the tunnel. I would like to know whether that timer is configurable, and if not, what the intended mitigation is. From a device sysdiagnose (iPhone, iOS 26.6, build 23G71): NEIPSecDBStatsUpdate: SA is idle for past 120 secs KernelSASession[1, IKEv2 Session Database] idle timeout SA Internal SAID = 2 SPI = C53320D1 Direction = Outbound ChildSA[1] state Connected -> Disconnected error Domain=NEIKEv2ErrorDomain Code=15 "IdleTimeout" <NEIKEv2Provider: Primary Tunnel>: stopping tunnel since Child disconnected nesessionmanager: plugin disconnected with reason "Tunnel was idle for too long" This happened 12 times across a 9.2 hour overnight capture on one idle device. Median time before the tunnel re-established was 14m35s. DISCONNECT-ON-IDLE IS NOT ENABLED The same sysdiagnose shows the plugin's own configuration as: disconnectOnIdle = NO disconnectOnIdleTimeout = 0 These are the stock defaults. There is no disconnectOnIdle property on the public NEVPNProtocol, so a Personal VPN app cannot set them either way. The installed SA parameters contain no idle field at all, only "Lifetime Seconds = 1800", which is honoured correctly: the same capture shows 20 clean rekey cycles. WHAT I HAVE RULED OUT iOS logs a distinct stop reason for each of the following, and none of them occurred across 24 teardowns: "On Demand Disconnect rule matched", "Tunnel was terminated by the server", "Server is not responding", "Network changed, tunnel no longer viable", "Device went to sleep", "Stop command received". The only reason recorded was "Tunnel was idle for too long". On the gateway (strongSwan), IKE rekey and reauth are disabled, uniqueids is never, and DPD is answered in roughly 200ms right up to the teardown. The gateway considers the tunnel healthy at the moment iOS tears it down. DPD does not reset the timer, which makes sense: DPD is an INFORMATIONAL exchange on the IKE SA, whereas the log shows the timer measuring the OUTBOUND Child SA (SAID 2). THE APP CANNOT SEE THIS HAPPEN NEVPNConnection.fetchLastDisconnectError() returns nil for this teardown, because the error is in NEIKEv2ErrorDomain rather than NEVPNConnectionErrorDomain. The app has no supported way to detect that the tunnel dropped for this reason, or to distinguish it from a user-initiated disconnect. It is only visible in a sysdiagnose. TRAFFIC IS NOT HELD DURING THE RECONNECT With Connect On Demand enabled (NEOnDemandRuleConnect, interfaceTypeMatch .any), traffic after the teardown does not wait for the tunnel. On device wake following one of these drops: 01:32:43 device wakes 01:32:43 [C331 ... :443] path:satisfied @0.001s, interface: en0[802.11], uses wifi 01:32:44 [C331 ... :443] flow:finish_connect @0.623s (over en0) 01:32:47 tunnel status changed to connected so flows complete over the physical interface for several seconds before the VPN re-establishes. On-demand triggered the reconnect but did not delay the traffic. For a VPN product this window is the part that concerns me most. QUESTIONS Is the 120 second Child SA idle timeout configurable for a Personal VPN using NEVPNProtocolIKEv2, from the app or from a configuration profile? If DisconnectOnIdle / DisconnectOnIdleTimer are meant to control it, why does the teardown occur when they are NO / 0? If it is not configurable, is application-generated keepalive traffic the intended workaround? If so, how is that expected to work while iOS has the app suspended, which is exactly when a tunnel goes idle? Would server originated traffic that elicits a client response be a supported approach? Is there any supported way for an app to be notified of this teardown, given that fetchLastDisconnectError() returns nil for it? Is the behaviour in "traffic is not held during the reconnect" expected for NEOnDemandRuleConnect, or should matching flows be delayed until the tunnel is up? Is includeAllNetworks the only supported way to close that window? Happy to supply the full sysdiagnose privately.
1
0
217
21h
IKEv2 Personal VPN: Child SA torn down after 120s idle (NEIKEv2ErrorDomain Code=15) with DisconnectOnIdle already NO
We ship a consumer VPN app on iOS, iPadOS and tvOS using a Personal VPN configuration: NEVPNManager with NEVPNProtocolIKEv2, EAP-MSCHAPv2, no MDM profile installed. After exactly 120 seconds with no traffic, iOS destroys the Child SA and disconnects the tunnel. I would like to know whether that timer is configurable, and if not, what the intended mitigation is. From a device sysdiagnose (iPhone, iOS 26.6, build 23G71): NEIPSecDBStatsUpdate: SA is idle for past 120 secs KernelSASession[1, IKEv2 Session Database] idle timeout SA Internal SAID = 2 SPI = C53320D1 Direction = Outbound ChildSA[1] state Connected -> Disconnected error Domain=NEIKEv2ErrorDomain Code=15 "IdleTimeout" <NEIKEv2Provider: Primary Tunnel>: stopping tunnel since Child disconnected nesessionmanager: plugin disconnected with reason "Tunnel was idle for too long" This happened 12 times across a 9.2 hour overnight capture on one idle device. Median time before the tunnel re-established was 14m35s. DISCONNECT-ON-IDLE IS NOT ENABLED The same sysdiagnose shows the plugin's own configuration as: disconnectOnIdle = NO disconnectOnIdleTimeout = 0 These are the stock defaults. There is no disconnectOnIdle property on the public NEVPNProtocol, so a Personal VPN app cannot set them either way. The installed SA parameters contain no idle field at all, only "Lifetime Seconds = 1800", which is honoured correctly: the same capture shows 20 clean rekey cycles. WHAT I HAVE RULED OUT iOS logs a distinct stop reason for each of the following, and none of them occurred across 24 teardowns: "On Demand Disconnect rule matched", "Tunnel was terminated by the server", "Server is not responding", "Network changed, tunnel no longer viable", "Device went to sleep", "Stop command received". The only reason recorded was "Tunnel was idle for too long". On the gateway (strongSwan), IKE rekey and reauth are disabled, uniqueids is never, and DPD is answered in roughly 200ms right up to the teardown. The gateway considers the tunnel healthy at the moment iOS tears it down. DPD does not reset the timer, which makes sense: DPD is an INFORMATIONAL exchange on the IKE SA, whereas the log shows the timer measuring the OUTBOUND Child SA (SAID 2). THE APP CANNOT SEE THIS HAPPEN NEVPNConnection.fetchLastDisconnectError() returns nil for this teardown, because the error is in NEIKEv2ErrorDomain rather than NEVPNConnectionErrorDomain. The app has no supported way to detect that the tunnel dropped for this reason, or to distinguish it from a user-initiated disconnect. It is only visible in a sysdiagnose. TRAFFIC IS NOT HELD DURING THE RECONNECT With Connect On Demand enabled (NEOnDemandRuleConnect, interfaceTypeMatch .any), traffic after the teardown does not wait for the tunnel. On device wake following one of these drops: 01:32:43 device wakes 01:32:43 [C331 ... :443] path:satisfied @0.001s, interface: en0[802.11], uses wifi 01:32:44 [C331 ... :443] flow:finish_connect @0.623s (over en0) 01:32:47 tunnel status changed to connected so flows complete over the physical interface for several seconds before the VPN re-establishes. On-demand triggered the reconnect but did not delay the traffic. For a VPN product this window is the part that concerns me most. QUESTIONS Is the 120 second Child SA idle timeout configurable for a Personal VPN using NEVPNProtocolIKEv2, from the app or from a configuration profile? If DisconnectOnIdle / DisconnectOnIdleTimer are meant to control it, why does the teardown occur when they are NO / 0? If it is not configurable, is application-generated keepalive traffic the intended workaround? If so, how is that expected to work while iOS has the app suspended, which is exactly when a tunnel goes idle? Would server originated traffic that elicits a client response be a supported approach? Is there any supported way for an app to be notified of this teardown, given that fetchLastDisconnectError() returns nil for it? Is the behaviour in "traffic is not held during the reconnect" expected for NEOnDemandRuleConnect, or should matching flows be delayed until the tunnel is up? Is includeAllNetworks the only supported way to close that window? Happy to supply the full sysdiagnose privately.
Replies
1
Boosts
0
Views
217
Activity
21h
Revoked a push notification key please help.
I accidentally deleted a Push notification key that is being used by most of our apps. How big of a problem is it and how can I solve it to help my follow developers out? I do have access to our Firebase and what would be advised I should do?
Replies
1
Boosts
0
Views
1.2k
Activity
Jan ’24