diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 81619d8..0640d06 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + diff --git a/android/src/main/java/com/tailscale/ipn/App.java b/android/src/main/java/com/tailscale/ipn/App.java index 7a472d5..796b376 100644 --- a/android/src/main/java/com/tailscale/ipn/App.java +++ b/android/src/main/java/com/tailscale/ipn/App.java @@ -24,6 +24,9 @@ import android.content.pm.Signature; import android.provider.MediaStore; import android.provider.Settings; import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkRequest; import android.net.Uri; import android.net.VpnService; import android.view.View; @@ -77,6 +80,9 @@ public class App extends Application { private final static Handler mainHandler = new Handler(Looper.getMainLooper()); + public DnsConfig dns = new DnsConfig(this); + public DnsConfig getDnsConfigObj() { return this.dns; } + @Override public void onCreate() { super.onCreate(); // Load and initialize the Go library. @@ -90,13 +96,18 @@ public class App extends Application { } private void registerNetworkCallback() { - BroadcastReceiver connectivityChanged = new BroadcastReceiver() { - @Override public void onReceive(Context ctx, Intent intent) { - boolean noconn = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); - onConnectivityChanged(!noconn); + ConnectivityManager cMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); + cMgr.registerNetworkCallback(new NetworkRequest.Builder().build(), new ConnectivityManager.NetworkCallback() { + @Override + public void onLost(Network network) { + onConnectivityChanged(false); + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { + onConnectivityChanged(true); } - }; - registerReceiver(connectivityChanged, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); + }); } public void startVPN() { diff --git a/android/src/main/java/com/tailscale/ipn/DnsConfig.java b/android/src/main/java/com/tailscale/ipn/DnsConfig.java new file mode 100644 index 0000000..7a9696a --- /dev/null +++ b/android/src/main/java/com/tailscale/ipn/DnsConfig.java @@ -0,0 +1,360 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package com.tailscale.ipn; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.DhcpInfo; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.net.wifi.WifiManager; + +import java.lang.reflect.Method; + +import java.net.InetAddress; + +import java.util.ArrayList; +import java.util.List; + +// Tailscale DNS Config retrieval +// +// Tailscale's DNS support can either override the local DNS servers with a set of servers +// configured in the admin panel, or supplement the local DNS servers with additional +// servers for specific domains like example.com.beta.tailscale.net. In the non-override mode, +// we need to retrieve the current set of DNS servers from the platform. These will typically +// be the DNS servers received from DHCP. +// +// Importantly, after the Tailscale VPN comes up it will set a DNS server of 100.100.100.100 +// but we still want to retrieve the underlying DNS servers received from DHCP. If we roam +// from Wi-Fi to LTE, we want the DNS servers received from LTE. +// +// --------------------- Android 7 and later ----------------------------------------- +// +// ## getDnsConfigFromLinkProperties +// Android provides a getAllNetworks interface in the ConnectivityManager. We walk through +// each interface to pick the most appropriate one. +// - If there is an Ethernet interface active we use that. +// - If Wi-Fi is active we use that. +// - If LTE is active we use that. +// - We never use a VPN's DNS servers. That VPN is likely us. Even if not us, Android +// only allows one VPN at a time so a different VPN's DNS servers won't be available +// once Tailscale comes up. +// +// getAllNetworks() is used as the sole mechanism for retrieving the DNS config with +// Android 7 and later. +// +// --------------------- Releases older than Android 7 ------------------------------- +// +// We support Tailscale back to Android 5. Android versions 5 and 6 supply a getAllNetworks() +// implementation but it always returns an empty list. +// +// ## getDnsConfigFromLinkProperties with getActiveNetwork +// ConnectivityManager also supports a getActiveNetwork() routine, which Android 5 and 6 do +// return a value for. If Tailscale isn't up yet and we can get the Wi-Fi/LTE/etc DNS +// config using getActiveNetwork(), we use that. +// +// Once Tailscale is up, getActiveNetwork() returns tailscale0 with DNS server 100.100.100.100 +// and that isn't useful. So we try two other mechanisms: +// +// ## getDnsServersFromSystemProperties +// Android versions prior to 8 let us retrieve the actual system DNS servers from properties. +// Later Android versions removed the properties and only return an empty string. +// +// We check the net.dns1 - net.dns4 DNS servers. If Tailscale is up the DNS server will be +// 100.100.100.100, which isn't useful, but if we get something different we'll use that. +// +// getDnsServersFromSystemProperties can only retrieve the IPv4 or IPv6 addresses of the +// configured DNS servers. We also want to know the DNS Search Domains configured, but +// we have no way to retrieve this using these interfaces. We return an empty list of +// search domains. Sorry. +// +// ## getDnsServersFromNetworkInfo +// ConnectivityManager supports an older API called getActiveNetworkInfo to return the +// active network interface. It doesn't handle VPNs, so the interface will always be Wi-Fi +// or Cellular even if Tailscale is up. +// +// For Wi-Fi interfaces we retrieve the DHCP response from the WifiManager. For Cellular +// interfaces we check for properties populated by most of the radio drivers. +// +// getDnsServersFromNetworkInfo does not have a way to retrieve the DNS Search Domains, +// so we return an empty list. Additionally, these interfaces are so old that they only +// support IPv4. We can't retrieve IPv6 DNS server addresses this way. + +public class DnsConfig { + private Context ctx; + + public DnsConfig(Context ctx) { + this.ctx = ctx; + } + + // getDnsConfigAsString returns the current DNS configuration as a multiline string: + // line[0] DNS server addresses separated by spaces + // line[1] search domains separated by spaces + // + // For example: + // 8.8.8.8 8.8.4.4 + // example.com + // + // an empty string means the current DNS configuration could not be retrieved. + String getDnsConfigAsString() { + String s = getDnsConfigFromLinkProperties(); + if (!s.trim().isEmpty()) { + return s; + } + if (android.os.Build.VERSION.SDK_INT >= 23) { + // If ConnectivityManager.getAllNetworks() works, it is the + // authoritative mechanism and we rely on it. The other methods + // which follow involve more compromises. + return ""; + } + + s = getDnsServersFromSystemProperties(); + if (!s.trim().isEmpty()) { + return s; + } + return getDnsServersFromNetworkInfo(); + } + + // getDnsConfigFromLinkProperties finds the DNS servers for each Network interface + // returned by ConnectivityManager getAllNetworks().LinkProperties, and return the + // one that (heuristically) would be the primary DNS servers. + // + // on a Nexus 4 with Android 5.1 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 + // on a Nexus 7 with Android 6.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 + // on a Pixel 3a with Android 12.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1\nlocaldomain + // on a Pixel 3a with Android 12.0 on LTE: fd00:976a::9 fd00:976a::10 + // + // One odd behavior noted on Pixel3a with Android 12: + // With Wi-Fi already connected, starting Tailscale returned DNS servers 2602:248:7b4a:ff60::1 10.1.10.1 + // Turning off Wi-Fi and connecting LTE returned DNS servers fd00:976a::9 fd00:976a::10. + // Turning Wi-Fi back on return DNS servers: 10.1.10.1. The IPv6 DNS server is gone. + // This appears to be the ConnectivityManager behavior, not something we are doing. + // + // This implementation can work through Android 12 (SDK 30). In SDK 31 the + // getAllNetworks() method is deprecated and we'll need to implement a + // android.net.ConnectivityManager.NetworkCallback instead to monitor + // link changes and track which DNS server to use. + String getDnsConfigFromLinkProperties() { + ConnectivityManager cMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); + if (cMgr == null) { + return ""; + } + + Network[] networks = cMgr.getAllNetworks(); + if (networks == null) { + // Android 6 and before often returns an empty list, but we + // can try again with just the active network. + // + // Once Tailscale is connected, the active network will be Tailscale + // which will have 100.100.100.100 for its DNS server. We reject + // TYPE_VPN in getPreferabilityForNetwork, so it won't be returned. + Network active = cMgr.getActiveNetwork(); + if (active == null) { + return ""; + } + networks = new Network[]{active}; + } + + // getPreferabilityForNetwork returns an index into dnsConfigs from 0-3. + String[] dnsConfigs = new String[]{"", "", "", ""}; + for (Network network : networks) { + int idx = getPreferabilityForNetwork(cMgr, network); + if ((idx < 0) || (idx > 3)) { + continue; + } + + LinkProperties linkProp = cMgr.getLinkProperties(network); + NetworkCapabilities nc = cMgr.getNetworkCapabilities(network); + List dnsList = linkProp.getDnsServers(); + StringBuilder sb = new StringBuilder(""); + for (InetAddress ip : dnsList) { + sb.append(ip.getHostAddress() + " "); + } + + String d = linkProp.getDomains(); + if (d != null) { + sb.append("\n"); + sb.append(d); + } + + dnsConfigs[idx] = sb.toString(); + } + + // return the lowest index DNS config which exists. If an Ethernet config + // was found, return it. Otherwise if Wi-fi was found, return it. Etc. + for (String s : dnsConfigs) { + if (!s.trim().isEmpty()) { + return s; + } + } + + return ""; + } + + // getDnsServersFromSystemProperties returns DNS servers found in system properties. + // On Android versions prior to Android 8, we can directly query the DNS + // servers the system is using. More recent Android releases return empty strings. + // + // Once Tailscale is connected these properties will return 100.100.100.100, which we + // suppress. + // + // on a Nexus 4 with Android 5.1 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 + // on a Nexus 7 with Android 6.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 + // on a Pixel 3a with Android 12.0 on wifi: + // on a Pixel 3a with Android 12.0 on LTE: + // + // The list of DNS search domains does not appear to be available in system properties. + String getDnsServersFromSystemProperties() { + try { + Class SystemProperties = Class.forName("android.os.SystemProperties"); + Method method = SystemProperties.getMethod("get", String.class); + List servers = new ArrayList(); + for (String name : new String[]{"net.dns1", "net.dns2", "net.dns3", "net.dns4"}) { + String value = (String) method.invoke(null, name); + if (value != null && !value.isEmpty() && + !value.equals("100.100.100.100") && + !servers.contains(value)) { + servers.add(value); + } + } + return String.join(" ", servers); + } catch (Exception e) { + return ""; + } + } + + + String intToInetString(int hostAddress) { + return String.format("%d.%d.%d.%d", + (byte)(0xff & hostAddress), + (byte)(0xff & (hostAddress >> 8)), + (byte)(0xff & (hostAddress >> 16)), + (byte)(0xff & (hostAddress >> 24))); + } + + // getDnsServersFromNetworkInfo retrieves DNS servers using ConnectivityManager + // getActiveNetworkInfo() plus interface-specific mechanisms to retrieve the DNS servers. + // Only IPv4 DNS servers are supported by this mechanism, neither the WifiManager nor the + // interface-specific dns properties appear to populate IPv6 DNS server addresses. + // + // on a Nexus 4 with Android 5.1 on wifi: 10.1.10.1 + // on a Nexus 7 with Android 6.0 on wifi: 10.1.10.1 + // on a Pixel-3a with Android 12.0 on wifi: 10.1.10.1 + // on a Pixel-3a with Android 12.0 on LTE: + // + // The list of DNS search domains is not available in this way. + String getDnsServersFromNetworkInfo() { + ConnectivityManager cMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); + if (cMgr == null) { + return ""; + } + + NetworkInfo info = cMgr.getActiveNetworkInfo(); + if (info == null) { + return ""; + } + + Class SystemProperties; + Method method; + + try { + SystemProperties = Class.forName("android.os.SystemProperties"); + method = SystemProperties.getMethod("get", String.class); + } catch (Exception e) { + return ""; + } + + List servers = new ArrayList(); + + switch(info.getType()) { + case ConnectivityManager.TYPE_WIFI: + case ConnectivityManager.TYPE_WIMAX: + for (String name : new String[]{ + "net.wifi0.dns1", "net.wifi0.dns2", "net.wifi0.dns3", "net.wifi0.dns4", + "net.wlan0.dns1", "net.wlan0.dns2", "net.wlan0.dns3", "net.wlan0.dns4", + "net.eth0.dns1", "net.eth0.dns2", "net.eth0.dns3", "net.eth0.dns4", + "dhcp.wlan0.dns1", "dhcp.wlan0.dns2", "dhcp.wlan0.dns3", "dhcp.wlan0.dns4", + "dhcp.tiwlan0.dns1", "dhcp.tiwlan0.dns2", "dhcp.tiwlan0.dns3", "dhcp.tiwlan0.dns4"}) { + try { + String value = (String) method.invoke(null, name); + if (value != null && !value.isEmpty() && !servers.contains(value)) { + servers.add(value); + } + } catch (Exception e) { + continue; + } + } + + WifiManager wMgr = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE); + if (wMgr != null) { + DhcpInfo dhcp = wMgr.getDhcpInfo(); + if (dhcp.dns1 != 0) { + String value = intToInetString(dhcp.dns1); + if (value != null && !value.isEmpty() && !servers.contains(value)) { + servers.add(value); + } + } + if (dhcp.dns2 != 0) { + String value = intToInetString(dhcp.dns2); + if (value != null && !value.isEmpty() && !servers.contains(value)) { + servers.add(value); + } + } + } + return String.join(" ", servers); + case ConnectivityManager.TYPE_MOBILE: + case ConnectivityManager.TYPE_MOBILE_HIPRI: + for (String name : new String[]{ + "net.rmnet0.dns1", "net.rmnet0.dns2", "net.rmnet0.dns3", "net.rmnet0.dns4", + "net.rmnet1.dns1", "net.rmnet1.dns2", "net.rmnet1.dns3", "net.rmnet1.dns4", + "net.rmnet2.dns1", "net.rmnet2.dns2", "net.rmnet2.dns3", "net.rmnet2.dns4", + "net.rmnet3.dns1", "net.rmnet3.dns2", "net.rmnet3.dns3", "net.rmnet3.dns4", + "net.rmnet4.dns1", "net.rmnet4.dns2", "net.rmnet4.dns3", "net.rmnet4.dns4", + "net.rmnet5.dns1", "net.rmnet5.dns2", "net.rmnet5.dns3", "net.rmnet5.dns4", + "net.rmnet6.dns1", "net.rmnet6.dns2", "net.rmnet6.dns3", "net.rmnet6.dns4", + "net.rmnet7.dns1", "net.rmnet7.dns2", "net.rmnet7.dns3", "net.rmnet7.dns4", + "net.pdp0.dns1", "net.pdp0.dns2", "net.pdp0.dns3", "net.pdp0.dns4", + "net.pdpbr0.dns1", "net.pdpbr0.dns2", "net.pdpbr0.dns3", "net.pdpbr0.dns4"}) { + try { + String value = (String) method.invoke(null, name); + if (value != null && !value.isEmpty() && !servers.contains(value)) { + servers.add(value); + } + } catch (Exception e) { + continue; + } + + } + } + + return ""; + } + + // getPreferabilityForNetwork is a utility routine which implements a priority for + // different types of network transport, used in a heuristic to pick DNS servers to use. + int getPreferabilityForNetwork(ConnectivityManager cMgr, Network network) { + NetworkCapabilities nc = cMgr.getNetworkCapabilities(network); + + if (nc == null) { + return -1; + } + if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { + // tun0 has both VPN and WIFI set, have to check VPN first and return. + return -1; + } + + if (nc.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + return 0; + } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + return 1; + } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return 2; + } else { + return 3; + } + } +} diff --git a/cmd/tailscale/backend.go b/cmd/tailscale/backend.go index d9efc30..bced41f 100644 --- a/cmd/tailscale/backend.go +++ b/cmd/tailscale/backend.go @@ -11,6 +11,7 @@ import ( "net/http" "path/filepath" "reflect" + "strings" "time" "github.com/tailscale/tailscale-android/jni" @@ -23,8 +24,10 @@ import ( "tailscale.com/logtail" "tailscale.com/logtail/filch" "tailscale.com/net/dns" + "tailscale.com/net/tsdial" "tailscale.com/smallzstd" "tailscale.com/types/logger" + "tailscale.com/util/dnsname" "tailscale.com/wgengine" "tailscale.com/wgengine/router" ) @@ -41,7 +44,8 @@ type backend struct { // when no nameservers are provided by Tailscale. avoidEmptyDNS bool - jvm *jni.JVM + jvm *jni.JVM + appCtx jni.Object } type settingsFunc func(*router.Config, *dns.OSConfig) error @@ -58,19 +62,27 @@ const ( loginMethodWeb = "web" ) -var fallbackNameservers = []netaddr.IP{netaddr.IPv4(8, 8, 8, 8), netaddr.IPv4(8, 8, 4, 4)} +// googleDnsServers are used on ChromeOS, where an empty VpnBuilder DNS setting results +// in erasing the platform DNS servers. The developer docs say this is not supposed to happen, +// but nonetheless it does. +var googleDnsServers = []netaddr.IP{netaddr.MustParseIP("8.8.8.8"), netaddr.MustParseIP("8.8.4.4"), + netaddr.MustParseIP("2001:4860:4860::8888"), netaddr.MustParseIP("2001:4860:4860::8844"), +} // errVPNNotPrepared is used when VPNService.Builder.establish returns // null, either because the VPNService is not yet prepared or because // VPN status was revoked. var errVPNNotPrepared = errors.New("VPN service not prepared or was revoked") -func newBackend(dataDir string, jvm *jni.JVM, store *stateStore, settings settingsFunc) (*backend, error) { +func newBackend(dataDir string, jvm *jni.JVM, appCtx jni.Object, store *stateStore, + settings settingsFunc) (*backend, error) { + logf := logger.RusagePrefixLog(log.Printf) b := &backend{ jvm: jvm, devices: newTUNDevices(), settings: settings, + appCtx: appCtx, } var logID logtail.PrivateID logID.UnmarshalText([]byte("dead0000dead0000dead0000dead0000dead0000dead0000dead0000dead0000")) @@ -90,19 +102,23 @@ func newBackend(dataDir string, jvm *jni.JVM, store *stateStore, settings settin logID.UnmarshalText([]byte(storedLogID)) } b.SetupLogs(dataDir, logID) + + dialer := new(tsdial.Dialer) cb := &router.CallbackRouter{ - SetBoth: b.setCfg, - SplitDNS: false, // TODO: https://github.com/tailscale/tailscale/issues/1695 + SetBoth: b.setCfg, + SplitDNS: false, + GetBaseConfigFunc: b.getDNSBaseConfig, } engine, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ Tun: b.devices, Router: cb, DNS: cb, + Dialer: dialer, }) if err != nil { return nil, fmt.Errorf("runBackend: NewUserspaceEngine: %v", err) } - local, err := ipnlocal.NewLocalBackend(logf, logID.Public().String(), store, engine) + local, err := ipnlocal.NewLocalBackend(logf, logID.Public().String(), store, dialer, engine) if err != nil { engine.Close() return nil, fmt.Errorf("runBackend: NewLocalBackend: %v", err) @@ -170,7 +186,7 @@ func (b *backend) updateTUN(service jni.Object, rcfg *router.Config, dcfg *dns.O if dcfg != nil { nameservers := dcfg.Nameservers if b.avoidEmptyDNS && len(nameservers) == 0 { - nameservers = fallbackNameservers + nameservers = googleDnsServers } for _, dns := range nameservers { _, err = jni.CallObjectMethod(env, @@ -324,3 +340,89 @@ func (b *backend) SetupLogs(logDir string, logID logtail.PrivateID) { log.Printf("SetupLogs: filch setup failed: %v", filchErr) } } + +// We log the result of each of the DNS configuration discovery mechanisms, as we're +// expecting a long tail of obscure Android devices with interesting behavior. +func (b *backend) logDNSConfigMechanisms() { + err := jni.Do(b.jvm, func(env *jni.Env) error { + cls := jni.GetObjectClass(env, b.appCtx) + m := jni.GetMethodID(env, cls, "getDnsConfigObj", "()Lcom/tailscale/ipn/DnsConfig;") + dns, err := jni.CallObjectMethod(env, b.appCtx, m) + if err != nil { + return fmt.Errorf("getDnsConfigObj JNI: %v", err) + } + dnsCls := jni.GetObjectClass(env, dns) + + for _, impl := range []string{"getDnsConfigFromLinkProperties", + "getDnsServersFromSystemProperties", + "getDnsServersFromNetworkInfo"} { + + m = jni.GetMethodID(env, dnsCls, impl, "()Ljava/lang/String;") + n, err := jni.CallObjectMethod(env, dns, m) + baseConfig := jni.GoString(env, jni.String(n)) + if err != nil { + log.Printf("%s JNI: %v", impl, err) + } else { + oneLine := strings.Replace(baseConfig, "\n", ";", -1) + log.Printf("%s: %s", impl, oneLine) + } + } + return nil + }) + if err != nil { + log.Printf("logDNSConfigMechanisms: %v", err) + } +} + +func (b *backend) getPlatformDNSConfig() string { + var baseConfig string + err := jni.Do(b.jvm, func(env *jni.Env) error { + cls := jni.GetObjectClass(env, b.appCtx) + m := jni.GetMethodID(env, cls, "getDnsConfigObj", "()Lcom/tailscale/ipn/DnsConfig;") + dns, err := jni.CallObjectMethod(env, b.appCtx, m) + if err != nil { + return fmt.Errorf("getDnsConfigObj: %v", err) + } + dnsCls := jni.GetObjectClass(env, dns) + m = jni.GetMethodID(env, dnsCls, "getDnsConfigAsString", "()Ljava/lang/String;") + n, err := jni.CallObjectMethod(env, dns, m) + baseConfig = jni.GoString(env, jni.String(n)) + return err + }) + if err != nil { + log.Printf("getPlatformDNSConfig JNI: %v", err) + return "" + } + return baseConfig +} + +func (b *backend) getDNSBaseConfig() (dns.OSConfig, error) { + b.logDNSConfigMechanisms() + baseConfig := b.getPlatformDNSConfig() + lines := strings.Split(baseConfig, "\n") + if len(lines) == 0 { + return dns.OSConfig{}, nil + } + + config := dns.OSConfig{} + addrs := strings.Trim(lines[0], " \n") + for _, addr := range strings.Split(addrs, " ") { + ip, err := netaddr.ParseIP(addr) + if err == nil { + config.Nameservers = append(config.Nameservers, ip) + } + } + + if len(lines) > 1 { + for _, s := range strings.Split(strings.Trim(lines[1], " \n"), " ") { + domain, err := dnsname.ToFQDN(s) + if err != nil { + log.Printf("getDNSBaseConfig: unable to parse %q: %v", s, err) + continue + } + config.SearchDomains = append(config.SearchDomains, domain) + } + } + + return config, nil +} diff --git a/cmd/tailscale/main.go b/cmd/tailscale/main.go index 72f8c1d..822a3cc 100644 --- a/cmd/tailscale/main.go +++ b/cmd/tailscale/main.go @@ -256,7 +256,7 @@ func (a *App) runBackend() error { } configs := make(chan configPair) configErrs := make(chan error) - b, err := newBackend(appDir, a.jvm, a.store, func(rcfg *router.Config, dcfg *dns.OSConfig) error { + b, err := newBackend(appDir, a.jvm, a.appCtx, a.store, func(rcfg *router.Config, dcfg *dns.OSConfig) error { if rcfg == nil { return nil } diff --git a/go.mod b/go.mod index e114679..e0e0fca 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 golang.zx2c4.com/wireguard v0.0.0-20211116201604-de7c702ace45 inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 - tailscale.com v1.1.1-0.20211125200034-e24f89efad22 + tailscale.com v1.1.1-0.20211206024951-b3810e3b1b93 ) require ( diff --git a/go.sum b/go.sum index 39cd6bd..e8c6bbc 100644 --- a/go.sum +++ b/go.sum @@ -636,5 +636,19 @@ nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= software.sslmate.com/src/go-pkcs12 v0.0.0-20180114231543-2291e8f0f237 h1:iAEkCBPbRaflBgZ7o9gjVUuWuvWeV4sytFWg9o+Pj2k= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +tailscale.com v1.1.1-0.20211103210016-0532eb30dbba h1:UJfsplfXBBJb2d2Sj3G+Uwq4cZqNQUOM04K+aWavumM= +tailscale.com v1.1.1-0.20211103210016-0532eb30dbba/go.mod h1:KpeWAuozkb9G2RharSOmrtLh8nfUsJNI9Ml1hUSjk1U= +tailscale.com v1.1.1-0.20211108154433-eccc2ac6ee91 h1:cfV2IJg5dc6BfxzX3W+GAZ/veXgvuoKUxHyuxrXM4iE= +tailscale.com v1.1.1-0.20211108154433-eccc2ac6ee91/go.mod h1:+3SVDKPct8EqzwfYDQ3RpRwwBodKP7kNs49WXoM7wiw= +tailscale.com v1.1.1-0.20211109021509-d6dde5a1aca7 h1:gfDJ/zqR+hPeL3JCOY6akU2VHvmRz+lv3OpwkPgBbFA= +tailscale.com v1.1.1-0.20211109021509-d6dde5a1aca7/go.mod h1:+3SVDKPct8EqzwfYDQ3RpRwwBodKP7kNs49WXoM7wiw= +tailscale.com v1.1.1-0.20211116231549-773af7292b95 h1:gyWNQkqxuUbdumPC5XH5rGRQG1iomkTblYVC8A7L7Jw= +tailscale.com v1.1.1-0.20211116231549-773af7292b95/go.mod h1:XzG4o2vtYFkVvmJWPaTGSaOzqlKSRx2WU+aJbrxaVE0= +tailscale.com v1.1.1-0.20211119125307-221a18f4f07c h1:XVV1hEdNdLT2md2XkTBtD1oFBSPs/A/FcDZrRxbuN9A= +tailscale.com v1.1.1-0.20211119125307-221a18f4f07c/go.mod h1:XzG4o2vtYFkVvmJWPaTGSaOzqlKSRx2WU+aJbrxaVE0= tailscale.com v1.1.1-0.20211125200034-e24f89efad22 h1:BCCsNwOxI+Oo4E7GCWcIrOCfVmyYkQDI/iYBYyj/kpA= tailscale.com v1.1.1-0.20211125200034-e24f89efad22/go.mod h1:i+JH48j9W4tCWOzunNJfrEZcZRQgavPQXO57oh3cwGE= +tailscale.com v1.1.1-0.20211205233917-7f5171030f07 h1:3zeQUManu3redjOkkcvoa5nCPD8Q3hZV0B5RvGiNK28= +tailscale.com v1.1.1-0.20211205233917-7f5171030f07/go.mod h1:L3DiIyJXiHO4r8/6y+G2axGMdYAI/VERGMhGftHfP4U= +tailscale.com v1.1.1-0.20211206024951-b3810e3b1b93 h1:7AWRaSMyCYl8/wAruUelHPnFSqK4hSRwXUFHG9lDRbY= +tailscale.com v1.1.1-0.20211206024951-b3810e3b1b93/go.mod h1:L3DiIyJXiHO4r8/6y+G2axGMdYAI/VERGMhGftHfP4U=