Skip to content

WireGuard tunnel disconnects on Wi-Fi roaming / network switch, requires manual toggle to reconnect #3016

Open

Description

@mmjoshi

Environment

App version: RethinkDNS v0.5.6
Android version: 14
Device: realme narzo 50 Pro 5G
Proxy type: WireGuard (single tunnel, Always-on disabled)
Persistent keepalive: 25 sec

Description
The WireGuard proxy disconnects and does not automatically reconnect whenever the underlying network changes — this happens both when roaming between two Wi-Fi access points on the same network (same SSID and password, extender in bridge/AP mode) and when switching between Wi-Fi and mobile data. The tunnel appears to stall rather than recover; the only fix is manually toggling the WireGuard connection off and on.

Steps to reproduce

Connect to Wi-Fi with WireGuard proxy active in RethinkDNS.
Walk to an area of the home covered by a Wi-Fi extender broadcasting the same SSID/password as the main router (extender in bridge mode, same security type).
Phone roams from router to extender (or vice versa).
Observe: WireGuard tunnel disconnects and does not reconnect on its own.

Same behavior also occurs switching Wi-Fi → mobile data and back, even with "Use All Networks" enabled in RethinkDNS settings and mobile data left on continuously.

Expected behavior
WireGuard tunnel should detect the network change and automatically rebind/reconnect without manual intervention, similar to how the standalone official WireGuard app handles roaming.

Actual behavior
Tunnel stalls; must manually toggle the WireGuard connection off and on to restore connectivity. This causes active calls (e.g. WhatsApp) to drop entirely rather than briefly stutter.

Troubleshooting already done

Confirmed extender is in bridge/access point mode (not router mode), same SSID and security type as main router.
Disabled Android's "Connect to best Wi-Fi network" setting as a test — no change in frequency of disconnects (re-enabled afterward, as it's needed for extender roaming to function).
Confirmed "Persistent keepalive" is already set to 25 sec in the WireGuard peer config.
Confirmed on latest app version (0.5.6).
Comparison test: A second phone (Samsung, same Android version range, same home network, no RethinkDNS installed) roams between the same router/extender and switches Wi-Fi↔mobile data without any call drops or manual reconnection needed — isolating this as an app-side issue rather than a network configuration issue.

Related issue
This may be the same underlying cause as #1808 (WireGuard endpoint IP change causing stall with no auto-reconnect).

