Skip to content

macOS: skip VPN reconnect on same-SSID WiFi AP roams#310

Open
Safibulae wants to merge 1 commit intoWindscribe:masterfrom
Safibulae:fix/skip-reconnect-on-ssid-unchanged-roam
Open

macOS: skip VPN reconnect on same-SSID WiFi AP roams#310
Safibulae wants to merge 1 commit intoWindscribe:masterfrom
Safibulae:fix/skip-reconnect-on-ssid-unchanged-roam

Conversation

@Safibulae
Copy link

Summary

On macOS with enterprise WiFi (multiple APs, same SSID, FT_PSK), AP roams trigger a full VPN tunnel teardown and rebuild, causing 15-20s connectivity loss per event.

The root cause is that onNetworkStateChanged() in networkdetectionmanager_mac.cpp emits networkChanged() even when only cosmetic NetworkInterface fields change (e.g. metric, physicalAddress). The operator!= compares all 11 fields, so a same-SSID AP roam enters the "Unidentified interface change" branch and still triggers ConnectionManager::updateConnectionSettings(), which blindly disconnects and reconnects.

Change

Gate networkChanged() emission on whether interfaceName or networkOrSsid actually changed. Minor interface property changes (same-SSID AP roams) still update the cached state but no longer trigger a reconnect. WireGuard and AmneziaWG handle endpoint roaming natively at the protocol level, so the tunnel stays up.

One file changed, 9 insertions, 3 deletions.

Code path

  1. networkdetectionmanager_mac.cpp:onNetworkStateChanged() — outer != fires on any of 11 fields
  2. engine.cpp:onNetworkChange() — calls connectionManager_->updateConnectionSettings()
  3. connectionmanager.cpp:updateConnectionSettings() — if STATE_CONNECTED, calls connector_->startDisconnect()

Testing

Verified the issue on macOS 26.4 (Tahoe), Windscribe 2.21.6, AmneziaWG, enterprise WPA2/FT_PSK WiFi with multiple APs. Observed 12 tunnel rebuilds in 47 minutes on the same SSID with retained DHCP lease (details in #307).

Fixes #307

When macOS roams between access points on the same SSID (e.g. enterprise
WiFi), NetworkInterface fields like metric or physicalAddress can change
while interfaceName and networkOrSsid remain identical. The existing
operator!= on NetworkInterface compares all 11 fields, so these cosmetic
changes enter the "Unidentified interface change" branch in
onNetworkStateChanged() and still emit networkChanged(), which triggers
a full tunnel teardown and rebuild via ConnectionManager::updateConnectionSettings().

This causes 15-20 seconds of connectivity loss per roam event, which on
multi-AP networks can happen repeatedly.

This patch gates the networkChanged() emission on whether the change is
significant (interface name or SSID actually changed). Minor changes such
as same-SSID AP roams still update the cached state but no longer trigger
a reconnect. The tunnel stays up through the roam, which WireGuard and
AmneziaWG handle natively at the protocol level.

Fixes Windscribe#307
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

macOS: Is full AmneziaWG tunnel rebuild necessary on same-SSID WiFi AP roams?

1 participant