Bug 515707 - KDE Connect 1.35.x fails TLS handshake over Tailscale VPN — regression from 1.34.4
Summary: KDE Connect 1.35.x fails TLS handshake over Tailscale VPN — regression from 1...
Status: ASSIGNED
Alias: None
Product: kdeconnect
Classification: Applications
Component: android-application (other bugs)
Version First Reported In: unspecified
Platform: Android Android 14.x
: NOR major
Target Milestone: ---
Assignee: Albert Vaca Cintora
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-02-08 04:08 UTC by Matt
Modified: 2026-02-11 07:58 UTC (History)
5 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matt 2026-02-08 04:08:36 UTC
SUMMARY


STEPS TO REPRODUCE
1. Set up a Tailscale network with the desktop configured as an exit node
2. Configure firewall to allow KDE Connect ports 1714-1764 TCP/UDP on the Tailscale interface
3. Install KDE Connect 1.35.1 or 1.35.2 on Android phone
4. Install KDE Connect (kdeconnectd 25.12.1) on desktop
5. Connect both devices to the same LAN
6. Pair devices over LAN — pairing succeeds, all plugins load
7. Disconnect phone from LAN WiFi
8. Enable Tailscale on the phone, using the desktop as the exit node
9. Verify Tailscale connectivity: ping desktop Tailscale IP
10. Verify other services work over Tailscale: VNC on port 5900 connects fine
11. Open KDE Connect on phone, refresh device list
12. Manually add desktop's Tailscale IP (100.x.x.x) in KDE Connect on phone
13. Phone shows ping succeeds but no device connection is established
14. tcpdump on desktop shows: UDP identity packet arrives, TCP three-way handshake completes, phone sends RST during TLS negotiation
15. Revert phone to KDE Connect 1.34.4 — repeat steps 7-12, connection works immediately over Tailscale

OBSERVED RESULT
Phone sends UDP identity packet (received by desktop). Desktop initiates TCP connection back to phone (three-way handshake completes). During TLS negotiation, phone sends TCP RST, killing the connection. Devices never connect over Tailscale. Even manually adding the desktop's Tailscale IP on the phone shows a successful ping but no KDE Connect connection.

EXPECTED RESULT
Devices connect over Tailscale as they did on version 1.34.4.

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: Fedora Linux 43
KDE Plasma Version: 6.5.5
KDE Frameworks Version: 6.22.0
Qt Version: 6.10.1
Phone: Samsung S21 Ultra, Android 14, KDE Connect 1.35.1 / 1.35.2
Tailscale: forced DERP relay


ADDITIONAL INFORMATION
VNC (port 5900) works perfectly over the same Tailscale tunnel, so the network path itself is fine.
Firewall ports 1714-1764 TCP/UDP confirmed open on tailscale and trusted zones.
tcpdump on desktop confirms: UDP identity packets arrive, TCP handshake completes, phone sends RST during TLS.
Desktop debug log (QT_LOGGING_RULES="kdeconnect.*=true") shows: "TCP connection done (I'm the existing device)" then "Starting server ssl (I'm the client TCP socket)" — nothing after that.
Reverting to KDE Connect Android 1.34.4 fixes it right away. Pairing on LAN and then roaming to Tailscale works perfectly on 1.34.4.
Issue reproduces on both 1.35.1 and 1.35.2.
This appears to be the Android app rejecting TLS connections arriving on VPN interfaces.
Comment 1 Albert Vaca Cintora 2026-02-08 09:52:31 UTC
Maybe this change affects your setup? https://invent.kde.org/network/kdeconnect-android/-/commit/72881f8b04d280284b31ddd9810ee1c9a0fa8320

If that's the case you should see the new log messages though.
Comment 2 knyipab 2026-02-08 14:29:01 UTC
I can confirm this regression is present in v1.35.2 and breaks VPN-based setups (specifically Tailscale).

My Setup:
* Device: Samsung SM-F9460 
* OS: Android 16 
* App Version: KDE Connect v1.35.2 
* Network: Tailscale (100.x.y.z range)
* Method: "Add Device by IP" (Manual entry)

Investigation & Logs:
* Network Verification: I verified connectivity from the phone using Termux. Running nc -z -v <desktop-tailscale-ip> 1716 succeeds immediately, confirming the tunnel is up and ports are reachable.
* The Failure: despite the open network path, the KDE Connect app fails to discover or pair with the device.
* Log Evidence: The internal KDE Connect app logs show the following error when the packet arrives: I LanLinkProvider: Discarding UDP packet from a non-local IP 

Conclusion: It appears v1.35.2 introduced a strict check in LanLinkProvider that discards packets from VPN interfaces (like tun0) because they are not recognized as "local" by the standard connectivity check. This logic seems to override the user's explicit intent when using "Add Device by IP."

