github.com/sagernet/sing-box@v1.2.7/common/settings/proxy_linux.go (about)

     1  //go:build linux && !android
     2  
     3  package settings
     4  
     5  import (
     6  	"os"
     7  	"os/exec"
     8  	"strings"
     9  
    10  	"github.com/sagernet/sing-box/adapter"
    11  	"github.com/sagernet/sing/common"
    12  	E "github.com/sagernet/sing/common/exceptions"
    13  	F "github.com/sagernet/sing/common/format"
    14  	"github.com/sagernet/sing/common/shell"
    15  )
    16  
    17  var (
    18  	hasGSettings bool
    19  	sudoUser     string
    20  )
    21  
    22  func init() {
    23  	hasGSettings = common.Error(exec.LookPath("gsettings")) == nil
    24  	if os.Getuid() == 0 {
    25  		sudoUser = os.Getenv("SUDO_USER")
    26  	}
    27  }
    28  
    29  func runAsUser(name string, args ...string) error {
    30  	if os.Getuid() != 0 {
    31  		return shell.Exec(name, args...).Attach().Run()
    32  	} else if sudoUser != "" {
    33  		return shell.Exec("su", "-", sudoUser, "-c", F.ToString(name, " ", strings.Join(args, " "))).Attach().Run()
    34  	} else {
    35  		return E.New("set system proxy: unable to set as root")
    36  	}
    37  }
    38  
    39  func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
    40  	if !hasGSettings {
    41  		return nil, E.New("unsupported desktop environment")
    42  	}
    43  	err := runAsUser("gsettings", "set", "org.gnome.system.proxy.http", "enabled", "true")
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	if isMixed {
    48  		err = setGnomeProxy(port, "ftp", "http", "https", "socks")
    49  	} else {
    50  		err = setGnomeProxy(port, "http", "https")
    51  	}
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	err = runAsUser("gsettings", "set", "org.gnome.system.proxy", "use-same-proxy", F.ToString(isMixed))
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	err = runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "manual")
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return func() error {
    64  		return runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
    65  	}, nil
    66  }
    67  
    68  func setGnomeProxy(port uint16, proxyTypes ...string) error {
    69  	for _, proxyType := range proxyTypes {
    70  		err := runAsUser("gsettings", "set", "org.gnome.system.proxy."+proxyType, "host", "127.0.0.1")
    71  		if err != nil {
    72  			return err
    73  		}
    74  		err = runAsUser("gsettings", "set", "org.gnome.system.proxy."+proxyType, "port", F.ToString(port))
    75  		if err != nil {
    76  			return err
    77  		}
    78  	}
    79  	return nil
    80  }