mirror of
https://github.com/tailscale/tailscale.git
synced 2026-09-13 06:19:11 -04:00
Android doesn't have /etc/resolv.conf. This causes problems for people running GOOS=linux binaries (or GOOS=android binaries without cgo, so they don't use Android's bionic libc) in Termux, adb shell, etc. (Go binaries built with cgo use bionic on Android: golang/go#10714) 16 years ago when I was on the Android team I added a system-wide DNS cache (dnsproxyd) and made bionic query that, so each Android app wasn't doing its own DNS resolution. That interface was never meant to be stable, and I thought that code would be surely dead by now 16 years later, but apparently it lives on, and is more stable now: both empirically (time, ossification?), and because of how Android's split system updates work nowadays, the dnsproxyd lives on the other side of bionic, so they seem to keep it pretty stable. The old bionic<->dnsproxyd APIs I added 16 years ago are still there, but 8 years ago it got some additional APIs to query by a DNS packet instead. So use it! If we find ourselves on Android and without libc access (and because we don't want to pull in ebitengine/purego with all its side effects), just query the DNS server like bionic does. This can be disabled in Linux binaries with ts_omit_androiddns. Old links: LineageOS/android_system_netd@007e987fee https://android.googlesource.com/platform/system/netd/+/007e987fee7e815e0c4bc820f434a632b7a69a9d ("DNS proxy thread in netd.") aosp-mirror/platform_bionic@a1dbf0b453 https://android.googlesource.com/platform/bionic/+/a1dbf0b453801620565e5911f354f82706b0200d ("DNS proxy: the start. proxies getaddrinfo calls.") Back then I found it cleaner to proxy at the getaddrinfo level rather than speak in terms of DNS packets. The raw-packet resnsend command I use here came eight years later, added in November 2018 for Android 10's android_res_nsend NDK API: LineageOS/android_system_netd@c0c818f448 https://android.googlesource.com/platform/system/netd/+/c0c818f448efa90ab1f9b1733fb86c5e22fb894c ("Add resNetworkSend cmd in DnsProxyListener") Android 10 (codename Q, API level 29, released September 2019) is therefore the minimum OS version for this to work. I verified this against the DnsResolver module on an Android 13 emulator with SELinux enforcing, from the shell UID, with both a pure Go GOOS=android binary and a static GOOS=linux binary: raw queries, NXDOMAIN handling, the runtime Android detection, and a tailcat binary reaching DERP with lookups visible in the daemon's logcat output, some served from my 2010 DNS cache. Updates #21129 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I0d63763e255a077e4e5745b3e64ba0d78dab6d69 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>