[GH-ISSUE #3129] Automatically pause VPN on SIM card switch over #1452

Open
opened 2026-10-13 20:42:44 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @JohnWallerUK on GitHub (Sep 4, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3129

Feature request

I use AmneziaVPN on an iPhone, using a WireGuard connection, with two eSIMs:

  • My main eSIM is giffgaff and has normal Internet access.
  • My backup eSIM is Honest Mobile Smart SIM.
  • iOS has Allow Mobile Data Switching enabled, so if my main eSIM loses service, the phone automatically switches mobile data to the Smart SIM.

The problem is that Honest Mobile Smart SIM does not support VPN traffic. When iOS switches to the Smart SIM, my WireGuard connection through AmneziaVPN remains connected, and the Smart SIM connection effectively stops working until I manually disconnect AmneziaVPN.

When normal service returns, I then have to manually reconnect AmneziaVPN.

Desired behaviour

It would be useful if AmneziaVPN could automatically:

  • Stay connected on Wi-Fi.
  • Stay connected on my normal cellular connection.
  • Disconnect/pause the WireGuard tunnel when the active connection is a restricted cellular network that cannot support the VPN.
  • Automatically reconnect when normal Internet access becomes available again.

I understand that iOS may not expose the identity of the currently active SIM/eSIM directly to VPN applications, so detecting “Honest Smart SIM” specifically may not be possible.

A possible alternative would be a configurable connectivity probe, for example:

“Pause VPN if this URL cannot be reached without the VPN.”

I have tested the following URL:

https://www.cloudflare.com/cdn-cgi/trace

On my iPhone:

giffgaff → URL reachable → VPN should remain connected
Wi-Fi → URL reachable → VPN should remain connected
Honest Smart SIM → URL unreachable → VPN should pause/disconnect

When the URL becomes reachable again, AmneziaVPN could automatically reconnect the WireGuard tunnel.

This wouldn’t need to be specific to Honest Mobile. It could potentially help users with other restricted mobile networks, backup/travel eSIMs, captive networks, corporate networks, or connections that block VPN traffic.

An option such as “Pause VPN when connectivity test fails”, with an optional user-configurable probe URL, would be extremely useful on iOS.

Thanks for considering it.

Originally created by @JohnWallerUK on GitHub (Sep 4, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3129 Feature request I use AmneziaVPN on an iPhone, using a WireGuard connection, with two eSIMs: * My main eSIM is giffgaff and has normal Internet access. * My backup eSIM is Honest Mobile Smart SIM. * iOS has Allow Mobile Data Switching enabled, so if my main eSIM loses service, the phone automatically switches mobile data to the Smart SIM. The problem is that Honest Mobile Smart SIM does not support VPN traffic. When iOS switches to the Smart SIM, my WireGuard connection through AmneziaVPN remains connected, and the Smart SIM connection effectively stops working until I manually disconnect AmneziaVPN. When normal service returns, I then have to manually reconnect AmneziaVPN. Desired behaviour It would be useful if AmneziaVPN could automatically: * Stay connected on Wi-Fi. * Stay connected on my normal cellular connection. * Disconnect/pause the WireGuard tunnel when the active connection is a restricted cellular network that cannot support the VPN. * Automatically reconnect when normal Internet access becomes available again. I understand that iOS may not expose the identity of the currently active SIM/eSIM directly to VPN applications, so detecting “Honest Smart SIM” specifically may not be possible. A possible alternative would be a configurable connectivity probe, for example: “Pause VPN if this URL cannot be reached without the VPN.” I have tested the following URL: https://www.cloudflare.com/cdn-cgi/trace On my iPhone: giffgaff → URL reachable → VPN should remain connected Wi-Fi → URL reachable → VPN should remain connected Honest Smart SIM → URL unreachable → VPN should pause/disconnect When the URL becomes reachable again, AmneziaVPN could automatically reconnect the WireGuard tunnel. This wouldn’t need to be specific to Honest Mobile. It could potentially help users with other restricted mobile networks, backup/travel eSIMs, captive networks, corporate networks, or connections that block VPN traffic. An option such as “Pause VPN when connectivity test fails”, with an optional user-configurable probe URL, would be extremely useful on iOS. Thanks for considering it.
Author
Owner

@HeisLuka commented on GitHub (Sep 8, 2026):

I think this feature would be useful, but I would distinguish a user-defined network policy probe from a generic “Internet/VPN health” probe.

Current dev already has a useful foundation on iOS: PacketTunnelProvider owns an NWPathMonitor, tracks the active Wi-Fi/cellular interface, and computes a physical-path signature.

However, WireGuard/AWG currently deliberately ignores those path-change events:

if proto == .wireguard || proto == .openvpn {
return
}

because the WireGuard adapter is expected to handle network roaming itself.

That is fine for transport roaming, but it cannot implement the policy requested here:

physical network changed
-> this underlay does not permit/usefully support this VPN
-> temporarily pause VPN
-> retry when environment becomes suitable again

There is also an important edge case with relying only on NWPath.

Current pathSignature() contains roughly:

path.status
isExpensive
isConstrained
interface type
interface index
uses Wi-Fi/cellular/ethernet

It contains no SIM/carrier identity.

Therefore this state is possible:

SIM A:
cellular, index=4, satisfied, expensive=true

SIM B:
cellular, index=4, satisfied, expensive=true

pathSignature(A) == pathSignature(B)

So even if an eSIM switch changes the actual network policy, it does not necessarily give this code a distinguishable physical-network identity.

For that reason I think an active probe is a reasonable fallback, but I would not give a single URL probe the semantics:

URL failed
=> Internet bad
=> VPN unsupported

An HTTPS probe can fail because:

probe endpoint outage
DNS failure
captive portal
endpoint/rate limiting
TLS/interception behaviour
actual access policy of the carrier

and these are not equivalent.

I would expose two different semantics.

  1. User policy probe

The user explicitly says:

"On networks where this control URL is unavailable,
pause this VPN profile."

In that mode the URL is a policy discriminator, not a claim that the whole network is unhealthy.

This appears to fit the original Honest Smart SIM use case very well.

  1. Automatic VPN-compatibility detection

This should require multiple pieces of evidence, e.g.:

physical underlay is available
AND
underlay-bound control connectivity works
AND
WireGuard transport shows no useful progress for N windows

before classifying the current network as VPN-incompatible.

The WireGuard iOS implementation already exposes runtime:

rx_bytes
tx_bytes
last_handshake_time_sec

via wgAdapter.getRuntimeConfiguration(), so those signals can participate in the decision. I would not use a fresh handshake alone as proof of usable traffic, but stale/no-progress transport combined with an independently working physical underlay is much more informative than either signal alone.

I would also make the state machine explicit:

ACTIVE
|
| path event / repeated policy-probe failure / WG no-progress
v
SUSPECT
|
| failure threshold reached
v
PAUSED_BY_NETWORK_POLICY
|
| cooldown + probe recovery
v
RECOVERING
|
| several stable positive observations
v
ACTIVE

rather than toggling the tunnel on every individual probe result.

For example:

pause after 2-3 consecutive failures
retry with bounded backoff
resume after 2 consecutive successful recovery checks

so one transient timeout does not flap the VPN on/off.

One more important invariant: the “without VPN” probe must actually be proven to use the physical underlay.

If the probe accidentally follows the VPN path, then:

VPN broken
-> probe broken through VPN
-> "physical network is restricted"

is circular evidence.

I would therefore log at least:

physicalPath=<wifi/cellular + interface>
probeTarget=<...>
probePath=
probeResult=<...>
WG handshake age
WG rx/tx delta
state transition

Regression cases I would add:

  1. Probe URL temporarily down, VPN transport still progressing
    expected: do not pause in automatic-health mode

  2. Restricted cellular network, ordinary underlay usable,
    WG repeatedly has no progress
    expected: ACTIVE -> SUSPECT -> PAUSED

  3. Two eSIMs produce identical NWPath signature
    expected: policy can still detect incompatibility

  4. One failed probe followed by success
    expected: no VPN flap

  5. PAUSED -> first successful recovery probe
    expected: RECOVERING, not immediately ACTIVE

  6. Probe escapes through the VPN instead of the underlay
    expected: observation is invalid, no policy transition

This would keep the feature useful for restricted eSIMs/captive/corporate networks without turning one third-party HTTP endpoint into a global network-health oracle.

<!-- gh-comment-id:5586813085 --> @HeisLuka commented on GitHub (Sep 8, 2026): I think this feature would be useful, but I would distinguish a user-defined network policy probe from a generic “Internet/VPN health” probe. Current dev already has a useful foundation on iOS: PacketTunnelProvider owns an NWPathMonitor, tracks the active Wi-Fi/cellular interface, and computes a physical-path signature. However, WireGuard/AWG currently deliberately ignores those path-change events: if proto == .wireguard || proto == .openvpn { return } because the WireGuard adapter is expected to handle network roaming itself. That is fine for transport roaming, but it cannot implement the policy requested here: physical network changed -> this underlay does not permit/usefully support this VPN -> temporarily pause VPN -> retry when environment becomes suitable again There is also an important edge case with relying only on NWPath. Current pathSignature() contains roughly: path.status isExpensive isConstrained interface type interface index uses Wi-Fi/cellular/ethernet It contains no SIM/carrier identity. Therefore this state is possible: SIM A: cellular, index=4, satisfied, expensive=true SIM B: cellular, index=4, satisfied, expensive=true pathSignature(A) == pathSignature(B) So even if an eSIM switch changes the actual network policy, it does not necessarily give this code a distinguishable physical-network identity. For that reason I think an active probe is a reasonable fallback, but I would not give a single URL probe the semantics: URL failed => Internet bad => VPN unsupported An HTTPS probe can fail because: probe endpoint outage DNS failure captive portal endpoint/rate limiting TLS/interception behaviour actual access policy of the carrier and these are not equivalent. I would expose two different semantics. 1. User policy probe The user explicitly says: "On networks where this control URL is unavailable, pause this VPN profile." In that mode the URL is a policy discriminator, not a claim that the whole network is unhealthy. This appears to fit the original Honest Smart SIM use case very well. 2. Automatic VPN-compatibility detection This should require multiple pieces of evidence, e.g.: physical underlay is available AND underlay-bound control connectivity works AND WireGuard transport shows no useful progress for N windows before classifying the current network as VPN-incompatible. The WireGuard iOS implementation already exposes runtime: rx_bytes tx_bytes last_handshake_time_sec via wgAdapter.getRuntimeConfiguration(), so those signals can participate in the decision. I would not use a fresh handshake alone as proof of usable traffic, but stale/no-progress transport combined with an independently working physical underlay is much more informative than either signal alone. I would also make the state machine explicit: ACTIVE | | path event / repeated policy-probe failure / WG no-progress v SUSPECT | | failure threshold reached v PAUSED_BY_NETWORK_POLICY | | cooldown + probe recovery v RECOVERING | | several stable positive observations v ACTIVE rather than toggling the tunnel on every individual probe result. For example: pause after 2-3 consecutive failures retry with bounded backoff resume after 2 consecutive successful recovery checks so one transient timeout does not flap the VPN on/off. One more important invariant: the “without VPN” probe must actually be proven to use the physical underlay. If the probe accidentally follows the VPN path, then: VPN broken -> probe broken through VPN -> "physical network is restricted" is circular evidence. I would therefore log at least: physicalPath=<wifi/cellular + interface> probeTarget=<...> probePath=<physical-underlay> probeResult=<...> WG handshake age WG rx/tx delta state transition Regression cases I would add: 1. Probe URL temporarily down, VPN transport still progressing expected: do not pause in automatic-health mode 2. Restricted cellular network, ordinary underlay usable, WG repeatedly has no progress expected: ACTIVE -> SUSPECT -> PAUSED 3. Two eSIMs produce identical NWPath signature expected: policy can still detect incompatibility 4. One failed probe followed by success expected: no VPN flap 5. PAUSED -> first successful recovery probe expected: RECOVERING, not immediately ACTIVE 6. Probe escapes through the VPN instead of the underlay expected: observation is invalid, no policy transition This would keep the feature useful for restricted eSIMs/captive/corporate networks without turning one third-party HTTP endpoint into a global network-health oracle.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1452
No description provided.