proxy_linux.go 2.0 KB

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