proxy_linux.go 2.0 KB

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