proxy_darwin.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package settings
  2. import (
  3. "strings"
  4. "github.com/sagernet/sing-box/adapter"
  5. "github.com/sagernet/sing-tun"
  6. "github.com/sagernet/sing/common"
  7. E "github.com/sagernet/sing/common/exceptions"
  8. F "github.com/sagernet/sing/common/format"
  9. "github.com/sagernet/sing/common/x/list"
  10. )
  11. type systemProxy struct {
  12. monitor tun.DefaultInterfaceMonitor
  13. interfaceName string
  14. element *list.Element[tun.DefaultInterfaceUpdateCallback]
  15. port uint16
  16. isMixed bool
  17. }
  18. func (p *systemProxy) update() error {
  19. newInterfaceName := p.monitor.DefaultInterfaceName()
  20. if p.interfaceName == newInterfaceName {
  21. return nil
  22. }
  23. if p.interfaceName != "" {
  24. _ = p.unset()
  25. }
  26. p.interfaceName = newInterfaceName
  27. interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
  28. if err != nil {
  29. return err
  30. }
  31. if p.isMixed {
  32. err = common.Exec("networksetup", "-setsocksfirewallproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port)).Attach().Run()
  33. }
  34. if err == nil {
  35. err = common.Exec("networksetup", "-setwebproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port)).Attach().Run()
  36. }
  37. if err == nil {
  38. err = common.Exec("networksetup", "-setsecurewebproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port)).Attach().Run()
  39. }
  40. return err
  41. }
  42. func (p *systemProxy) unset() error {
  43. interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
  44. if err != nil {
  45. return err
  46. }
  47. if p.isMixed {
  48. err = common.Exec("networksetup", "-setsocksfirewallproxystate", interfaceDisplayName, "off").Attach().Run()
  49. }
  50. if err == nil {
  51. err = common.Exec("networksetup", "-setwebproxystate", interfaceDisplayName, "off").Attach().Run()
  52. }
  53. if err == nil {
  54. err = common.Exec("networksetup", "-setsecurewebproxystate", interfaceDisplayName, "off").Attach().Run()
  55. }
  56. return err
  57. }
  58. func getInterfaceDisplayName(name string) (string, error) {
  59. content, err := common.Exec("networksetup", "-listallhardwareports").Read()
  60. if err != nil {
  61. return "", err
  62. }
  63. for _, deviceSpan := range strings.Split(string(content), "Ethernet Address") {
  64. if strings.Contains(deviceSpan, "Device: "+name) {
  65. substr := "Hardware Port: "
  66. deviceSpan = deviceSpan[strings.Index(deviceSpan, substr)+len(substr):]
  67. deviceSpan = deviceSpan[:strings.Index(deviceSpan, "\n")]
  68. return deviceSpan, nil
  69. }
  70. }
  71. return "", E.New(name, " not found in networksetup -listallhardwareports")
  72. }
  73. func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
  74. interfaceMonitor := router.InterfaceMonitor()
  75. if interfaceMonitor == nil {
  76. return nil, E.New("missing interface monitor")
  77. }
  78. proxy := &systemProxy{
  79. monitor: interfaceMonitor,
  80. port: port,
  81. isMixed: isMixed,
  82. }
  83. err := proxy.update()
  84. if err != nil {
  85. return nil, err
  86. }
  87. proxy.element = interfaceMonitor.RegisterCallback(proxy.update)
  88. return func() error {
  89. interfaceMonitor.UnregisterCallback(proxy.element)
  90. return proxy.unset()
  91. }, nil
  92. }