Workaround: I have confirmed that downgrading to v1.34.3 immediately resolves the issue and allows the connection over Tailscale to succeed.
Comment 3 Matt 2026-02-08 14:43:12 UTC
(In reply to Albert Vaca Cintora from comment #1)
> Maybe this change affects your setup?
> https://invent.kde.org/network/kdeconnect-android/-/commit/
> 72881f8b04d280284b31ddd9810ee1c9a0fa8320
> 
> If that's the case you should see the new log messages though.

Yep, that's the one. Tailscale uses 100.64.0.0/10 — that's RFC 6598 space, which IANA specifically allocated for CGNAT and similar setups. Java's isSiteLocalAddress() only covers RFC 1918 (10.x, 172.16-31.x, 192.168.x), so the 100.64 range gets rejected.

Thing is, 100.64.0.0/10 is pretty widely used beyond just Tailscale. ZeroTier, Nebula, and a bunch of WireGuard setups sit in that range too. ISPs also stick customers behind CGNAT on these same addresses, so this could bite more people than just VPN users. Might be worth expanding the check to include RFC 6598, or making it something users can configure?
Comment 4 Matt 2026-02-08 15:55:27 UTC
I redact my statement on the other apps, Nebula,  Zerotier, etc. I can only confirm, at this time, that Tailscale is the only one affected, unless others with those apps say otherwise.
Comment 5 zocker.network 2026-02-08 20:58:00 UTC
FYI This issue is also (kind of) tracked on Tailscale’s GitHub starting at this comment: https://github.com/tailscale/tailscale/issues/14476#issuecomment-3844353335

I'm also affected by this issue, also using Tailscale, also by manually adding the Tailscale IPs / hostnames to the KDE Connect clients via config file / "add devices by IP" on desktop / Android resp..

I agree to Matt’s 2nd suggestion to add a setting for this, I assume, security feature filtering for local IPs only. Esp. because a) KDE Connect (seems to) use a TLS connection with TOFU authenticating both sides and b) there will be (advanced) setups where KDE Connect connections should be routed through some kind of VPN, be it device-to-device / site-to-site / and so on. Enabling this security feature by default IMO is fine because I think this will be sufficient most users. And I see that this increases the security as filtering for local IPs only should decrease the attack surface esp. on phones which may be confronted with connections using public IPs (e.g. via cellular connections).

Just in case, other ideas I had in my mind are, but which seem more complex & less secure when applied to all users:
2) allowing connections from IPs which are explicitly listed in the configs (but then this may require users to list them on both sides; and what about hostnames with multiple records)
3) only allowing connections from already paired devices (may be complex to implement; still allows for increased attack surface; requires "local" pairing first)

I would not just fix this for the 100.64.0.0/10 IP space because:
- There is IPv6 with its public & unique local addresses (ULA, fc00::/7). Site-to-Site VPNs between trusted local networks may use public IPv6s. And on the other side, depending on the context and/or network operator, ULAs might be routed across "untrusted" networks.
- some uncommon networks may use public IPv4 addresses
- maybe some users want/require KDE Connect connections via the internet
Comment 6 Linus Dierheimer 2026-02-09 16:53:20 UTC
Duplicate of https://bugs.kde.org/show_bug.cgi?id=515707
Comment 7 Linus Dierheimer 2026-02-09 17:00:11 UTC
(In reply to Linus Dierheimer from comment #6)
> Duplicate of https://bugs.kde.org/show_bug.cgi?id=515707

https://bugs.kde.org/show_bug.cgi?id=515566, copied the wrong tab....
Comment 8 Bug Janitor Service 2026-02-10 21:28:47 UTC
A possibly relevant merge request was started @ https://invent.kde.org/network/kdeconnect-android/-/merge_requests/621
Comment 9 Bug Janitor Service 2026-02-10 21:28:49 UTC
A possibly relevant merge request was started @ https://invent.kde.org/network/kdeconnect-android/-/merge_requests/621
Comment 10 Matt 2026-02-10 23:50:13 UTC
Thanks for the quick response on MR 621.

One thing I wanted to flag: in the duplicate bug 515566, Linus Dierheimer suspects their dormitory subnet (100.122.0.0/16) falls within the 100.64.0.0/10 range being allowed here. If so, that's a shared multi-tenant network. RFC 6598 explicitly distinguishes this range from RFC 1918 private address space — it was allocated for carrier-grade NAT where multiple subscribers share the same address block.

As zocker.network suggested in comment 5, would it make sense to have this be a user-facing toggle, off by default? That would cover VPN and CGNAT users who need it without broadening the filter for everyone else.

knyipab also raised an interesting point in comment 2 — the current behavior discards packets from addresses the user has explicitly entered via "Add device by IP." There might be a narrower fix there, though I don't know if the code architecture makes that straightforward.

Appreciate the work on this either way.
Comment 11 Kiril Vladimirov 2026-02-11 07:58:01 UTC
(In reply to Matt from comment #10)
> One thing I wanted to flag: in the duplicate bug 515566, Linus Dierheimer
> suspects their dormitory subnet (100.122.0.0/16) falls within the
> 100.64.0.0/10 range being allowed here. If so, that's a shared multi-tenant
> network. RFC 6598 explicitly distinguishes this range from RFC 1918 private
> address space — it was allocated for carrier-grade NAT where multiple
> subscribers share the same address block.

In theory yes. Not sure whether it's really used at all by carriers these days, though. I've never seen them used outside of corporate networks and lately Tailscale.

(In reply to Matt from comment #10)
> As zocker.network suggested in comment 5, would it make sense to have this
> be a user-facing toggle, off by default? That would cover VPN and CGNAT
> users who need it without broadening the filter for everyone else.

I feel that this setting will be tedious to explain. "Check this if you're using Tailscale"?
Love the idea, though as it would make the tailnet feel really like local network as before.

(In reply to Matt from comment #10)
> knyipab also raised an interesting point in comment 2 — the current behavior
> discards packets from addresses the user has explicitly entered via "Add
> device by IP." There might be a narrower fix there, though I don't know if
> the code architecture makes that straightforward.

This one is easy to be implemented. The custom device list is easily accessible where this check happens. Downsides:

- Pairing new devices over Tailscale would be tedious. The device simply disappears when you're using tailscale and it's not obvious that adding it manually by IP would work
- Tailscale also has dns resolving inside the tailnet (e.g. desktop.tail123456.ts.net). If we want to support devices added by hostnames in the custom device list, that would make things a bit more tedious

I still believe that we should just treat 100.64.0.0/10 as a local network, given that the real world treats it that way these days. Said that, if maintainers decide on any of the other two suggested ideas, I'm willing to submit a MR implementing them.