Repository navigation
[Bug]: Proton VPN address is advertised as Tailscale IP and breaks phone pairing #15750
Copy link
Copy link
Open
Labels
bugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
Description
Activity
Note
Grok responding on behalf of Julius.
Triage
Thanks for the clear report and the working workaround, @arthurkatcher!
What I found
Confirmed on
mainat4ee6bfd. This is separate from #15751, where the Connections list stays cached after the network changes.Why the wrong address gets picked:
isTailscaleIpv4Address(packages/tailscale/src/tailscale.ts) accepts any address in100.64.0.0/10. That's shared CGNAT space, not Tailscale's alone.- Proton's Linux kill switch adds a dummy interface (
pvpnksintrf0/pvpnksintrf1) with100.85.0.1/24, which falls in that range. resolveTailscaleIpAdvertisedEndpoints(apps/desktop/src/backend/tailscaleEndpointProvider.ts) scansObject.values(networkInterfaces), so interface names are dropped and listing order decides which address comes first.- Every
tailscale-ip:endpoint shares the saved preference keytailscale:ip:http(endpointDefaultPreferenceKeyinConnectionsSettings.tsx), and pairing takes the first match. So the Proton address stays selected, and the phone's/.well-known/t3-environmentrequest times out.
The same range check also affects:
- LAN endpoint selection (
isUsableLanIpv4Address). - The exposure state (
resolveRuntimeStateinapps/desktop/src/backend/DesktopServerExposure.ts).
Related, not duplicates:
- fix(desktop): separate LAN and Tailscale pairing endpoints #9882 separated LAN and Tailscale entries using this same range check.
- fix(macos): stop repeated data access prompts #11920 was about macOS permission prompts.
- Other non-Tailscale CGNAT interfaces could hit the same mislabel, so filtering
pvpnksintrf*by name alone wouldn't cover it.
Likely fix area
Some options:
- Use addresses Tailscale actually owns.
readTailscaleStatusalready returnsSelf.TailscaleIPsastailnetIpv4Addresses, but the desktop path only keeps the MagicDNS name. Its cached result could be used to filter the interface candidates. Spawningtailscale statuson every settings read should be avoided, since that brings back the macOS "Other apps" prompt. - Keep interface names during the scan and prefer
tailscale*/utun*-style interfaces when several CGNAT addresses exist. - Revisit the shared
tailscale:ip:httppreference key, so a stale first candidate doesn't stay selected.
Until then, your workaround works: keep the port, path, and token, and replace only the host with the address from
tailscale ip -4.A maintainer will decide on the fix direction.
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
on Oct 4, 2026 Ran into this with Cloudflare WARP as well.
Metadata
Metadata
Assignees
Labels
bugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
Before submitting
Area
apps/desktop
Steps to reproduce
pvpnksintrf1has100.85.0.1andtailscale0has100.74.126.34.100.85.0.1, create a pairing link, and open it on a phone connected to the same tailnet from another network.tailscale ip -4on the host.The failure also appears with a freshly computed endpoint list: the current provider emits the Proton address before the actual Tailscale address.
Expected behavior
The Tailscale pairing option should advertise the host's actual Tailscale address. An unrelated VPN interface should not be labeled as reachable through the tailnet.
Actual behavior
T3 advertises
http://100.85.0.1:3773/as Tailscale IP and uses it in the pairing link. The phone's request to/.well-known/t3-environmenttimes out after 10 seconds. Replacing only the host in the link with100.74.126.34makes pairing succeed.Impact
Major degradation or frequent failure: the generated remote-pairing link is unusable unless the address is manually corrected.
Version or commit
Observed on desktop 0.0.45. Source reproduction confirmed on main at
4ee6bfd50ef4a089440d5c3662db2298da9cc50e.Environment
Ubuntu 24.04.4 LTS; Linux x86_64 AppImage; Proton VPN; Tailscale 1.102.4; iPhone connected to the same tailnet.
Relevant evidence
The provider scans every interface and accepts anything matching isTailscaleIpv4Address, which only tests the shared
100.64.0.0/10range. That range alone does not establish ownership by Tailscale.The saved Tailscale default is keyed by endpoint type, so the first incorrectly admitted candidate can remain selected. Filtering out the unrelated candidate lets the existing selection logic resolve to the real address.
Related but different: #9882 separates LAN and Tailscale entries; #11920 proposed broader discovery changes for macOS permission prompts and was closed without merging during the V2 transition.
Workaround
Use
tailscale ip -4and replace the address in the generated pairing URL while preserving the port, path, and token. This worked on the affected phone. Reloading alone does not change the range-based classification.