Hi,
We’ve recently fixed the interface address discovery on Android by using the “anet” go library. Now there’s one problem left with the NAT-PMP feature of SyncthingNative. Android 14+ deny native code to read /proc/net/route. This approach is used by SyncthingNative in “lib/pmp.go:34” using the go lib “GitHub - jackpal/gateway: A golang library for discovering the address of a LAN gateway.”:
ip, err = gateway.DiscoverGateway()
I’ve tried to fix it in jackpal/gateway but could not find a solution. Multiple approaches don’t work from Android 14+, e.g. “ip route show”, “ip route get 8.8.8.8”, “cat /proc/net/…” or fake-binding a socket and reading out the info.
Android 14+ only lets java code get the gateway IPv4 address which is used in SynchtingNative’s NAT-PMP feature.
So I’ve added the java code to the wrapper, got the router IP address and feeded it to SynchtingNative by setting the env var “ANDROID_NET_GATEWAY_IPV4”.
This revives the NAT feature:
[Z36WU] INFO: Detected 1 NAT service
Function used based on the v2-main of SyncthingNative was:
func Discover(ctx context.Context, renewal, timeout time.Duration) []nat.Device {
var ip net.IP
err := svcutil.CallWithContext(ctx, func() error {
var err error
ip, err = gateway.DiscoverGateway()
if err != nil {
// Fails on Android 14+ due to permission denied error when reading
// /proc/net/route. The wrapper may give a hint then because it is
// able to discover the gateway from java code.
if v := os.Getenv("ANDROID_NET_GATEWAY_IPV4"); v != "" {
ip = net.ParseIP(v)
l.Debugln("Using gateway IP hint from env var ANDROID_NET_GATEWAY_IPV4", ip)
return nil
}
}
return err
})
if err != nil {
l.Debugln("Failed to discover gateway", err)
return nil
}
if ip == nil || ip.IsUnspecified() {
return nil
}
(...)
Would you be fine with that workaround if I open a PR to Syncthing’s go code? It’s again a hacky workaround, but I personally think something lightweight is better than disabling the NAT feature completely for Android 14+.
What’s your opinion on this?
Should I also try to do the more-complicated-looking JNI binding from go code to java code?
More refs/reading on this:
- [Bug] NAT PMP denied by Android 10+ · Issue #1514 · Catfriend1/syncthing-android · GitHub
- Fix discover default gateway on Android (fixes #45) by Catfriend1 · Pull Request #46 · jackpal/gateway · GitHub
- Discover default gateway on Android using "/proc/net/route" fails with "access denied" · Issue #45 · jackpal/gateway · GitHub
- draft: fix(pmp): workaround native code denied to discover gateway ipv4 addr on Android 14+ by Catfriend1 · Pull Request #10204 · syncthing/syncthing · GitHub