Add mobile sandbox optimizations for v1.5.3

- Skip systemd-resolved initialization on Android (ChromeOS crash fix)
- Skip system DNS discovery commands on iOS mobile (sandbox restrictions)
- Skip route-based DNS discovery on Android
- Skip systemd resolver on Android
- Add mobile platform checks to prevent sandbox access violations

These changes ensure ctrld works correctly in mobile sandboxed environments
where system commands and file access are restricted.
This commit is contained in:
Ginder Singh
2026-08-05 00:39:42 +07:00
committed by Cuong Manh Le
parent 8ebe911b1a
commit 959f49dae3
3 changed files with 41 additions and 0 deletions
+3
View File
@@ -14,6 +14,9 @@ import (
)
func init() {
if isAndroid() {
return
}
if r, err := newLoopbackOSConfigurator(); err == nil {
useSystemdResolved = r.Mode() == "systemd-resolved"
}
+22
View File
@@ -11,6 +11,7 @@ import (
"net"
"os/exec"
"regexp"
"runtime"
"slices"
"strings"
"time"
@@ -25,6 +26,12 @@ func dnsFns() []dnsFn {
func getDNSFromScutil() []string {
logger := *ProxyLogger.Load()
// Skip scutil on mobile platforms - not available in sandbox
if isMobile() {
Log(context.Background(), logger.Debug(), "skipping scutil DNS discovery on mobile platform")
return nil
}
const (
maxRetries = 10
retryInterval = 100 * time.Millisecond
@@ -89,6 +96,11 @@ func getDNSFromScutil() []string {
}
func getDHCPNameservers(iface string) ([]string, error) {
// Skip ipconfig on mobile platforms - not available in sandbox
if isMobile() {
return nil, fmt.Errorf("ipconfig not available on mobile")
}
// Run the ipconfig command for the given interface.
cmd := exec.Command("ipconfig", "getpacket", iface)
output, err := cmd.Output()
@@ -201,6 +213,11 @@ func getAllDHCPNameservers() []string {
}
func patchNetIfaceName(iface *net.Interface) (bool, error) {
// Skip networksetup on mobile platforms - not available in sandbox
if isMobile() {
return false, nil
}
b, err := exec.Command("networksetup", "-listnetworkserviceorder").Output()
if err != nil {
return false, err
@@ -234,3 +251,8 @@ func networkServiceName(ifaceName string, r io.Reader) string {
}
return ""
}
// isMobile reports whether the current OS is a mobile platform.
func isMobile() bool {
return runtime.GOOS == "ios"
}
+16
View File
@@ -7,6 +7,7 @@ import (
"net"
"net/netip"
"os"
"runtime"
"strings"
"tailscale.com/net/netmon"
@@ -24,6 +25,11 @@ func dnsFns() []dnsFn {
}
func dns4() []string {
// Skip route-based DNS discovery on Android
if runtime.GOOS == "android" {
return nil
}
f, err := os.Open(v4RouteFile)
if err != nil {
return nil
@@ -64,6 +70,11 @@ func dns4() []string {
}
func dns6() []string {
// Skip route-based DNS discovery on Android
if runtime.GOOS == "android" {
return nil
}
f, err := os.Open(v6RouteFile)
if err != nil {
return nil
@@ -98,6 +109,11 @@ func dns6() []string {
}
func dnsFromSystemdResolver() []string {
// Skip systemd resolver on Android
if runtime.GOOS == "android" {
return nil
}
c, err := resolvconffile.ParseFile("/run/systemd/resolve/resolv.conf")
if err != nil {
return nil