Activity

  1. ignoramous commented on Aug 20, 2026

    @ignoramous
    Collaborator

    Surprising. Rethink has seen significant improvements with respect to WireGuard reconnectivity since v055v.

    Will you scroll to the "WireGuard" section of the About -> General dialog & see what value for "lastOK" & "lastOpen" (for the WireGuard that's failing on network switches) is? These indicate the latest attempt by Rethink to "handshake" & reconnect with its peers. All text is selectable, so you can copy paste it here, if you're not tech savvy to grok the section.

    You can view About -> App Logs to check if any of the "Error" messages seem relevant. You can use the search bar to filter out for keywords like "wg". You can also change the log level to "Warning" or "Info" when prompted, to capture then diagnose the events better (the level for App Logs will switch back to its default "Error" after ~3h to conserve battery).

    You can also try and see if turning ON Configure -> Network -> Smart Persistent Keepalive helps.

  2. self-assigned this
    on Aug 20, 2026
  3. mmjoshi commented on Aug 20, 2026

    @mmjoshi
    Author
  4. ignoramous commented on Aug 20, 2026

    @ignoramous
    Collaborator

    Thanks. That was super helpful.

    had this problem about an hour ago

    Does the eperm issue happen consistently, frequently, or intermittently? If consistently, that's worrying.

    If consistently or frequently: Can you check, if you see the same issue with Rethink on another non Realme/Vivo/Oppo Android (they all use the same ColorOS, I believe)?

    If not, please see steps below.

    the WireGuard socket gets EPERM and doesn't seem to retry after that.

    I have seen this before but at the time, it seemed like an OS bug, as Rethink (which is a VPN) should always be able to bind to underlying networks.

    Things to try (one at a time or all at once):

    • Turn off the built-in "Block connections without VPN" in Android's Settings app.
    • Turn off Configure -> Network -> Use all available networks.
    • Set Configure -> Network -> Connection change policy to "Relaxed" (remember to switch this to "Auto" if it doesn't work).
    • Turn off other "experimental" settings in Configure -> Network like Bandwidth Booster & Loopback, if set.

    About → General at the time showed status: unresponsive, lastOk: 0.

    What value is lastOpen? lastOpen indicates the latest (socket) re-connection / re-establish attempt, while lastOK indicates latest (WireGuard protocol) handshake attempt, when you hit eperm?

  5. ignoramous commented on Aug 20, 2026

    @ignoramous
    Collaborator

    Tunnel stalls; must manually toggle the WireGuard connection off and on to restore connectivity

    The next time eperm happens, please check if tapping on the "refresh" (icon) button at the top right hand corner of Configure -> Proxy -> Setup WireGuard UI recovers WireGuard connectivity to the peer without having to go through a off / on cycle.

    Are you using WireGuard in Simple mode or Advanced mode? If in Advanced mode, does the eperm issue happen with all active WireGuards or just one?

    Comparison test: A second phone (Samsung, same Android version range, same home network, no RethinkDNS installed) roams between the same router/extender and switches Wi-Fi↔mobile data without any call drops or manual reconnection needed — isolating this as an app-side issue rather than a network configuration issue.

    I'm inclined to believe this is an OS (Android 14) bug specific to OEM (Realme, in this case). See if the steps mentioned in the previous comment help workaround eperm. You may try one or any or all options from those steps.

  6. mmjoshi commented on Aug 22, 2026

    @mmjoshi
    Author

    Update: three separate captures, showing the failure isn't always the same pattern

    I've now caught this three times with logging on, plus tried every suggested setting change. Details below.

    Settings tried (all reverted/confirmed as noted):

    Turned off "Block connections without VPN" in Android settings
    Turned off "Use all available networks"
    Set Connection change policy to "Relaxed" — no improvement, reverted back to "Auto" as suggested
    Tapping the refresh icon in Configure → Proxy → Setup WireGuard does not recover connectivity — still need a full off/on toggle every time
    Issue remains consistent, not intermittent — happens on effectively every network switch/roam
    

    Capture 1 (first reported) — WireGuard socket itself EPERMs right after roam:

    02:27:25 — capability change detected, new netId 253 (WiFi) + netId 252 (Cellular) both live
    02:27:30 — err bindToNw(nw: 1090032422925, netid: 253, fid: 5, Binding socket to network 253 failed: EPERM), specifically bind failed: who: wg29, addr: 0.0.0.0:43893
    02:29:31 — old socket then reports read udp4/udp6 ...: use of closed network connection
    From 02:27:30 for 13+ min: continuous Failed to send handshake initiation: wg: bind: peer unreachable, DNS no connectivity | no answer. lastOk: 0, lastOpen: 13 sec ago at the time — a reconnect attempt was being made, but no handshake ever succeeded.
    

    Capture 2 (next occurrence) — no EPERM at all, yet same stall:

    22:48:20 — Failed to send handshake initiation: wg: bind: peer unreachable begins, no EPERM anywhere in this log
    Continues intermittently until 00:34:33, then stops
    By ~03:02–03:03 the log shows tcp: ... connection was refused and ICMP attempts — signs of real connectivity, suggesting it recovered in that window. I honestly can't confirm whether I manually toggled it in that window or it recovered on its own — will pay closer attention to this timing next time.
    

    Capture 3 (most recent) — EPERM hits Base/Exit sockets for ~50 min before WireGuard itself fails:

    10:59:51 to 11:49:01 — repeated err bindToNw(... EPERM) but on the Base and Exit proxy sockets (245 and 282 occurrences respectively), not wg29
    Only at 11:47:58, near the end of that window, does wg29 itself start failing — and with a different message this time: Failed to send data packets: wg: bind: peer unreachable (not "handshake initiation" — suggesting the tunnel was live and lost mid-flow, not failing to establish)
    Toggled manually shortly after
    

    So across three captures: sometimes wg29's own socket EPERMs immediately after a roam; sometimes other proxy sockets (Base/Exit) EPERM for a long stretch before wg29 fails; and sometimes there's no EPERM at all and it still goes unresponsive. All three logs were captured at Error level (only reverting to Info in the final export lines), so I don't have the Info-level CAPABILITY_CHANGE/netId context for captures 2 and 3 — happy to try capturing at Info level proactively for longer stretches if that would help pin down the network-change correlation more precisely.

    Let me know what else would be useful — I have attached the raw log files so that you can see the unfiltered captures.

    rethink_log_capture2_no_eperm.txt
    rethink_log_capture3_eperm_base_exit.txt
    rethink_log_capture1_eperm_on_wg29.txt

  7. mmjoshi commented on Aug 24, 2026

    @mmjoshi
    Author

    New finding: dual-stack WireGuard tunnel — DNS via tunnel fails, browsing breaks entirely; general traffic still works

    Following up on the earlier notok/timeout report — did a clean, controlled test to isolate the actual cause.

    Setup: WireGuard config identical to my working single-stack (SG) one, except Address now includes an IPv6 address too: Address = 10.2.0.2/32, 2a07:b944::2:2/128 (matches Proton's own dual-stack config format, confirmed working correctly on desktop/laptop with the same file).

    Controlled test (Wi-Fi, no roaming/network change involved at all):

    Disabled all proxies, waited, confirmed clean state.
    Enabled the dual-stack (CA) tunnel only.
    Browsing failed immediately — not delayed, not intermittent.
    Waited 2 min, then 5 min — browsing still failed throughout.
    Syncthing (LAN sync app) stayed connected and working the entire time.
    Switched back to the single-stack (SG) tunnel — browsing recovered immediately.
    Diagnosis from the Stats/log dump captured during the failure window:

    Tunnel itself: status: ok, status-reason: TOK: write ok, real rx/tx traffic flowing, lastOk: 2 min ago — genuinely healthy and carrying real data (confirmed via visible Syncthing connections routed through wg33 to real external IPs).
    But: wg33:10.2.0.1:53[DNS/Failing/15000ms] and Cachewg33:cached.10.2.0.1:53[DNS/Failing/0ms] — DNS queries to the tunnel's own configured DNS server (10.2.0.1, from the config's DNS = line) are timing out repeatedly (15s timeout).
    Meanwhile Rethink's own resolver works fine in the same log: Default:ech.rethink.zero.rethinkdns.com[DNS-over-HTTPS/OK/43ms].
    My read: browsing needs DNS resolution; Syncthing doesn't (hardcoded IPs). If DNS lookups are being routed through the tunnel's peer-DNS (10.2.0.1) and that's failing/timing out on this device specifically for dual-stack tunnels, that would fully explain why browsing dies instantly while raw tunnel connectivity is fine.

    Attempted workaround, hit another issue: tried removing the DNS = line from the config entirely to force fallback to Rethink's own resolver instead of the tunnel's DNS — but this throws an "invalid config" error on import, so RethinkDNS appears to require that field to be present for WireGuard configs, meaning this isn't something I can test/work around from the config side.

    Environment recap: Realme, Android 14, RethinkDNS v0.5.6, Advanced WireGuard mode, single tunnel active. Same dual-stack config file works with no issues (no leaks, normal browsing) on a laptop via standalone WireGuard client — so this looks device/app-specific, not a bad config file.

    I think I've exhausted what I can usefully test from my side — happy to grab any specific additional logs/settings if there's something particular you'd want to see, but wanted to flag this clearly as I believe it's a distinct, well-isolated issue from the original roaming/EPERM report.

    capture4_dualstack_dns_fail.txt

  8. mmjoshi commented on Aug 25, 2026

    @mmjoshi
    Author

    Additional observation: caught the SG (single-stack) tunnel showing "1 Failing" on the Home screen, and simultaneously ran an ipleak.net test — it correctly showed the proxy's Singapore IP, not my real ISP address. So this "Failing" status appears to be a UI/status-reporting inaccuracy rather than an actual connectivity/leak issue — traffic continues to be properly tunneled even when the badge is wrong. Worth noting since it's a different (lower-severity) class of bug than the dual-stack leak/breakage reported separately.

    Details Image Image
  9. mmjoshi commented on Aug 25, 2026

    @mmjoshi
    Author

    Follow-up: on mobile data, "Failing" status corresponds to a real leak (unlike Wi-Fi)

    Earlier I noted that on Wi-Fi, catching the SG (single-stack) proxy in "1 Failing" state still showed the correct Singapore IP on ipleak.net — i.e., traffic kept flowing through the tunnel correctly despite the misleading status badge.

    Just repeated the same check on mobile data (4G, Jio), and the result is different and more concerning:

    Home screen showed "1 Failing" for the SG WireGuard proxy (screenshot attached).
    ipleak.net at the same moment showed my real Jio IPv4 (152.58.30.46) and IPv6 (2409:40c2:101b:968f:8000::), both flagged as Reliance Jio Infocomm Limited, India — not the Singapore proxy IP at all (screenshot attached).

    So on mobile data specifically, the "Failing" state appears to correspond to a genuine leak — traffic silently falls back to direct/Exit routing rather than staying blocked or recovering through the tunnel, exposing my real IP and location. This is a different (and more serious) outcome than the Wi-Fi case, where the same status flicker had no real effect on routing.

    Pattern so far:

    Wi-Fi + "Failing": cosmetic only — traffic still correctly tunneled (confirmed via ipleak.net).
    Mobile data + "Failing": real leak — traffic falls through to direct, exposing real ISP/location (confirmed via ipleak.net, screenshots attached).

    Given this, the "Failing" status isn't just a UI inaccuracy in all cases — on mobile data it seems to reflect (or possibly cause) an actual fallback-to-direct that a user would have no way of knowing about just by looking at browsing working normally.

    Details Image Image
  10. ignoramous commented on Aug 25, 2026

    @ignoramous
    Collaborator

    Given this, the "Failing" status isn't just a UI inaccuracy in all cases — on mobile data it seems to reflect (or possibly cause) an actual fallback-to-direct that a user would have no way of knowing about just by looking at browsing working normally.

    Make sure Configure -> Network -> Choose IP version is set to "Auto" and the WireGuard you're using is set up as "Lockdown" (since you're using in Advanced mode, per this comment).

    Alternatively, if you do not use the per-app "Bypass app from all proxies" (in Configure -> Apps), you can instruct Rethink to drop all non-proxied egress from third-party apps by turning on Configure -> Network -> Proxy Lockdown (this is an experimental setting).

  11. mmjoshi commented on Aug 26, 2026

    @mmjoshi
    Author

    Update: tested Lockdown as suggested — confirms the leak, and reveals the status badge is unreliable even during "Active"

    What I did: Enabled Lockdown on the WireGuard tunnel (Configure → Proxy → Setup WireGuard → Lockdown), as suggested. "Choose IP version" was already set to Auto. Did not enable global Proxy Lockdown, since I rely on the per-app "Bypass from all proxies" exclusion (6 apps excluded) and didn't want to interfere with that.

    Before enabling Lockdown (screenshots attached): caught the Home screen showing "1 Active" under Proxy — not Failing — while ipleak.net simultaneously showed my real Jio IPv4 (152.58.30.46) and IPv6 (2409:40c2:101b:968f:8000::), both flagged Reliance Jio Infocomm Limited. Timestamps 5 seconds apart, same session. So the leak isn't limited to visible "Failing" states — it can happen while the UI shows everything as normal and protected, with no indicator to the user at all.

    After enabling Lockdown (screenshots attached): as expected, when the tunnel hit a "Failing" state, browsing correctly stopped instead of leaking — Lockdown is working as intended there. But separately, I also caught a case where Proxy still showed "1 Active", yet DNS showed "No Internet" and browsing to ipleak.net failed outright (net::ERR_CONNECTION_REFUSED). I had to manually toggle the proxy to recover.

    What this confirms:

    The earlier leak reports are validated — Lockdown converting them into visible failures proves real traffic really was silently bypassing the tunnel before.
    The root cause (whatever intermittently breaks the tunnel's ability to actually carry traffic) is not reflected by the "Active"/"Failing" status badge at all — it can happen in either displayed state. The badge appears to track something like last-handshake/keepalive success rather than actual current data-plane health.
    Lockdown is a good safety mitigation (turns silent leak → visible failure) but does not fix the underlying problem — manual toggling is still required to recover either way.

    Open question for you: does your Lockdown/Proxy Lockdown suggestion have any bearing on the separate dual-stack (IPv6-address-on-tunnel) issue reported earlier — where browsing and Syncthing failed outright on the US/CA config even on stable Wi-Fi with no roaming involved? That one never exhibited leak-then-fallback behavior — it just failed immediately and stayed failed. Want to make sure that thread doesn't get deprioritized while this leak/lockdown discussion is being worked through, since it seems like a distinct root cause.

    What I think needs fixing on RethinkDNS's side:

    The actual mechanism causing intermittent tunnel data-plane failure (independent of roaming) needs investigation — this is the true root cause behind both the leak and the Lockdown-induced "No Internet while Active" state.
    The status badge (Active/Failing) should reflect actual data-plane health, not just handshake/keepalive state, so users have an accurate signal.
    Even with Lockdown, some form of automatic recovery/retry would be valuable — right now the only recovery path is a manual toggle, regardless of whether the failure is silent (no Lockdown) or blocked (with Lockdown).

    Details Image Image Image Image
  12. mmjoshi commented on Sep 9, 2026

    @mmjoshi
    Author

    Any update on this?

  13. mmjoshi commented on Oct 5, 2026

    @mmjoshi
    Author

    Any ETA on this?

  14. ignoramous commented on Oct 15, 2026

    @ignoramous
    Collaborator

    @mmjoshi I have analyzed your detailed bug reports, but I don't have a correct theory on what's really going on. Does v058 show any improvement? If not, can you switch Configure -> Network -> Choose IP version to "IPv4" only and see if things improve?

  15. mmjoshi commented on Oct 16, 2026

    @mmjoshi
    Author
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions