sing-box/common/settings/proxy_darwin.go

98 lines
2.9 KiB
Go
Raw Normal View History

2022-08-04 14:01:20 +00:00
package settings
import (
"net/netip"
2022-08-04 14:01:20 +00:00
"strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-tun"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
2023-03-13 03:31:36 +00:00
"github.com/sagernet/sing/common/shell"
2022-08-04 14:01:20 +00:00
"github.com/sagernet/sing/common/x/list"
)
type systemProxy struct {
monitor tun.DefaultInterfaceMonitor
interfaceName string
element *list.Element[tun.DefaultInterfaceUpdateCallback]
port uint16
isMixed bool
}
2023-07-23 06:42:19 +00:00
func (p *systemProxy) update(event int) {
newInterfaceName := p.monitor.DefaultInterfaceName(netip.IPv4Unspecified())
2022-08-04 14:01:20 +00:00
if p.interfaceName == newInterfaceName {
2023-07-23 06:42:19 +00:00
return
2022-08-04 14:01:20 +00:00
}
if p.interfaceName != "" {
_ = p.unset()
}
p.interfaceName = newInterfaceName
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
if err != nil {
2023-07-23 06:42:19 +00:00
return
2022-08-04 14:01:20 +00:00
}
if p.isMixed {
2023-03-13 03:31:36 +00:00
err = shell.Exec("networksetup", "-setsocksfirewallproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port)).Attach().Run()
2022-08-04 14:01:20 +00:00
}
if err == nil {
2023-03-13 03:31:36 +00:00
err = shell.Exec("networksetup", "-setwebproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port)).Attach().Run()
2022-08-04 14:01:20 +00:00
}
if err == nil {
2023-07-23 06:42:19 +00:00
_ = shell.Exec("networksetup", "-setsecurewebproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port)).Attach().Run()
2022-08-04 14:01:20 +00:00
}
2023-07-23 06:42:19 +00:00
return
2022-08-04 14:01:20 +00:00
}
func (p *systemProxy) unset() error {
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
if err != nil {
return err
}
if p.isMixed {
2023-03-13 03:31:36 +00:00
err = shell.Exec("networksetup", "-setsocksfirewallproxystate", interfaceDisplayName, "off").Attach().Run()
2022-08-04 14:01:20 +00:00
}
if err == nil {
2023-03-13 03:31:36 +00:00
err = shell.Exec("networksetup", "-setwebproxystate", interfaceDisplayName, "off").Attach().Run()
2022-08-04 14:01:20 +00:00
}
if err == nil {
2023-03-13 03:31:36 +00:00
err = shell.Exec("networksetup", "-setsecurewebproxystate", interfaceDisplayName, "off").Attach().Run()
2022-08-04 14:01:20 +00:00
}
return err
}
func getInterfaceDisplayName(name string) (string, error) {
2023-03-13 03:31:36 +00:00
content, err := shell.Exec("networksetup", "-listallhardwareports").ReadOutput()
2022-08-04 14:01:20 +00:00
if err != nil {
return "", err
}
for _, deviceSpan := range strings.Split(string(content), "Ethernet Address") {
if strings.Contains(deviceSpan, "Device: "+name) {
substr := "Hardware Port: "
deviceSpan = deviceSpan[strings.Index(deviceSpan, substr)+len(substr):]
deviceSpan = deviceSpan[:strings.Index(deviceSpan, "\n")]
return deviceSpan, nil
}
}
return "", E.New(name, " not found in networksetup -listallhardwareports")
}
func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
interfaceMonitor := router.InterfaceMonitor()
if interfaceMonitor == nil {
return nil, E.New("missing interface monitor")
}
proxy := &systemProxy{
monitor: interfaceMonitor,
port: port,
isMixed: isMixed,
}
2023-07-23 06:42:19 +00:00
proxy.update(tun.EventInterfaceUpdate)
2022-08-04 14:01:20 +00:00
proxy.element = interfaceMonitor.RegisterCallback(proxy.update)
return func() error {
interfaceMonitor.UnregisterCallback(proxy.element)
return proxy.unset()
}, nil
}