Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android API level 30 breaks interface address discovery #1628

Closed
bt90 opened this issue Mar 26, 2021 · 18 comments · Fixed by syncthing/syncthing#9087
Closed

Android API level 30 breaks interface address discovery #1628

bt90 opened this issue Mar 26, 2021 · 18 comments · Fixed by syncthing/syncthing#9087

Comments

@bt90
Copy link
Contributor

bt90 commented Mar 26, 2021

API level 30(Android 11) will be mandatory starting November 2021 for apps on the PlayStore but seems to break golangs interface address discovery: golang/go#40569

This seems to be an intended privacy related change which directly affects how golangs stdlib retrieves addresses for an interface:

  • NetworkInterface.getHardwareAddress() returns null for every interface.
  • Apps cannot use the bind() function on NETLINK_ROUTE sockets.
  • The ip command does not return information about interfaces.
  • Apps cannot send RTM_GETLINK messages.

Source: https://developer.android.com/training/articles/user-data-ids#mac-11-plus

@bt90
Copy link
Contributor Author

bt90 commented Mar 26, 2021

Related: Catfriend1/syncthing-android#735

@imsodin
Copy link
Member

imsodin commented Feb 15, 2022

Golang issue on the same problem: golang/go#40569

There's a go android app (tailscale) which implemented this functionality in java and created bindings for their go code: tailscale/tailscale-android#21
Probably doable to adobt that, but definitely not trivial. And nothing I have time to investigate at the moment - contributions welcome.

@bt90
Copy link
Contributor Author

bt90 commented Feb 15, 2022

We already have a wrapper which is able to access this APIs. It's probably easier to leverage our REST API and allow external sources to feed syncthing with discovered IPs.

@imsodin
Copy link
Member

imsodin commented Feb 15, 2022

Maybe there's also potential there - however my limited testing shows that it can still receive local announcements. The problem here is the other way around: Syncthing can't get it's own address to announce that. There's no rest endpoint to do that (and that would be kind of strange).

@calmh
Copy link
Member

calmh commented Feb 15, 2022

We could have an endpoint to set extra external addresses for announcement though, in addition to one populating the discovery cache. I could even see other potential uses for it (peeps running it in k8s behind a load balancer etc).

But both local and global discovery take the source of the packets as the address if none is given, that should work for most cases on mobile as well? We just lose out on announcing our LAN addresses...

@bt90
Copy link
Contributor Author

bt90 commented Feb 15, 2022

It would be really nice if the wrapper could add (LAN) addresses to Syncthing which are in turn used for local and global announcements.

@bt90
Copy link
Contributor Author

bt90 commented Feb 16, 2022

@Catfriend1 what's your take on this? I know the official wrapper and the fork are somewhat independent but the REST API would be a common denominator in this case.

@Catfriend1
Copy link
Contributor

@bt90 In which way should we add addresses to Syncthing (which, from where, to where)? The fork allows for discovery by listening to some other syncthing on the network calling out to the phone. But actively sending won't work because of Android restrictions, I'm not sure if doing this from the wrapper would be possible.

@bt90
Copy link
Contributor Author

bt90 commented Feb 16, 2022

I think we need to separate two different concerns here:

  • IP address discovery
  • local announcement

Currently the Syncthing process isn't able to retrieve the LAN IPs assigned to the network interface of the phone. This deterioates connectivity if only Android devices are involved as they can only establish global or relay connections.

Broadcast problems are unfortunate but at least could be worked around with global discovery if the aformentioned IP discovery works.

@Atrate
Copy link

Atrate commented Apr 19, 2022

For anyone struggling: running syncthing as root on Android is a workaround, but please remember that it's very inadvisable.

Maybe the IP address discovery issue could be partially worked around if Syncthing detected that there's an ip binary/symlink available (provided by e.g. Busybox (I tested that binary in a terminal and it returned everything needed, without root))? Of course, this still requires a rooted phone, but doesn't require Syncthing to run as root on its own. Note that this is still just a workaround, not a solution for most users.

@StephenCleary
Copy link

Alternative workaround, which I prefer over rooting:

  1. Give one (or more) of your devices a reserved DHCP address, e.g., 192.168.0.231.
  2. On your other devices, update the addresses field for that device to use QUIC specifying that reserved DHCP address, e.g., quic://192.168.0.231 instead of default.

This turns discovery off completely.

@anonymous-user
Copy link

For some reason using quic:// did not work for me but tcp4:// did. But at least it works now. Thanks.

@StephenCleary
Copy link

Did some research this morning, and it seems to me that the best way forward is to adopt the tailscale workaround, which uses the higher-level APIs recommended by the Android docs. Is it just lack of time preventing this from being addressed?

The workarounds are fine for home networks, but I'm currently traveling with two Android devices and using ST for syncing travel plans/documents The hotel wifis tend to disallow UPnP, so even global discovery doesn't work. Of course I can still do the workarounds, but I have to redo them each time we return to the hotel which is tedious. Not complaining; just describing a use case. ;)

If this is still open after my vacation, I could contribute a PR.

@imsodin
Copy link
Member

imsodin commented Jun 10, 2022

They are using java bindings in go. So the difficult thing will be setting that up. My first reaction would be to try and keep it out of syncthing/syncthing, i.e. likely have a branch/patch-set adding the android/java stuff to be used in syncthing-android. You are totally welcome at giving it a go, please ask questions and write about plans whenever something comes up.

@AudriusButkevicius
Copy link
Member

It's probably easier to do it the other way around, build syncthing as a dynamic library. Eitherway, both of these are massive "weeks of effort" undertakings.

@imsodin
Copy link
Member

imsodin commented Jun 10, 2022

Even easier is to implement discovery in java libraries and use the rest api to configure devices with the discovered addresses.

@bt90
Copy link
Contributor Author

bt90 commented Sep 9, 2023

I'm testing a different approach in syncthing/syncthing#9087

@bt90
Copy link
Contributor Author

bt90 commented Sep 12, 2023

golang/go#61089 might solve our remaining problems on Android but so far local discovery should work with next syncthing-android release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants