android, libtailscale: pass BuildConfig to Go code; use for DNS config

This commit wires up a method to allow the Tailscale Go backend to
obtain the build configuration, and then adds a new build configuration
to the build to control whether we fall back to the Google public DNS
servers if we can't determine the platform's DNS configuration.

This replaces the previous "IsPlayVersion" / "MaybeGoogle" check for
whether to use the DNS servers as fallbacks, to allow users to decide
this independently of what version of the Android app this is.

Updates tailscale/tailscale#13431

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
pull/495/head
Andrew Dunham 2 months ago
parent 283e1ebcd8
commit 45567146f4

@ -39,6 +39,14 @@ android {
targetSdkVersion 34
versionCode 241
versionName "1.73.114-t0970615b1-gab7ab737364"
// This setting, which defaults to 'true', will cause Tailscale to fall
// back to the Google DNS servers if it cannot determine what the
// operating system's DNS configuration is.
//
// Set it to false either here or in your local.properties file to
// disable this behaviour.
buildConfigField "boolean", "USE_GOOGLE_DNS_FALLBACK", getLocalProperty("tailscale.useGoogleDnsFallback", "true")
}
compileOptions {
@ -54,6 +62,7 @@ android {
jvmTarget = "17"
}
buildFeatures {
buildConfig true
compose true
}
composeOptions {
@ -66,9 +75,9 @@ android {
applicationTest {
initWith debug
manifestPlaceholders.leanbackRequired = false
buildConfigField "String", "GITHUB_USERNAME", "\"" + getLocalProperty("githubUsername")+"\""
buildConfigField "String", "GITHUB_PASSWORD", "\"" + getLocalProperty("githubPassword")+"\""
buildConfigField "String", "GITHUB_2FA_SECRET", "\"" + getLocalProperty("github2FASecret")+"\""
buildConfigField "String", "GITHUB_USERNAME", "\"" + getLocalProperty("githubUsername", "")+"\""
buildConfigField "String", "GITHUB_PASSWORD", "\"" + getLocalProperty("githubPassword", "")+"\""
buildConfigField "String", "GITHUB_2FA_SECRET", "\"" + getLocalProperty("github2FASecret", "")+"\""
}
debug {
manifestPlaceholders.leanbackRequired = false
@ -156,12 +165,12 @@ dependencies {
implementation("androidx.compose.ui:ui-tooling-preview")
}
def getLocalProperty(key) {
def getLocalProperty(key, defaultValue) {
try {
Properties properties = new Properties()
properties.load(project.file('local.properties').newDataInputStream())
return properties.getProperty(key)
return properties.getProperty(key) ?: defaultValue
} catch(Throwable ignored) {
return ""
return defaultValue
}
}

@ -38,6 +38,7 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import libtailscale.BuildConfig as GoBuildConfig
import libtailscale.Libtailscale
import java.io.File
import java.io.IOException
@ -311,6 +312,13 @@ class App : UninitializedApp(), libtailscale.AppContext, ViewModelStoreOwner {
}
}
// getBuildConfig implements the libtailscale.AppContext interface.
override fun getBuildConfig(): GoBuildConfig {
var buildConfig = GoBuildConfig()
buildConfig.useGoogleDNSFallback = BuildConfig.USE_GOOGLE_DNS_FALLBACK
return buildConfig
}
fun notifyPolicyChanged() {
app.notifyPolicyChanged()
}

@ -44,6 +44,9 @@ type App struct {
// appCtx is a global reference to the com.tailscale.ipn.App instance.
appCtx AppContext
// buildConfig is the build configuration for the app.
buildConfig *BuildConfig
store *stateStore
policyStore *syspolicyHandler
logIDPublicAtomic atomic.Pointer[logid.PublicID]
@ -97,7 +100,8 @@ type backend struct {
// when no nameservers are provided by Tailscale.
avoidEmptyDNS bool
appCtx AppContext
appCtx AppContext
buildConfig *BuildConfig
}
type settingsFunc func(*router.Config, *dns.OSConfig) error
@ -262,9 +266,10 @@ func (a *App) newBackend(dataDir, directFileRoot string, appCtx AppContext, stor
logf := logger.RusagePrefixLog(log.Printf)
b := &backend{
devices: newTUNDevices(),
settings: settings,
appCtx: appCtx,
devices: newTUNDevices(),
settings: settings,
appCtx: appCtx,
buildConfig: a.buildConfig,
}
var logID logid.PrivateID
logID.UnmarshalText([]byte("dead0000dead0000dead0000dead0000dead0000dead0000dead0000dead0000"))

@ -57,6 +57,12 @@ type AppContext interface {
// GetSyspolicyStringArrayValue returns the current string array value for the given system policy,
// expressed as a JSON string.
GetSyspolicyStringArrayJSONValue(key string) (string, error)
// GetBuildConfig gets the build configuration of the Android app.
//
// The returned BuildConfig should not change during the lifetime of
// the app.
GetBuildConfig() *BuildConfig
}
// IPNService corresponds to our IPNService in Java.
@ -166,3 +172,11 @@ func RequestVPN(service IPNService) {
func ServiceDisconnect(service IPNService) {
onDisconnect <- service
}
// BuildConfig is a struct that represents the build configuration of the
// Android application, as set in BuildConfig.java.
type BuildConfig struct {
// UseGoogleDNSFallback is whether to fall back to the Google public
// DNS servers if the platform's DNS servers cannot be determined.
UseGoogleDNSFallback bool
}

@ -287,7 +287,7 @@ func (b *backend) getDNSBaseConfig() (ret dns.OSConfig, _ error) {
// DNS config are lacking, and almost all Android phones use Google
// services anyway, so it's a reasonable default: it's an ecosystem the
// user has selected by having an Android device.
if len(ret.Nameservers) == 0 && b.appCtx.IsPlayVersion() {
if len(ret.Nameservers) == 0 && b.buildConfig.UseGoogleDNSFallback {
log.Printf("getDNSBaseConfig: none found; falling back to Google public DNS")
ret.Nameservers = append(ret.Nameservers, googleDNSServers...)
}

@ -38,6 +38,11 @@ func newApp(dataDir, directFileRoot string, appCtx AppContext) Application {
}
a.ready.Add(2)
// Get the build configuration, if any.
if bc := appCtx.GetBuildConfig(); bc != nil {
a.buildConfig = bc
}
a.store = newStateStore(a.appCtx)
a.policyStore = &syspolicyHandler{a: a}
netmon.RegisterInterfaceGetter(a.getInterfaces)

Loading…
Cancel
Save